Redis架构安全
先学习:Redis架构简介-CSDN博客
Redis压测
Redis一般应用于高并发的场景,所以一定要对Redis的性能做压测。
Redis提供了压测脚本redis-benchmark,可以对Redis进行快速的基准测试。
# 20个线程,100W个请求,测试redis的set指令(写数据)
redis-benchmark -a 123qweasd -t set -n 1000000 -c 20
...
Summary:
throughput summary: 116536.53 requests per second ##平均每秒11w次写
latency summary (msec):
avg min p50 p95 p99 max
0.111 0.032 0.111 0.167 0.215 3.199
Redis数据持久化
持久化配置
Redis持久化相关的配置,可以分为几个策略:
- 无持久化:不保证数据安全,只将Redis当做缓存用
- RDB(RedisDatabase):按照一定的时间间隔缓存Redis所有的数据快照
- AOF(Append Only File):记录Redis收到的每一次写操作,在之前的基础上进行追加新的操作
- RDB+AOF:
RDB特点
- RDB文件紧凑,适合定期备份,非常适合灾难恢复
- 备份的是当前时间的内存的全部数据集。
- 主线程启动一个子线程进行RDB备份
- 数据备份时,需要将内存的数据克隆一份,如果数据量比较大,fork的子线程虽然不会阻塞redis主线程,但是会占用CPU, 容易造成Redis短暂的服务停用。
- 不能进行实时备份,丢失数据风险
AOF特点
- Redis默认1s进行一次AOF写入,数据更安全
- 以日志的形式记录每一次写操作,追加文件而不允许写文件
- AOF出现数据记录不完整的情况,可以使用redis-check-aof工具恢复
- AOF文件通常比RDB文件更大
- 写操作频繁的情况下,AOF的备份性能比RDB更慢
[root@192-168-65-214 appendonlydir]# redis-check-aof --fix appendonly.aof.1.incr.aof
混合持久策略(RDB+ AOF):
redis.conf配置文件中做配置
# Redis can create append-only base files in either RDB or AOF formats. Using
# the RDB format is always faster and more efficient, and disabling it is only
# supported for backward compatibility purposes.
aof-use-rdb-preamble yes
RDB
文件名默认dump.rdb。
RDB同步(何时触发RDB备份)
1.手动触发
- save命令:备份期间阻塞主线程
- bgsave命令:fork出一个子线程执行持久化,主线程在fork子线程的过程有短暂的阻塞,但是会占用更多的cpu和内存
2. 自动触发
- 达到配置文件的配置要求。 配置文件中,save m n : 在m秒有n个键发生改变,自动触发持久化,如果设置多个,只要满足其中一个条件就会触发。配置文件中可以修改。
- flushall : 用于清空redis所有的数据库,flushdb清空redis所在数据库(默认0号数据库),会清空RDB文件,同时也会生成dump.rdb, 内容为空。
- 主从同步(看Redis版本):全量同步时自动触发bgsave命令,生成rdb发送给从节点。
配置文件(备份策略)
# Save the DB to disk.
# save <seconds> <changes> [<seconds> <changes> ...]
# save ""
# Unless specified otherwise, by default Redis will save the DB:
# * After 3600 seconds (an hour) if at least 1 change was performed
# * After 300 seconds (5 minutes) if at least 100 changes were performed
# * After 60 seconds if at least 10000 changes were performed
# You can set these explicitly by uncommenting the following line.
# save 3600 1 300 100 60 10000 -- 备份策略
- rdbcompression 是否启用RDB压缩,默认yes。 如果不想消耗CPU进行压缩,可以设置为no
- stop-writes-on-bgsave-error 默认yes;如果配置成no,表示你不在乎数据不一致或者有其他的手段发现和控制这种不一致, 在快照写入失败时,也能确保redis继续接受新的写入请求。
- rdbchecksum 默认yes。在存储快照后,还可以让redis使用CRC64算法来进行数据校样做会增加大约10%的性能消耗。如果希望获得最大的性能提升,可以关闭此功能。
RDB日志恢复
恢复指令:redis-check-rdb,因为rdb文件是二进制文件,所以不太容易篡改。
AOF
配置文件
# The base name of the append only file.
# Append-only file names are created by Redis following a specific pattern.
# The file name's prefix is based on the 'appendfilename' configuration
# parameter, followed by additional information about the sequence and type.
# For example, if appendfilename is set to appendonly.aof, the following file
# names could be derived:
# - appendonly.aof.1.base.rdb as a base file. -- rdb文件是二进制数据文件
# - appendonly.aof.1.incr.aof, appendonly.aof.2.incr.aof as incremental files. -- incr.aof是增量的操作日志
# - appendonly.aof.manifest as a manifest file. -- manifest文件信息元数据
appendfilename "appendonly.aof"
现在的AOF已经具备了RDB+AOF的功能。并且,拆分增量文件的方式,也能够进一步控制aof文件的大小。 虽然AOF具备了RDB的功能,但是因为AOF数据通常在不断变化,还是建议定期做RDB的备份。
配置:
- appendonly 是否开启aof。 默认是不开启的。
- appendSync同步方式, 默认1s同步一次
- appenddirname AOF文件目录
- auto-aof-rewrite-percentage, auto-aof-rewrite-min-size 文件触发重写策略。 默认每个文件64M,写到100%, 进行一次重写。
- no-appendfsync-on-rewrite aof重写期间是否同步
AOF文件内容
appendonly.aof.1.incr.aof增量文件。里面其实就是按照Redis的协议记录了每一次操作。
127.0.0.1:6379> keys *
(empty array)
127.0.0.1:6379> set k1 v1
OK
127.0.0.1:6379> set k2 v2
OK
这组指令的文件示例:

AOF同步过程
- 所有的命令追加到AOF缓冲区
- AOF缓冲区根据对应的同步策略(配置参数appendfSync)向硬盘进行同步操作
同步策略:
- 同步:每次修改同步
- 异步:每秒同步
- 不同步:由操作系统决定同步时机
AOF重写过程
Redis会定期对AOF中的操作进行优化重写,让AOF中的操作更加精简,在Redis7的AOF文件中,会生成base rdb和incr.aof文件。
AOF日志恢复
修复的过程实际上就是将aof文件(appendonly.aof.1.incr.aof日志文件)的最后那一条不完整的指令删除掉。使用redis-check-aof工具恢复.
主从复制Replica机制
配置方式
配从不配主原则
REPLICAOF host port|NO ONE : 一般配置到redis.conf中。
SLAVEOF host port|NO ONE: 在运行期间修改slave节点的信息。如果该服务已经是某个主库的从库了,那么就会停止和原master的同步关系。
-- 查看主从状态
127.0.0.1:6379> info replication
默认情况下,从库是只读的,不允许写入数据。因为数据只能从master往数据,就会造成数据不一致。但是从库没有禁止CONFIG、DEBUG等管理指令,这些指令如果和主节点不一致,还是容易造成数据不一致。
replica-read-only yes -- redis.conf中的配置
rename-command CONFIG "" 。 -- redis.conf中增加这个配置,屏蔽掉slave上的CONFIG指令。
复制时机
主从复制。当Master数据有变化时,自动将新的数据异步同步到其他slave中。
主从复制过程

哨兵机制Sentinel机制
配置方式
sentinel.conf

如何发现Master宕机
- S_DOWN(主观下线):通过心跳检测,一个Sentinel节点认为 Redis Master节点宕机了。
- O_DOWN(客观下线): 当一个Sentinel认为Redis Master宕机了,Redis的Sentinel就会互相进行沟通,当超过quorum(Sentinel集群的半数)个Sentinel节点都认为master已经出现S_DOWN后,就会将master标记为O_DOWN。
切换新Master过程
<1> master变成O_DOWN后,Sentinel集群Leader的节点负责协调整个故障切换过程。
<2>Sentinel会在剩余健康的Slave节点中选举出一个节点作为新的Master。选举采用采用的Raft算法, 选举的规则如下:
- 首先检查是否有提前配置的优先节点:各个服务节点的redis.conf中的replica-priority配置最低的从节点。这个配置的默认值是100。
- 如果配置都一样,检查复制偏移量offset最大的从节点。也就是找同步数据最快的slave节点。因为他的数据相对更全。
- 如果offset还是一样,最后按照slave的RunID字典顺序最小的节点。
<3>切换新的主节点。 Sentinel Leader给新的mater节点执行 slave of no one操作,将他提升为master节点。 然后给其他slave发送slave of 指令。让其他slave成为新Master的slave。
<4>如果旧的master恢复了,Sentinel Leader会让旧的master降级为slave,并从新的master上同步数据,恢复工作。
集群Cluster机制
配置方式
cluster-enabled yes -- 开启集群模式
cluster-config-file nodes-6379.conf -- 指定一个给集群进行修改的配置问文件
将多个独立的Redis服务整合成一个统一的集群:
--cluster create表示创建集群。
--cluster-replicas 表示为每个master创建一个slave节点。
接下来,Redis会自动分配主从关系,形成Redis集群。
[root@192-168-65-214 cluster]# redis-cli -a 123qweasd --cluster create --cluster-replicas 1 192.168.65.214:6381 192.168.65.214:6382 192.168.65.214:6383
192.168.65.214:6384 192.168.65.214:6385 192.168.65.214:6386
Redis在分配主从关系时,会优先将主节点和从节点分配在不同的机器上。
集群模式下的问题
1. 批量指令原子性问题
127.0.0.1:6381> mset k1 v1 k2 v2 k3 v3
(error) CROSSSLOT Keys in request don't hash to the same slot
不同的key对应到不同的槽位,分不到了不同的服务器,就出现分布式事务问题。
解决方案:
127.0.0.1:6381> CLUSTER KEYSLOT k1
(integer) 12706
127.0.0.1:6381> CLUSTER KEYSLOT roy{k1}
(integer) 12706
127.0.0.1:6381> CLUSTER KEYSLOT roy:k1
(integer) 12349
-- 使用相同的hash tag,能保证这些数据都是保存在同一个节点上的。
-- 如果key中有{}, 只根据{}中的内容计算槽位。
127.0.0.1:6381> mset user_{1}_name roy user_{1}_id 1 user_{1}_password 123
-> Redirected to slot [9842] located at 192.168.65.214:6382
OK
2. 数据倾斜
大量的数据被存储到集群中的某个热点Redis节点上
解决方案:
- 调整key的结构,尤其是那些访问频繁的热点key,让数据能够尽量平均的分配到各个slot上。
- 调整slot的分布,将那些数据量多,访问频繁的热点slot进行重新调配,让他们尽量平均的分配到不同的Redis节点上。
集群通信协议
Redis集群之间通过gossip协议进行频繁的通信,用于传递消息和更新节点状态。gossip协议包含多种消息,包括ping,pong,meet,fail等等。
gossip集群是去中心化的,各个节点彼此之间通过gossip协议互相通信,保证集群内部各个节点最终能够达成统一。
Redis集群中,每个节点都有一个专门用于节点之间进行gossip通信的端口,就是自己提供服务的端口+10000.因此,在部署Redis集群时,要注意防火墙配置,不要把这个端口屏蔽。
集群选举Master
当slave发现自己的master变为FAIL状态时,便尝试进行Failover,以期成为新的master。由于挂掉的master 可能会有多个slave,从而存在多个slave竞争成为master节点的过程, 其过程如下:
1》slave发现自己的master变为FAIL
2》将自己记录的集群currentEpoch加1,并广播FAILOVER_AUTH_REQUEST信息(currentEpoch代表选举周期)
3》其他节点收到该信息,只有master响应,判断请求者的合法性,并发送FAILOVER_AUTH_ACK,对每一个 epoch只发送一次ack(master应该根据特定的决定响应结果)
4》尝试Failover的slave收集master返回的FAILOVER_AUTH_ACK
5》slave收到超过半数master的ack后变成新Master
6》slave广播Pong消息通知其他集群节点
注意:slave节点并不是在master节点一进入 FAIL 状态就马上尝试发起选举,而是有一定延迟,确保mater FAIL状态在集群中传播,slave如果立即尝试选举,其它masters或许尚未意识到FAIL状态,可能会拒绝投票.
Redis数据不一致
Redis Cluster在设计上优先考虑一致性,但在特定场景下确实可能存在数据不一致的情况。
数据不一致原因
1. 脑裂问题(网络分区)
当集群出现网络分区时,可能会出现多个主节点都认为自己是某个槽位的主节点。
示例场景:
-
节点A、B、C在一个分区,节点D、E在另一个分区
-
如果多数节点(A、B、C)认为主节点D失效,它们会选举新的主节点
-
此时两个分区D和E都可能接受写操作,导致数据不一致
2. 异步复制导致的数据丢失
# 写操作流程:
1. 客户端向主节点写入数据
2. 主节点返回成功
3. 主节点异步复制到从节点 ← 此步骤延迟或失败可能导致数据丢失
3. 故障转移期间的写丢失
主节点故障后,从节点提升为主节点期间,可能丢失未复制的写操作。
4. 持久化失败导致数据不一致
持久化失败是导致数据不一致的原因,但往往与其他问题(如主从复制延迟或脑裂)共同作用导致数据不一致。
- 数据在内存中:当Redis实例(尤其是主节点)因故障(如断电、进程异常退出)重启时,内存中的数据会丢失。如果故障前没能成功将数据持久化到磁盘,那么这部分数据就彻底丢失了,从而造成数据不一致。
- 复制依赖持久化:在主从复制中,一个从节点如果要与主节点保持同步,在全量同步时,主节点会生成RDB快照(这本身是一个持久化过程)并发送给从节点。如果这个过程中断或失败,也会导致从节点数据不一致。
解决方案
1. 避免脑裂问题
1.1 多数派原则与故障检测
# 节点通过Gossip协议通信
# 需要大多数节点确认才会进行故障转移
CLUSTER NODES # 查看节点状态和纪元
1.2 合理集群规模
# 建议至少3主3从,避免2主2从(容易因网络分区产生脑裂)
# 节点数量最好是奇数,便于多数派决策
2. 配置参数优化
避免异步复制导致的数据丢失问题
# 关键配置项
min-replicas-to-write 1 # 至少1个从节点确认才接受写
min-replicas-max-lag 10 # 从节点延迟不超过10秒
cluster-node-timeout 15000 # 节点超时时间(毫秒)
3. 应用层保护
# 重要操作使用WAIT命令
r.set('important_key', 'value')
r.wait(1, 5000) # 等待至少1个副本确认,超时5秒
4. 监控告警
对Redis集群的节点状态、主从复制延迟、网络延迟、持久化状态等关键指标进行监控,以便及时发现问题。
# 关键监控指标
redis-cli cluster info | grep cluster_state
redis-cli info replication | grep connected_slaves
手动恢复策略
# 检查集群状态
redis-cli --cluster check 192.168.1.101:7001
# 修复槽位分配
redis-cli --cluster fix 192.168.1.101:7001
5. 持久化配置
- 启用合理的持久化机制
-
RDB自动生成策略
-
AOF同步策略appendfSync
-
RDB和AOF结合:这样可以利用RDB进行快速备份和恢复,同时利用AOF来保证更高的数据安全性。
-
-
建立定期备份计划:定期备份你的Redis数据都是至关重要的。可以编写脚本,定期执行
SAVE或BGSAVE命令(BGSAVE会在后台执行,不会阻塞服务器)来生成RDB文件的备份,并将备份文件传输到安全的地方(如不同的物理机或云存储)。
Redis Cluster通过多数派决策、故障转移机制、复制机制、持久化等手段,在大多数情况下能保证数据一致性。但在网络分区、节点故障、运维误操作等极端情况下,仍可能出现数据不一致。
更多推荐




所有评论(0)