redis 的高可用使用主从架构 哨兵 数据持久化的原理

redis 的集群架构:

使用redis cluster (多master + 读写分离 + 高可用)

如果你的数据很少, 主要用来承载高并发和高性能的场景,那就搭建一个replication 一个master 多个slave 要几个slave就是和你自己的吞吐量有关系,然后自己在搭建一个
sentinal 集群,去保证redis 主从架构的高可用性,就ok了

保证redis的高并发和高可用?

采用读写分离 master 是主的 slave 为从。

redis的主从架构 -> 读写分离 -> 可支持水平扩展的读高并发框架。

redis replication:
写请求到 master node 同在写入到所有的slave node的上


redis replication 的核心机制;

  1. 一个master node 可以配置多个slave node 的
  2. 采用的异步方式同步到slave node节点上的,不过从版本2.8开始。slave node会周期性的自己每次复制的数据量
  3. slave 也可以链接其他的slave
  4.  slave node 在做复制的时候,是不会block master node 的正常工作的
  5. slave node 在做复制的时候。 也不会block 对自己 查询 操作, 它只会用旧数据集提供服务。但是复制完成后,就会删除旧的数据集,加载新的数据集,这个时候会暂停对外服务了
  6.  slave node 主要用来做横向扩容来做读写分离, 扩容slave node 可以提高读的吞吐量


redis 在master 上做持久化的操作?

redis 提供了 RDB 和AOF 两种不同的操作持久化的方式。

RDB的优点:

与AOF方式相比, 通过RDB文件恢复数据比较快,

RDB文件非常紧凑,适合于数据备份
通过RDB进行的数据备份,由于使用子进程生成,所有对redis 服务器性能影响很小。


RDB 的缺点:

如果服务器宕机的haul,采用RDB的方式会曹成某个时间段数据丢失。比如我们设置的10分钟同步一次或者是五分钟达到1000次的写入就同步一次的话。那么如果还没有达到触发条件服务器就死机了。那么这个时间段的数据就会丢失

使用slave 命令 会造成服务器阻塞, 直接数据同步完成才能接收到后续请求。

使用bgsave 的命令 在forks子进程时。如果数据量太大。 forks的过程也会发生阻塞, 另外,forks 子进程会耗费内存。


redis 支持主从复制 断点续传、

redis 哨兵的介绍


集群监控 ,负责监控redis master 和slave 进程是否正常工作。
消息通知 ,如果某个reidis实力有故障,那么哨兵负责发送消息作为报警通知给管理员
故障转移 ,如果master node 挂点了。会自动转移到slave node上
配置中心 ,如果故障转移发生了,通知client 客户端新的master 地址

哨兵的核心:

哨兵至少需要3个实例,来保证自己的健壮性,
哨兵 + redis 主从的部署架构, 是不会保证数据零丢失的, 只能保证redis的集群的高可用性。
对于哨兵 + redis 主从这种的复杂的部署架构, 尽量在测试环境和生产环境,都进行充足的测试和演练


redis 集群脑裂出现数据丢失问题,

master node上出现了网络上问题。 没发和slave node 进行通信了。 然后slave node 认为master node 宕机了,就会通过哨兵选举出新的master node 在为 这个时候出现了两个master node 这就是脑裂。 然后客户端在往 旧的master node 中写的数据, 一段时间后,旧的master 通信恢复了。变成的slave node, 在此时。 新的master node 同步数据到 slave node 上。 客户端写的数据就丢失了。

解决的办法;

配置参数 min-slaves-to-write 3 和 min-slave-max-lag 10
要求有几个slave ,数据复制和同步的延迟都超过10秒,这个时候master 就不会在接受任何请求了。

sdown 和 odown 转换机制。

sdown 是主观宕机,就是一个哨兵如果自己觉得一个master宕机了那就是主观宕机了。
odown 是客观宕机,如果quorum 数量的哨兵都觉得一个master宕机了,那就是客观宕机了。 

slave -> master 选举算法

如果一个master 被认为odown 了。 而且majority 哨兵都允许了主备切换,那就会执行主备切换操作,此时首先要选举一个slave来,会考虑slave 的一些信息,
1 跟master 断开连接的时常,
2 slave 的优先级
3 复制offset
4 run id


如果一个slave 跟master 断开连接已经超过了down-after-milliseconds 的10倍,外加master宕机的时长,那么slave就被认为不适合选举为master
(down-after-milliseconds * 10)+ milliseconds_since_master_is_in_SDOWN_state


接下里会对slave 进行排序

1 按照slave 优先级进行排序,slave priority 越低,优先级就越高,
2 如果slave priorty相同,那么看replica offset 哪个slave 复制了越多的数据,offset越靠后,优先级就越高,
3 如果上面两个条件都相同,那么选择一个run id 比较小的哪个slave

哨兵和slave 集群的自动发现机制

sub系统实现的每个哨兵都会往_sentinel_:hello 这个cheannel里面发送一个消息。这个时候所有其他的哨兵都可以消费这个消息,并感知其他的哨兵的存在。
每隔两秒钟,每隔哨兵都会往自己监控的某个master+slave对应的_sentinel_:hello channel里面发送一个消息, 内容时自己的host ip 和run id 还有对这个master的监控配置

每个哨兵也会监听自己监控的每个master + slave 对应的_sentinel_:hello channel,然后去感知到同样在监听这个master+slave的其他哨兵的存在。
每个哨兵还会跟其他哨兵交换对master 的监控配置,互相进行监控配置的同步。

slave 配置的自动纠正

哨兵会负责自动纠正的slave 的一些配置,比如slave如果成为潜在的master候选人, 哨兵会确保slave在复制现有的master的数据,如果slave连接到一个错误的master上, 比如故障转移之后, 那么哨兵会确保他们连接到正确的master上。

configuration epoch

哨兵会对一套redis master+slave 进行监控,有相应的监控的配置
执行切换的那个哨兵, 会从要切换的新的是master (salve -> master ) 那里得到一个configuration epoch,这就是一个version号。 每次切换的version 号都是必须是唯一的。
如果第一个选举出的哨兵切换失败了。 那么其他哨兵, 会等待failover-timeout 时间,然后接替继续执行切换, 此时会重新获取一个新的configuration epoch 作为新的version 号。

configuration传播

哨兵完成切换之后, 会在自己本地更新生成最新的master配置,然后同步给其他哨兵,就是通过之前说的pub/sub消息机制

这里之前的version 号就很重要了。 因为各种消息都是通过一个channel去发布和监听的,所以一个哨兵完成一次新的切换之后,新的master配置是跟着新的version号的, 其他的哨兵都是根据版本号的大小来更新自己的master配置的。

redis 的持久化的意思和生成环境灾难回复的意义。

做持久化的配置:
高可用,高并发,海量数据。

RDB 和 AOF 两种持久化机制介绍,
RDB 持久化对redis中的数据执行周期性的持久化,
AOF机制对每条写入的命令作为日志, 以append-only 的模式写入一个日志文件中,在redis 重启的时候,可以通过回放AOF日志中的写入指令来重新构建整个数据集,

如果我们想要redis 仅仅作为纯内存的缓存来用, 那么可以禁止RDB和AOF 所有的持久化机制,

如果同时使用RDB和AOF 两种机制持久化, 那么在redis重启的时候, 会使用,AOF来重新构建数据,因为AOF中的数据更加完整。


RDB持久化机制的优点:

1 RDB 会生成多个数据文件, 每个数据文件都代表了某个时间段的中redis中的数据 ,这种多个数据文件的方式,非常适合做冷备,可以将这种完成的数据发送到一个些远程的安全存储上,,比如说 阿里云ODPS分布存储上,等等,

2 RDB 对redis 对提供的读写服务, 影响非常小,可以让redis保持高性能,因为redis主进程只需要fork一个子进程,让子进程执行磁盘io操作来进行RDB的持久化

3 相对于AOF 持久化机制来说, 直接基于RDB数据文件来重启和恢复redis的进程,更加快速。

RDB持久化的缺点:


1 如果想要在redistribution故障时, 尽可能少丢失数据,那RDB没有AOF好。一般来说。RDB都是快照文件。都是每隔5分钟,或者更长时间生成一次, 这个时候就得接受一旦redis进程宕机了。那么会丢失最近5分钟数据

2 RDB 每次在fork子进程的来执行RDB快照数据文件生成的时候, 如果数据文件特别大的时候,可能会导致客户端提供的服务暂停数毫秒,或者甚至数秒,


AOF 持久化机制的缺点:


1 对于同一份数据来说, aof 的日志文件通常比rdb数据快照文件更大,
2 aof开启后, 支持的写QPS会比RDB支持的写QPS低, 因为aof一般会配置成每秒fsync 一次日志文件,当然,每秒一次的fsync 性能也是很高的。

3 以前的aof发生的bug, 就是通过aof记录的日志, 进行数据恢复的时候,没有恢复到一摸一样的数据出来,所以说类似aof这种较为复杂的基于命令/ merge / 回放的方式,比基于比基于RDB每次持久化一份完整的数据快照文件的方式, 更加脆弱一些,容易有bug,不过aof就是为了避免rewrite 过程导致bug,因此每次rewrite 就是基于旧的指令进行merge的,而是基于当时内存中的数据进行指令的重新构建,这样的健壮性会好很多,


AOF持久化机制的优点:

1 AOF 可以更好的保护数据不丢失, 一般的AOF会每个1秒,通过一个后台的线程执行一次fsync操作,最多就是丢失1秒的数据,

2 aof日志i文件以append-only模式写入, 所以没有任何磁盘寻址的开销, 写入性能非常高,而且文件不容易破损,即使文件尾部破损,也很容易修复,

3 aof日志文件即使过大的时候, 出现后台重写的操作, 也不会影响客户端的读写操作,因为在rewrite log 的时候,会对其种指导进行压缩,创建出一份需要恢复数据的最小日志出来, 在创建日志文件的时候,老的日志文件还是照常写入, 当新的merge后日志文件ready的时候,在交换新老日志文件即可,

4 aof 日志文件的命令通过非常可读的方式进行记录, 这个特征非常适合做灾难性的误删除的紧急恢复,比如某个人不小心用flushall 命令清空了所有的数据,只要这个时候后台rewrite还没发生,那么就可以立刻拷贝aof文件,将最后一条flushall 命令给删了, 然后再将aof文件放回去,就可以通过恢复机制,自动恢复所有数据,

RDB和AOF 到底如何选择

1 不要仅仅使用RDB 因为那样会导致你丢失很多数据

2 也不要仅仅使用aof 因为那样有两个问题, 第一 你通过aof做冷备,没有做RDB做冷备恢复速度更快,
第二 , RDB每次简单粗暴生成数据快照,更加健壮,可以避免AOF这种的复杂的备份和恢复机制的bug

3 综合使用AOF 和RDB 两种持久化机制, 用AOF 来保证数据不丢失,作为数据恢复的第一选择;
用RDB来做不同程度的冷备, 在AOF文件都丢失或损坏不可用的时候,还可以使用RDB来进行快速的数据恢复。

redis 数据算法hash 、一致性hash 和redis cluster slort


hash:  是对redis部署的机器进行取模 进行查询。 如果一个机器宕机了。 就会有几乎100%的数据找不到。

一致性hash:  相当与在一个圆环上, 部署的master ,使用hash值进行存储,如果落到圆环上进去顺时针旋转来找最近的master, 这样会存在一个问题。 会有大量的数据落到一个master上, 所以采用了虚拟的master节点来均匀的分布在圆环上来,来解决问题,

cluster slort : 算法是分别部署到redis机器上。用16384个slort 来存储数据, 每次的查询就用16384来取模进行查询。如果有一个机器宕机了。会有三分之一的数据找不到。 但是这个时候cluster slort 会进行数据迁移。均匀分到另外两台机器上。这样的在查询之前的数据还是能查询到的。

redis 的缓存数据库的时候一致性:

1.用户查询数据 先读缓存,存在数据就返回, 没有就读数据库,在写入到缓存中。
2 更新数据的时候, 先删除缓存,在去更新数据库

redis分布式锁:

设置分布式锁 set my:lock 随机值 NX PX 30000
(my 可以用 用户id或者是订单id等,随机值不能重复。NX:存在设置失败,反之就成功,px 设置过期时间)
释放锁。 就是删除key 是根据随机值, 是根据redis中的随机值和key对应的随机值一致就删除。

原文地址:https://www.cnblogs.com/yishuo/p/14653207.html