Redis 缓存数据库
[TOC]
前言
缓存数据库是一种位于应用程序与主要后端数据库之间的中间层,用于提高数据访问速度的技术。

以下是一些关于缓存数据库的详细介绍:
- 作用:缓存数据库主要用于存储那些
频繁访问或计算成本较高的数据副本。这些数据通常被放置在高速、低延迟的存储介质上,如内存中,以便快速访问。加快访问速度 ,缓解关系型数据库的读压力。 - 使用场景:当应用程序需要数据时,首先会从
缓存中查询。如果所需数据在缓存中存在,则可以直接获取,从而避免了直接访问主数据库的步骤,这可以显著减少数据检索的时间,并减轻主数据库的负载。 - 常见类型:
Redis:它是一种非关系型(NoSQL)内存键值存储数据库,支持多种数据结构,包括字符串、哈希、列表等。Redis以其快速的读写能力和丰富的功能而闻名,适用于缓存、消息传递、会话存储等多种场景。- Memcached:同样是键值对形式的内存缓存系统,设计相对简单,主要用于缓存常用数据,特别适应于分布式环境中的数据缓存需求。
- 优势:缓存数据库的使用可以减少数据库的
读取次数,加快数据的处理速度,改善用户体验,并在高流量环境下保持系统的响应性和稳定性。
注意事项:缓存数据库固然提供了许多好处,但也要注意数据一致性和缓存失效的问题。必须确保在适当的时候更新或清除缓存,以避免过时或错误的数据被使用。
1、简介
NoSQL产品: Redis、MongoDB、Memcached
- MongoDB:
- 基于文档的数据存储:MongoDB使用BSON(类似JSON)格式存储数据,这使得数据结构灵活且易于扩展。
NOSQL名词解释:非关系型数据库;通常是以键值对的方式存储数据(Key-Value)的形式。
2、NoSQL的优点/缺点
优点:
- 数据模型灵活性
- NoSQL数据库不需要
预先定义表结构,可以根据实际需求动态调整数据类型。
- NoSQL数据库不需要
- 高可扩展性
- NoSQL数据库采用
分布式架构,可以通过水平扩展来处理大规模数据和高并发读写。通过在集群中添加更多的节点,可以提高数据库的性能和容量。这种高可扩展性使得NoSQL数据库适用于大规模数据处理和高并发场景,可以满足业务的快速增长需求。
- NoSQL数据库采用
- 高性能
- NoSQL数据库通常采用
内存存储,以及并行计算和分布式计算技术,可以提供高性能的数据存储和查询能力。在对数据进行读取和写入操作时,NoSQL数据库可以快速响应,提供低延迟的数据访问。
- NoSQL数据库通常采用
缺点:
一致性问题- NoSQL数据库通常采用最终一致性的策略,即在一段时间内达到一致状态,可以容忍一定的数据不一致性。在数据更新和复制过程中,可能会出现数据不一致的情况。
- 查询能力限制
- NoSQL数据库的查询能力相对较弱,通常只支持基本的查询操作。与传统关系型数据库相比,NoSQL数据库缺少复杂的查询操作和聚合函数。在需要进行复杂的数据查询和分析的场景中,NoSQL数据库的查询能力可能无法满足需求。
- 缺乏标准化
- NoSQL数据库的种类繁多,没有一个统一的标准化规范。不同的NoSQL数据库具有不同的查询语言。
3、关系型数据库与非关系型数据库的区别:———面试高频率问题
1 | 1.首先了解一下 什么是关系型数据库? |
2、Memcached
2.1 特点
分布式缓存
Memcached是一个分布式的缓存系统,可以将数据存储在多个服务器上,从而提供更高的可用性和可扩展性。内存存储
Memcached将缓存数据存储在内存中,因此读取速度非常快,适用于需要快速访问的数据。由于数据存储在内存中,读取速度非常快,适用于缓存热点数据。但是服务器重启后,数据会丢失。- 键值存储
Memcached采用键值对存储数据,通过键(key)快速定位和检索数据值(value)。 - 自动过期
缓存数据可以设置过期时间,过期后自动从缓存中移除,避免数据过时或脏数据的问题。 缓存逐出策略
当内存不足时,Memcached会根据一定的策略逐出部分数据,为新数据腾出空间。

2.2 服务框架

原理
1、检查客户端的请求数据是否在memcached中,如有,直接把请求2数据返回,不再对数据库进行任何操作,路径操作为①②③⑦。
2、如果请求的数据不在memcached中,就去查数据库,把从数据库中获取的数据返回给客户端,同时把数据缓存一份到memcached中(memcached客户端不负责,需要程序明确实现),路径操作为①②④⑤⑦⑥。
3、保持缓存的新鲜性,每当数据发生变化的时候(比如,数据有被修改,或被删除的情况下),要同步更新的缓存信息,确保用户不会在缓存取到旧的数据。
2.3 配置安装Memcached
memcache能存放多少数据,取决于服务器本身的内存有多大。
1 | 1.安装----准备一台服务器 |
1 | >>> 安装nginx |

3、Redis服务
3.1 介绍
redis是一个开源的、使用C语言编写的、支持网络交互的、可基于内存也可持久化的Key-Value数据库,它支持多种数据结构,如字符串(strings)、散列(hashes)、列表

redis的官网:www.redis.io
3.1.1 redis的特点:
- 高性能:由于数据存储在内存中,Redis能够实现
微秒级的读写速度。 - 持久化:虽然数据主要
存储在内存中,但Redis提供了数据持久化的功能,可以将内存中的数据定期保存到磁盘中,以防止数据丢失。 - 支持丰富数据类型:除了基本的键值对存储,Redis还支持列表、集合、有序集合等多种数据结构,这使得它能够适应更多样的应用场景。
- 原子性操作:Redis的所有操作都是
原子性的,这意味着每一个操作都将完整地执行,不会被其他客户端的命令所干扰,确保了数据的一致性和完整性。
3.1.2 Redis和memcached区别(面试题)
- 数据结构:Redis提供了更丰富的数据类型,包括
字符串、列表、集合、有序集合和散列等,而Memcached主要支持简单的键值对结构。这使得Redis能够支持更复杂的数据操作,减少网络IO次数和数据体积。 - 数据持久化:Memcached不支持数据
持久化,服务器重启后数据会丢失,但这使得它在运行时拥有更高的性能。相比之下,Redis支持数据持久化到磁盘,提供了数据的恢复能力,但这也意味着它需要承担额外的性能开销。 - 性能考虑:Memcached在存储大数据时性能更高,因为它的
内存管理机制简单高效。而Redis虽然在处理大量数据时性能有所下降,但它提供了更多的数据结构和操作。 - 应用场景:Memcached通常用于
缓存系统中,以减轻数据库的读负载,适合多读少写的场景。而Redis不仅适用于缓存,还适用于对读写效率要求高、数据处理复杂和对安全性要求较高的系统。

4、安装Redis
4.1 安装单机版redis
1 | >>> 下载redis安装包 |

1 | >>> 登陆redis |
1 | #>>> 切换数据库 |
4.2 redis的相关工具
1 | ./redis-cli # redis的客户端 |
5、Redis设置密码的两种方式
Redis修改密码的方式主要有两种:使用redis-cli命令行工具和通过配置文件。
5.1 命令行临时修改密码
- 登录Redis:首先,你需要使用当前没有密码的Redis客户端登录到Redis服务器。
- 设置新密码:使用
CONFIG SET命令来设置新的密码。例如,要设置密码为qfyyds,你可以执行:
1 | 127.0.0.1:6379> CONFIG SET requirepass "qfyyds" |
注意:这种方式设置的密码只会
临时生效,重启Redis服务后密码会失效。
5.2 配置文件永久修改密码
- 找到Redis配置文件:通常,Redis的配置文件名为
redis.conf,它位于Redis安装目录或数据目录中。 - 编辑配置文件:编辑
redis.conf。 - 设置密码:在配置文件中找到
# requirepass foobared这一行(没有#注释符号),将foobared替换为你想要设置的新密码。例如,设置为afyyds:
1 | [root@localhost redis]# vim redis.conf |
保存并重启Redis:保存配置文件并重启Redis服务,新的密码设置就会生效。
注意事项:在修改密码后,确保所有客户端都已更新为使用新密码进行
连接,否则可能会出现认证失败的问题。
5.3 Redis配置文件详解
1 | [root@localhost redis]# egrep -v "^#|^$" redis.conf |
6、数据持久化
Redis是一个内存数据库,一旦断电或服务器进程退出,内存数据库中的数据将全部丢失,所以需要redis持久化;Redis持久化就是把数据保存在磁盘上,利用永久性存储介质将数据保存,在特定的时间将保存的数据进行恢复的工作机制。
6.1 redis持久化 – 两种方式
6.1.1 RDB
在指定的时间间隔内将内存中的数据集写入磁盘,也就是快照(Snapshot),数据恢复是将快照文件直接读到内存中redis会单独创建(fork)一个子进程来进行持久化,会先将数据写入一个到一个临时文件(dump.rdb)中,待持久化过程结束后,再用本次的临时文件替换上次持久化后的文件。
fork函数的作用是复制一个与当前进程一样的进程,新进程的所有数据数值都和原进程一致,但是一个全新的进程,并作为原进程的子进程。
redis服务器在处理bgsave采用子线程进行IO写入,而主进程仍然可以接收其他请求,但创建子进程是同步阻塞的,此时不接受其他请求。

save: 该命令会阻塞当前redis服务器,执行save命令期间,redis不能处理其他命令,直到RDB过程结束为止(会造成长时间阻塞,不建议使用)
bgsave:该命令执行后,redis会在后台异步进行快照操作,快照同时还可以响应客户端的请求,阻塞只发生在fork阶段,基本上redis内部的所有RDB操作都是采用bgsave命令。
1. RDB持久化配置
RDB持久化默认开启,但是需要配置触发规则。如下列代码所示:
1 | [root@redis-master redis]# vim /usr/local/redis/redis.conf |
2. RDB持久化数据恢复
将备份文件(dump.rdb)移动到redis路径下(可以配置文件的存放路径)启动服务即可,redis启动会将文件数据加载到内存,在此期间redis会处于阻塞状态,直到全部数据存入内存。
3. RDB持久化的优缺点
优点:
数据恢复快;
体积小;
数据备份使用子进程,对redis服务性能影响小。
缺点:
- 在一定时间间隔进行备份,当redis意外宕机,将会丢失最后一次修改的数据,无法做到秒级持久化;
- fork进程时,会占用一定的内存空间;
- RDB文件是二进制的没有可读性。
6.1.2 AOF
将客户端的每一个写操作命令以日志的形式记录下来,追加到appendonly.aof的文件末尾,在redis服务器重启时,会加载aof文件中的所有命令,来达到数据恢复的目的。
当有写命令请求时,会追加到AOF缓冲区内,AOF缓冲区根据AOF持久化策略[always,everysec,no]将操作同步到磁盘的AOF文件中,当AOF文件大小超过重写策略或手动重写时,会对AOF文件进行重写来压缩AOF文件容量,redis服务重启时,会重新加载AOF文件中的写操作来进行数据恢复。
1. AOF持久化策略
always: 把每个写命令立即同步到AOF文件,很慢但安全;everysec: 每秒同步一次,默认配置;no: redis不执行写入磁盘。
2. AOF的触发方式
- 手动触发
bgrewriteaof
1 | 127.0.0.1:6379> BGREWRITEAOF |
默认情况,redis是没有开启AOF(默认使用RDB持久化),需要通过配置文件开启。
1 | #>>> 是否开启 Redis AOF持久化,默认为no |
- Always:每次执行
写入操作后,都会立即调用fsync将数据同步到磁盘。这确保了极高的数据持久性,因为即使在系统崩溃的情况下,也最多只会丢失一次写入操作的数据。然而,这种模式会对性能产生较大影响,因为在每次写入后都进行fsync会导致较高的I/O开销。 - Everysec:这是默认设置,
每秒执行一次fsync。它在性能和持久性之间取得了平衡,既保证了较好的数据安全性,又避免了频繁的I/O操作对性能的影响。 - No:不做持久化
3. AOF的重写机制
AOF持久化,会把每次写命令都追加到appendonly.aof文件中,当文件过大,redis的数据恢复时间就会变长,因此加入重写策略对aof文件进行重写,生成一个恢复当前数据的最少命令集。通过压缩AOF文件里面的相同指令保留最新的一个数据操作指令,即将存储了某个key的多次变更记录。只是存储最新的变更记录即可,丢弃历史变更记录 。

1 | # Redis 重写机制配置 |
- auto-aof-rewrite-percentage:当前 AOF 文件大小超过上次重写后 AOF 文件大小的百分比时,触发 AOF 重写机制,默认值为 100 。
- auto-aof-rewrite-min-size:表示当当前 AOF 文件大小超过指定值时,才可能触发 AOF 重写机制,默认值为 64 MB 。
- 系统自动触发 AOF 重写机制还需要满足以下条件 :
当前没有正在执行 BGSAVE 或 BGREWRITEAOF 的子进程当前没有正在执行 SAVE 的主进程当前没有正在进行集群切换或故障转移
3.1 Redis AOF 重写机制原理
Redis AOF(Append Only File)重写流程是一个用于优化和压缩AOF文件的过程,以减少存储空间和提高写入效率。以下是AOF重写的流程:
触发条件:当满足一定条件时,Redis会自动触发AOF重写。常见的触发条件包括
文件大小超过阈值、系统负载较低等。创建子进程:
Redis启动一个子进程进行AOF重写操作。这个子进程与主进程并行运行,不会阻塞主进程的处理。遍历数据库:
子进程开始遍历Redis数据库中的所有键值对。这个过程中,子进程会记录下每个键值对的操作命令,但不会执行这些命令。生成重写缓冲区:在遍历数据库的过程中,
子进程会将记录的操作命令写入一个临时文件,即重写缓冲区。这个临时文件最终会成为新的AOF文件。同步命令到主进程:
在重写过程中,子进程会将部分命令同步回主进程,以确保主进程和子进程的数据一致性。这是通过Redis的内部机制实现的,确保在重写过程中主进程的数据不会被破坏。重写AOF文件:当子进程遍历完整个数据库并生成重写缓冲区后,它会根据一定的规则对缓冲区中的命令进行优化和压缩,生成新的AOF文件。这个
新文件会替换原有的AOF文件,具有更小的体积和更高的写入效率。更新配置:
一旦新的AOF文件生成并替换原有的文件,Redis会更新其配置信息,将新的AOF文件名写入配置文件中。这样,在下次启动时,Redis就会使用新的AOF文件作为持久化存储。AOF重写机制带来优点
通过AOF重写流程,Redis可以有效地优化和压缩AOF文件,减少存储空间的使用,并提高写入效率。同时,由于重写过程是在子进程中进行的,不会阻塞主进程的处理,因此对Redis的性能影响较小。
白话文解释:
- 旧AOF文件过大触发重写机制
- 创建子进程构建一个新的aof文件
- 子进程读取当前redis里面的数据,写入到新的aof文件里面
- 读取redis数据期间,主进程如果有其他新的操作指令则写入重写缓存中
- 重写完成以后,将重写缓存追加到新的aof文件中
- 用新的aof文件覆盖现有的aof文件
4. AOF的优点和缺点
优点:
数据安全性高,不易丢数据;
AOF文件有序保存了所有写操作,可读性强。
缺点:
AOF方式生成文件体积大;
数据恢复速度比RDB慢。
持久化配置
1 | 3、AOF默认关闭--开启 |

1 | 1、此选项为aof功能的开关,默认为“no”,可以通过“yes”来开启aof功能,只有在“yes”下,aof重写/文件同步等特性才会生效 |
开启持久化功能后,重启redis后,数据会自动通过持久化文件恢复。RDB是默认持久化方式,但 Redis 允许 RDB 与 AOF 两种持久化技术同时开启。不过如果同时存在两种持久化方式,会默认采取AOF的方式,AOF持久化方式的优先级更高。
拓展RDB快照备份恢复:
redis数据库备份与恢复(dump.rdb快照方式),两台机器
备份Redis实例配置
- 备份redis实例操作
1 | #>>> 备份机器的redis.conf配置文件内容 |
- 恢复Redis实例配置
1 | #>>> 配置文件修改 |
7、Redis主从配置
7.1 主从简介
持久化技术只是解决了Redis服务故障之后,快速数据恢复的问题。宕机和数据恢复的过程中整个业务系统来说,还是有损失的,并没有根本上提升可用性问题,而且持久化技术对于Redis服务性能来说是有损的。我们需要的是保障Redis的高可用,减少甚至避免Redis服务发生宕机的可能。
目前实现Redis高可用的模式主要有三种: 主从模式、哨兵模式、集群模式。我们先来聊一下主从模式。
Redis 提供的主从模式,是通过复制的方式,将主服务器上的Redis的数据同步复制一份到从 Redis 服务器,这种做法很常见,MySQL通过binlog进行的主从复制也是这么做的。
主节点的Redis我们称之为master,从节点的Redis我们称之为slave,主从复制为单向复制,只能由主到从,不能由从到主。可以有多个从节点,比如1主3从甚至n从,从节点的多少根据实际的业务需求来判断。
主从结构,一是为了纯粹的冗余备份,二是为了提升读性能,比如很消耗性能的操作就可以由从服务器来处理。
redis的主从同步是异步进行的,这意味着主从同步不会影响主逻辑,也不会降低redis的处理性能。主从架构中,可以考虑关闭主服务器的数据持久化功能,只让从服务器进行持久化,这样可以提高主服务器的处理性能。
7.2 主从复制的意义
故障隔离和恢复
无论主节点或者从节点
宕机,其他节点依然可以保证服务的正常运行,并可以手动或自动切换主从。- 如果Slave库故障,则读写操作全部走到Master库中
- 如果Master库故障,则将Slave转成Master库,仅丢失Master库来不及同步到Slave的小部分数据
读写隔离:Master 节点提供写服务,Slave 节点提供读服务,分摊流量压力,均衡流量的负载。
提供高可用保障:主从模式是高可用的最基础版本,也是
sentinel 哨兵模式和cluster 集群模式实施的前置条件。
7.3 主从同步原理偏移
- 从服务器会向主服务器发出
SYNC指令; - 当主服务器接到此命令后,就会调用
BGSAVE指令来fork一个子进程专门进行数据持久化工作,也就是将主服务器的数据写入RDB文件中。在数据持久化期间,主服务器将执行的写指令都缓存在内存中; - 在BGSAVE指令执行完成后,主服务器会将持久化好的RDB文件发送给从服务器,
- 从服务器接到此文件后会将其存储到磁盘上,然后再将其读取到内存中。
- 这个动作完成后,主服务器会将这段时间缓存的写指令再以redis协议的格式发送给从服务器。
另外,要说的一点是,即使有多个从服务器同时发来SYNC指令,主服务器也只会执行一次BGSAVE,然后把持久化好的RDB文件发给多个从服务器。
2.8版本之后,redis支持了效率更高的增量同步策略,这大大降低了连接断开的恢复成本。主服务器会在内存中维护一个缓冲区,缓冲区中存储着将要发给从服务器的内容。从服务器在与主服务器出现网络瞬断之后,从服务器会尝试再次与主服务器连接,一旦连接成功,主服务器就会向从服务器发送增量内容。增量同步功能,需要服务器端支持全新的PSYNC指令。这个指令,只有在redis-2.8之后才具有。
扩展内容:
1. 首次配置完成主从库之后的全量复制:在从库第一次连接到主库时,将采用psync复制方式进行全量复制。 这意味着从库会从头开始复制主库中的全部数据。
2. 主从正常运行期间,准实时同步:在正常运行状态下,从库通过读取主库的缓冲区来进行增量复制。 这个过程涉及复制主库上发生的新的数据变更。
3. 从库第二次启动(异常或主从网络断开后恢复): Append增量数据 + 准实时同步将通过读取主库的缓冲区进行部分复制。 这种方式能够快速同步中断期间发生的数据变更,而不会对主库造成重大影响。
PSYNC 命令是Redis中用于从节点与主节点之间数据同步的关键命令。它的工作原理包括以下几个步骤:
1. 启动或重连判断:
当从节点(Slave)启动或与主节点(Master)的连接断开后重连时,从节点需要确定是否曾经同步过。如果从节点没有保存任何主节点的运行ID(runid),它将视为第一次连接到主节点。
2. 首次同步处理:
如果是第一次同步的情况下,从节点会发送 PSYNC -1 命令给主节点,代表请求全量数据同步。 全量同步是指主节点将其所有数据完整地Copy一份给从节点。
3. 主从重连后的处理:
对于之前已经同步过的从节点,它会发送 PSYNC runid offset 命令,其中runid是主节点的唯一标识符,offset是从节点上次同步数据的偏移量。这样本质就是增量同步。
4. 主节点响应:
主节点接收到PSYNC命令后,会检查runid是否匹配,以及offset是否在复制积压缓冲区的范围内。如果匹配且offset有效,主节点将回复CONTINUE,并发送自从节点上次断开连接以来的所有写命令。
5. 触发全量同步的条件:
如果runid不匹配,或offset超出了积压缓冲区的范围,主节点将通知从节点执行全量同步,回复FULLRESYNC runid offset。
6. 积压缓冲区的作用:
主节点会在处理写命令的同时,将这些命令存入复制积压队列(缓冲池),同时记录队列中存放命令的全局offset。
这样做法是保证了效率。当从节点断线重连,且条件允许时(runid和offset都具备),它可以通过offset从积压队列中进行增量复制,而不是全量复制,这样复制的成本就低很多。
7. 保障数据一致性:
PSYNC机制允许从节点在网络不稳定或其他意外断开连接的情况下,能够以增量方式重新同步数据。这也是它的一大优势,那就是保持主从节点数据的一致性。
8. 什么时候启动重连工作
判断是否进行全量同步,需要考虑两个关键因素:首先,确认这是否是第一次进行数据同步;其次,检查缓存区是否已经达到或超过其容量上限。只有在是第一次同步,或者缓存区已溢出的情况下,才会执行全量同步。
7.4 1主n从的同步说明
如果你有多个从库,则在每次连接的时候需要注意一些细节,如下:
多个从库情况下,每个从库都会记录自己的
slave_repl_offset,各自复制的进度也不相同。重连主库进行恢复时,从库会通过
psync命令将 slave_repl_offset 告知主库,主库判断从库的状态,来决定进行增量复制,还是全量复制。replication buffer(复制缓冲区) 和 repl_backlog 的说明
replication buffer: 与每个从节点(slave)相关联的缓冲区,存在于主节点(master)上。当主从连接稳定时,主节点会将其接收到的所有写命令放入这个缓冲区中,并异步地发送给从节点。这样,从节点就可以通过执行这些写命令来更新自己的数据集。可以通过client-output-buffer-limit配置来设定其大小限制,以防止因从节点处理速度慢而导致主节点内存溢出。

repl_backlog_buffer:是为了解决从库断连后找不到主从差异数据而设立的环形缓冲区,从而避免全量同步带来的性能开销。在redis.conf配置文件中可以设置大小,如果从库断开时间过长,repl_backlog_buffer环形缓冲区会被主库的写命令覆盖,那么从库重连后只能全量同步,所以repl_backlog_size配置尽量大一点可以降低从库连接后全量同步的频率。

主库和从库会各自记录自己的复制进度,所以,不同的从库在进行恢复时,需要将自己的复制进度(slave_repl_offset)发给主库,主库才可以按照偏移量取数据跟它同步。
7.5 部署三台机器Redis—主从同步
- 集群环境准备
1 | >>> 三台服务器关闭防火墙 |
redis-master节点配置
1 | >>> 修改配置文件 |
关闭protected-mode模式,此时外部网络可以直接访问
开启protected-mode保护模式,需配置bind ip或者设置访问密码
redis-slave01配置
1 | >>> 修改配置文件 |
可以通过
replicaof(Redis 5.0 之前使用 slaveof)命令形成主库和从库的关系。
redis-slave02配置
1 | >>> 修改配置文件 |
- 测试主从复制
1 | >>> redis-master执行 |
注意:从服务器一般默认禁止写入操作:slave-read-only yes
redis-master执行info repliaction参数解释

1 | # 表示当前节点的角色是主节点 |
redis-slave执行info replication参数解释

1 | slave 节点执行 info replication 命令回显参数解释 |
7.6 主从同步保证数据一致性
为了保证主服务器Redis的数据和从服务器Redis的数据的一致性,也为了分担访问压力,均衡负载,应用层面一般采取读写分离的模式。读操作:主、从库都可以执行,一般是在从库上读数据,对实时性和准确性有100%高真要求的部分业务,在谨慎评估之后也可以读主库,前提是不能给Master带来高压力和风险。写操作:只在主库上写数据,写完之后将写操作指令同步到从库。
7.7 总结
- 主从复制的作用一个是为分担读写压力,均衡负载,另一个是为了保证部分实例宕机之后服务的持续可用性,所以Redis演变出主从架构和读写分离。
- 主从复制的步骤包括:建立连接的阶段、数据同步的阶段、基于长连接的命令传播阶段。
- 数据同步可以分为
全量复制和部分复制,全量复制一般为第一次全量或者长时间主从连接断开。 - 主从模式是比较低级的可用性优化,要做到故障自动转移,异常预警,高保活,还需要更为复杂的哨兵或者集群模式,这个后面我们继续介绍。
8、Redis-sentinel—哨兵模式

8.1 哨兵简介:Redis Sentinel
Sentinel(哨兵)进程是用于监控redis集群中Master主服务器工作的状态,在Master主服务器发生故障的时候,可以实现Master和Slave服务器的切换,保证系统的高可用。
哨兵(Sentinel) 是一个分布式系统,你可以在一个架构中运行多个哨兵(sentinel) 进程,这些进程使用流言协议来接收关于Master主服务器是否下线的信息,并使用投票协议来决定是否执行自动故障迁移,以及选择哪个Slave作为新的Master。
流言协议:
流言协议是一种去中心化的信息传播方式,其工作原理类似于人们在日常生活中传播流言:每个节点都将自己所知的信息告诉给它所连接的其他节点,这些节点再将信息传播给它们所连接的节点,以此类推,直到所有节点都获得了这条信息。
1、Redis哨兵集群的角色划分
- 主节点(Master): 处理客户端的读写请求。
- 从节点(Slave): 复制主节点的数据,用于提供读取服务和备份。
- 哨兵节点(Sentinel): 监控集群中各节点的健康状态,负责选举和故障转移。
2、作用
监控(Monitoring): 哨兵(sentinel) 会不断地检查你的Master和Slave是否运作正常。- 提醒(Notification):当被 监控的某个Redis节点出现问题时, 哨兵(sentinel) 可以通过 API 向管理员或者其他应用程序发送通知。
- 自动故障迁移(Automatic failover):当一个Master不能正常工作时,哨兵(sentinel) 会开始一次自动故障迁移操作,它会将失效Master的其中一个Slave升级为新的Master, 并让失效Master的其他Slave改为复制新的Master;当客户端试图连接失效的Master时,集群也会向客户端返回新Master的地址,使得集群可以使用现在的Master替换失效Master。
哨兵之间如何通信

哨兵实例之间可以相互发现,要归功于 Redis 提供的 pub/sub 机制,也就是发布 / 订阅机制。
哨兵只要和主库建立起了连接,就可以在主库上发布消息了,比如说发布它自己的连接信息(IP 和端口)。同时,它也可以从主库上订阅消息,获得其他哨兵发布的连接信息。当多个哨兵实例都在主库上做了发布和订阅操作后,它们之间就能知道彼此的 IP 地址和端口。
为了区分不同应用的消息,Redis 会以频道的形式,对这些消息进行分门别类的管理。所谓的频道,实际上就是消息的类别。当消息类别相同时,它们就属于同一个频道。反之,就属于不同的频道。只有订阅了同一个频道的应用,才能通过发布的消息进行信息交换。
在主从集群中,主库上有一个名为“sentinel:hello”的频道,不同哨兵就是通过它来相互发现,实现互相通信的。
在上图图中,哨兵 1 把自己的 IP(172.16.19.3)和端口(26579)发布到“sentinel:hello”频道上,哨兵 2 和 3 订阅了该频道。那么此时,哨兵 2 和 3 就可以从这个频道直接获取哨兵 1 的 IP 地址和端口号。
然后,哨兵 2、3 可以和哨兵 1 建立网络连接。通过这个方式,哨兵 2 和 3 也可以建立网络连接,这样一来,哨兵集群就形成了。它们相互间可以通过网络连接进行通信,比如说对主库有没有下线这件事儿进行判断和协商。
哨兵如何知道从库的ip地址和端口呢?

由哨兵向主库发送 INFO 命令来完成的。就像上图所示,哨兵 2 给主库发送 INFO 命令,主库接受到这个命令后,就会把从库列表返回给哨兵。接着,哨兵就可以根据从库列表中的连接信息,和每个从库建立连接,并在这个连接上持续地对从库进行监控。哨兵 1 和 3 可以通过相同的方法和从库建立连接。
3、工作模式
- 每个Sentinel(哨兵)进程以每秒钟一次的频率向整个集群中的Master主服务器,Slave从服务器以及其他Sentinel(哨兵)进程发送一个 PING 命令。并通过实例返回的结果来判断实例是否在线。
- 如果一个实例(instance)距离最后一次有效回复 PING 命令的时间超过
down-after-milliseconds选项所指定的值, 则这个实例会被 Sentinel(哨兵)进程标记为主观下线(SDOWN)。 - 如果一个Master主服务器被标记为主观下线(SDOWN),则正在监视这个Master主服务器的所有 Sentinel(哨兵)进程要以每秒一次的频率确认Master主服务器的确进入了主观下线状态。
- 当有足够数量的 Sentinel(哨兵)进程(大于等于配置文件指定的值)在指定的时间范围内确认Master主服务器进入了主观下线状态(SDOWN), 则Master主服务器会被标记为客观下线(ODOWN)。
- 在一般情况下, 每个 Sentinel(哨兵)进程会以每 10 秒一次的频率向集群中的所有Master主服务器、Slave从服务器发送 INFO 命令。
- 当Master主服务器被 Sentinel(哨兵)进程标记为客观下线(ODOWN)时,Sentinel(哨兵)进程向下线的 Master主服务器的所有 Slave从服务器发送 INFO 命令的频率会从 10 秒一次改为每秒一次。
- 若没有足够数量的 Sentinel(哨兵)进程同意 Master主服务器下线, Master主服务器的客观下线操作就会被移除。若 Master主服务器重新向 Sentinel(哨兵)进程发送 PING 命令返回有效回复,Master主服务器的主观下线状态就会被移除。
4、主观下线和客观下线
主观下线:Subjectively Down,简称 SDOWN,指的是当前一个Sentinel 实例对某个redis服务器做出的下线判断。
客观下线:Objectively Down, 简称ODOWN,指的是多个 Sentinel 实例在对Master Server做出 SDOWN 判断,并且通过SENTINEL is-master-down-by-addr 命令互相交流之后,得出的Master Server下线判断,然后开启failover/故障转移
5、配置哨兵模式
- 每台机器上修改redis主配置文件
redis.conf文件设置:bind 0.0.0.0 - 每台机器上修改
sentinel.conf配置文件:修改如下配置
1 | [root@redis-master ~]# cd /usr/local/redis/ |
参数解释:
sentinel down-after-milliseconds mymaster 3000: 当集群中有2个sentinel认为master死了时,才能真正认为该master已经不可用了。 (slave上面写的是master的ip,master写自己ip)
sentinel down-after-milliseconds mymaster 3000: 表示如果名为
mymaster的主节点在3秒(3000毫秒)内未对 Sentinel 的 PING 命令做出有效响应,那么 Sentinel 会开始考虑该主节点可能已经出现故障,并做好相应的故障转移准备。
sentinel failover-timeout mymaster 10000: 表示在进行名为
mymaster的主节点的故障转移操作时,Sentinel 最多允许花费10秒(10000毫秒)的时间来完成整个操作。
protected-mode no: 关闭加密保护模式

将master的哨兵模式退出(Crtl+c),再将redis服务stop了,在两台slave上面查看其中一台是否切换为master:(没有优先级,为随机切换)
1 | ^C4854:signal-handler (1564349039) Received SIGINT scheduling shutdown... |
在slave机器上面查看:


6、Redis故障Master选举算法(了解)
- 优先级: 每个节点都有一个优先级,选择优先级最高的节点作为新的主节点。
- 复制偏移量: 选择复制偏移量最大的从节点,确保数据同步性。
- 运行ID: 选择运行ID最大的节点,确保节点唯一性。
1 | import redis.clients.jedis.Jedis; |
面试:
1 | redis有哪些优点 |
了解:
redis–快照
1 | 快照,主要涉及的是redis的RDB持久化相关的配置 |
安全:为redis加密:
1 | 可以要求redis客户端在向redis-server发送请求之前,先进行密码验证。当你的redis-server处于一个不太可信的网络环境中时,相信你会用上这个功能。由于redis性能非常高,所以每秒钟可以完成多达15万次的密码尝试,所以你最好设置一个足够复杂的密码,否则很容易被黑客破解。 |
修改了Redis的哨兵配置文件后,先把文件拷贝到从机再启动,否则会出现myid冲突的情况。
解决方法:将哨兵停掉,哨兵配置文件删除后,重新弄一份新的,然后再启动即可。
+slave :取消主观下线
-slave :标记为主观下线







