redis-集群模式
一、Redis的主从复制
通过执行slaveof命令或设置slaveof选项,让一个服务器去复制另一个服务器的数据。被复制的服务器称为:Master主服 务; 对主服务器进行复制的服务器称为:Slave从服务器。主数据库可以进行读写操作,当写操作导致数据变化时会自动将数据同步给从数据库。而从数据库一般是只读的,并接受主数据库同步过来的数据。一个主数据库可以拥有多个从数据库,而一 个从数据库只能拥有一个主数据库。
主从复制问题:当master down,需要手动将一台slave使用slaveof no one提升为master要实现自动,就需要redis哨兵
实现原理
- 从服务器向主服务器发送SYNC命令
- 主服务器收到SYNC命令后,执行BGSAVE命令,在后台生成RDB文件,使用缓冲区记录从现在开始执行的所有的写命令。
- 当主服务器的BGSAVE命令执行完毕后,主服务器后将BGSAVE命令生成的RDB文件发送给从服务器,从服务器接收并载入这个RDB文件,将自己的数据库状态更新至主服务器执行BGSAVE命令时的数据库状态。
- 主服务器将记录在缓冲区里面的所有写命令发送给从服务器,从服务器执行这些写命令,将自己的数据库状态更新至主服务器数据库当前所处的状态。
缺点
- 不具备容错机制,主服务器(master)挂了,从服务器(slave)不会自动转为主服务器(从服务器不可以对外提供写服务,因为从服务不具备向主服务器发送数据),需要手动更改客户端IP地址
- 主服务器(master)发生宕机,会导致从服务器(slave)丢失最近一次同步数据到宕机之间的数据
优点
- 主从分离可以实现数据读写分离,主服务器(master)提供读写服务,从服务器(slave)提供读服务。
- 主-从同步数据的时候,对外仍然提供读写服务(非阻塞的方式)
- 从服务器(slave)同步期间,对外仍然提供读服务(非阻塞方式),返回的数据是同步之前的数据(会产生脏读)
二、Redis的哨兵(Sentinel)
为了解决Redis的主从复制的不支持高可用性能,Redis实现了Sentinel哨兵机制解决方案。由一个或多个Sentinel去监听任意多个主服务以及主服务器下的所有从服务器,并在被监视的主服务器进入下线状态时,自动将下线的主服务器属下的某个从服务器升级为新的主服务器,然后由新的主服务器代替已经下线的从服务器,并且Sentinel可以互相监视。
实现原理(哨兵监控)
1.如果 Redis 节点未在 [master-down-after-milliseconds] 指定的时间内,对向它发送 PING 命令的哨兵返回一个有效回复,该 哨兵就会将这个服务器标记为下线。
2. 当某个哨兵先检测到主节点不可用时,系统并不会马上进行 failover 过程【最终只有一个 sentinel 节点作为 failover 的发起 者,就需要选举一个 leader(采用类似 Raft 协议实现选举算法)】。该哨兵会通知其它哨兵,发送 [SENTINEL is-master-down-by-addr] 来询问其他哨兵是否认为主节点的服务器已下线并提议选举自己为领导者哨兵。
3. 如果在规定的时间内接收到多个哨兵(哨兵数量大于3且为奇数)的同意时,领导者哨兵产生
Redis 哨兵通知及故障转移
1. 领导者哨兵选出一个从节点,并将其升级为主节点。
2. 向被选中的从节点发送 SLAVEOF NO ONE 命令,让它转变为主节点。
3. 通过发布与订阅功能,将更新后的配置传播给所有其他 Sentinel,其他 Sentinel 对他们自己的配置进行更新。
4. 向其他从节点发送 SLAVE OF 命令,让它们去复制新的主节点。
5. 当所有的从节点都已经开始复制新的主节点时,领导者哨兵终止此次故障迁移操作。
6. 每当一个 Redis 实例被重新配置(reconfigured),无论是被设置成主节点、从节点、又或者被设置成其他主节点的从节点, 哨兵都会向被重新配置的实例发送一个 CONFIG REWRITE 命令,从而确保这些配置会持久化到硬盘。
优点
1.哨兵模式是基于主从模式的,所有主从的优点,哨兵模式都具有。
2.主从可以自动切换,系统更健壮,可用性更高。
缺点
1.Redis较难支持在线扩容,在集群容量达到上限时在线扩容会变得很复杂。
三、Redis-Cluster
哨兵模式基本符合高可用、读写分离,但是这种模式下每个redis保存的数据都是一致的,浪费大量内存空间。所以redis cluster实现了分布式存储,每个主节点服务器保存的数据不一样。
Redis-Cluster 简介
1.Redis 集群(Redis-Cluster)提供了在多个 Redis 节点间共享数据的功能。
2.Redis 集群通过分区来提高可用性。可自动分割数据到不同的节点上,集群的部分节点失败或者不可达时能够继续处理请求。
3.Redis Cluster 集群模式通常具有高可用性、可扩展性、分布式等特性。
4.Redis 集群采用 P2P 模式,是完全去中心化的,不存在中心节点或者代理节点。
5.Redis 集群是没有统一的入口,客户端连接集群的任意节点(node)即可,集群内部的节点是相互通信的(PING-PONG机制),每个节点都是一个 Redis 实例。
6.为了实现集群的高可用,即判断节点是否健康[能否正常使用],redis-cluster有这么一个投票容错机制:如果集群中超过半数的节点投票认为某个节点挂了,那么这个节点就挂了(fail)。这是判断节点是否挂了的方法。如果集群中任意一个节点挂了,而且该节点没有从节点(备份节点),那么这个集群就挂了。这是判断集群是否挂了的方法。
7.那么为什么任意一个节点挂了(没有从节点)这个集群就挂了呢? 因为集群内置了16384个slot(哈希槽),并且把所有的物理节点映射到了这16384[0-16383]个slot上,或者说把这些slot均等的分配给了各个节点。当需要在Redis集群存放一个数据(key-value)时,redis会先对这个key进行 CRC16 算法,然后得到一个结果。再把这个结果对16384进行求余,这个余数会对应[0-16383]其中一个槽,进而决定key-value存储到哪个节点中。所以一旦某个节点挂了,该节点对应的 slot 就无法使用,那么就会导致集群无法正常工作。综上所述,每个Redis集群理论上最多可以有16384个节点。
Redis-Cluster 查询路由方案
1.客户端随机地请求任意一个 Redis 实例,然后由 Redis 将请求转发给正确的 Redis 节点。
2.Redis-Cluster 实现了一种混合形式的查询路由,但不是直接将请求从一个 Redis 节点转发到另一个 Redis 节点,而是在客户端帮助下直接重定向(redirected)到正确的 Redis 节点。如果访问的第一个节点就是目标节点,则直接返回结果。
Redis-Cluster 数据分片
1.Redis-Cluster 没有使用一致性哈希,而是引入了哈希槽(slot)的概念。
2.Redis-Cluster 有16384 个哈希槽,每个 key 通过 CRC16 校验后对 16384 取模来决定放置在那个槽,集群中的每一个节点负责一部分 hash 槽。
Redis-Cluster 一致性保存
1.Redis-Cluster 使用了异步复制:主节点对客户端请求回复状态后,异步发起写操作给从节点,会存在一个时间间隙。
2.Redis-Cluster 出现网络分区时,当一个客户端与至少包含一个主节点在内的少数节点被孤立,可能导致在节点超时时间(node timeout)内,另一个网络分区内的大部分节点重新选举被孤立主节点的从节点为新的主节点。节点超时时间选项为 cluster-node-timeout 15000(毫秒)
使用 redis-trib.rb 搭建 Redis-Cluster
Redis集群至少需要3个节点,因为投票容错机制要求超过半数节点认为某个节点挂了该节点才是挂了,所以2个节点无法构成集群。 要保证集群的高可用,需要每个节点都有从节点,也就是备份节点,所以Redis集群至少需要6台服务器。因为我没有那么多服务器,也启动不了那么多虚拟机,所在这里搭建的是伪分布式集群,即一台服务器虚拟运行6个redis实例,修改端口号为(7001-7006),当然实际生产环境的 Redis 集群搭建和这里是一样的。
优点
1.解耦数据和节点之间的关系,简化了节点扩容和收缩难度。
2.节点自身维护槽的映射关系,不需要客户端或者代理服务维护槽分区元数据。
3.支持节点、槽、键之间的映射查询,用于数据路由、在线伸缩等场景。
4.无论添加、删除或者改变某个节点的哈希槽数量都不会造成集群不可用的状态。
四、Temproxy
temproxy 是 twitter 公司开发的一套后端缓存代理,他通过代理实现数据分片,而后端依赖于原生的 redis 节点与 redis-sentinel,由于原生的 redis 节点与 redis-sentinel 组成的集群没有了上述 redis-cluster 诸多限制,让我们可以十分方便的使用。
优点
1.快速 – 据测试,直连 twenproxy 和直连 redis 相比几乎没有性能损失,读写分离后更是能够极大地提高集群响应能力
2.轻量级 – Twemproxy 通过透明连接池、内存零拷贝以及 epoll 模型实现了足够的快速和轻量化,源码较为简洁精炼
3.降低负载 – 透明连接池保持前端的连接数,减少后端的连接数,让后端的 redis 节点负载大为降低
4.分片 – Twemproxy 通过一致性 hash 算法将数据进行分片,从而实现 redis 集群的高速缓存,降低负载
5.多协议 – 同时支持 redis 与 memcache 集群的搭建
6.多算法 – 支持多种算法实现一致性哈希分片,包括crc32,crc16,MD5等
7.配置简单
8.监控报警丰富 – 虽然他提供的原生监控功能一般较少使用,但其提供的统计信息,如发送了多少读写命令还是有很大的价值的
缺点
1.单点 – Twemproxy 只实现了静态分片的功能,本身不具备集群功能,但可以通过 keepalive 来解决
2.运维不友好 – 没有提供控制面板
3.无法平滑地扩容/缩容 – 这是一个非常大的缺陷,虽然我们可以通过技术手段和方案来尽量避免,但对于运维人员来说仍然是有很大压力的
五、codis
Codis 是由豌豆荚于2014年11月开源的 redis 集群解决方案,他针对 Twemproxy 上述弱点,实现了一套。他通过使用 go 和 C 语言在 redis 源码基础上二次开发,实现了 redis 分布式、高可用集群的实现,在 value 长度低于 888 字节的情况下,性能优于 Twemproxy 一倍左右。
Codis 的架构
1.Codis引入了Group的概念,每个Group包括1个Redis Master及至少1个Redis Slave。
2.同时,Codis 提供了一套运营监控界面,运维人员可通过Dashboard“自助式”地进行主从切换。
3.与 redis-cluster 一样,Codis 也采用预分片的机制,整个集群分成 1024 个 slot,由 Zookeeper 维护分片路由表,最新版本 的 codis-3.2 允许自定义分片路由表存储方式
优点
1.数据热迁移 – 这是 Redis 最大的优势,这也是他被广为使用的最大原因,
2.运维界面友好 – 提供 slot状态、Proxy状态、group状态、lock、action 等的丰富监控和显示
3.故障处理灵活 – 本身只监控和报告故障,提供 API 对故障进行处理,从而让运维能够实现灵活的故障处理方案
4.架构清晰 – 如上图所示,整个架构清晰,组件高度内聚,故障的发现和处理变得更为容易
5.除此以外,Codis 还提供了从 Twemproxy 到 Codis 的一键迁移工具。
缺点
1.版本滞后 – 因为在 redis 源码基础上进行二次开发,所以很难跟上最新版 redis 的脚步,目前最新的 Codis-3.2 基于 Redis- 3.2.8 版本
2.部署复杂 – 部署过程至少要进行 codis-dashboard、codis-proxy、codis-server、codis-fe 四个组件的部署和启动
3.单节点性能低 – 如果仅有一个 codis-server,性能低于原生 redis 20% 左右
4.更新频率低