一、Redis单机模式
特点:简单
问题:
1、内存容量有限 2、处理能力有限 3、无法高可用。
二、Redis的主从模式
Redis 的主从同步复制(replication)功能,保证一个 matser主节点服务器可以创建任意多个slaver从服务器实现数据从主节点传递到从节点。
主从复制流程如果所示:
Redis的主从模式特点:
1、master/slave 角色
2、master/slave 数据相同
3、降低 master 并发读压力在转交从库
问题:
1、无法保证高可用,master节点宕机导致整个服务不可用
2、没有解决 master 高并发写的压力
3、可能主从同步有数据延迟,对于即写即读的场景,必须强制使用主库进行数据读写
三、Redis哨兵模式
Sentinel(哨兵)是用于监控Redis集群中Master状态的工具,是Redis高可用解决方案,哨兵可以监视一个或者多个redis master服务,以及这些master服务的所有从服务。 某个master服务宕机后,会把这个master下的某个从服务升级为master来替代已宕机的master继续工作。
(顺带提一句,即使后来之前的master重启服务,也不会变回master了,而是作为slave从服务)
Redis sentinel 是一个分布式系统中监控 redis 主从服务器,并在主服务器下线时自动进行故障转移
其中三个特性:
1、监控(Monitoring): Sentinel 会不断地检查你的主服务器和从服务器是否运作正常。
2、提醒(Notification): 当被监控的某个 Redis 服务器出现问题时, Sentinel 可以通过 API 向管理员或者其他应用程序发送通知。
3、自动故障迁移(Automatic failover): 当一个主服务器不能正常工作时, Sentinel 会开始一次自动故障迁移操作
特点:
1、保证高可用
2、监控各个节点
3、自动故障迁移
缺点:主从模式,切换需要时间丢数据
没有解决 master 写的压力
四、Redis Cluster分片集群架构模式
但随着Redis的版本迭代,Redis官方的Cluster也越来越稳定,更多人开始采用官方的集群化方案。也正是因为它是官方推出的,所以它的持续维护性可以得到保障,这就比那些第三方的开源方案更有优势。
Redis Cluster没有了中间的Proxy代理层,那么是如何进行请求的转发呢?
Redis把请求转发的逻辑放在了Smart Client中,要想使用Redis Cluster,必须升级Client SDK,这个SDK中内置了请求转发的逻辑,所以业务开发人员同样不需要自己编写转发规则,Redis Cluster采用16384个槽位进行路由规则的转发。也有第三方代理方案:请参考Redis代理集群
图中定义的规则是平均分配槽位:
①节点1的槽位区间范围为0-5460
②节点2的槽位区间范围为5461-10922
③节点3的槽位区间范围为10923-16383
Redis虚拟槽的特点
解耦数据和节点之间的关系,简化了节点扩容和收缩难度。
节点自身维护槽的映射关系,不需要客户端或者代理服务维护槽分区元数据。
支持节点、槽和键之间的映射查询,用于数据路由,在线集群伸缩等场景。
Redis集群架构伸缩
Redis 集群提供了灵活的节点扩容和收缩方案。
在不影响集群对外服务的情况下,可以为集群添加节点进行扩容也可以下线部分节点进行缩容。
可以说,槽是 Redis 集群管理数据的基本单位,集群伸缩就是槽和数据在节点之间的移动
(1)假设主节点的数量为3,将16384个槽位按照用户自己的规则手动去分配这3个节点,16384除以3,那么每个节点大约得到5460个槽。
(用户自定义分配的原因在于有些机器的配置高,有些机器的配置低,配置高的可以分配多一点槽位,配置低的可以分配少一点槽位)
(2)存储数据时,对要存储的键进行crc16哈希运算,得到一个值,并取模16384,判断这个值在哪个节点的范围区间。
假设crc16(“test_key”)%16384=3345
因为3345在区间0-5460之间,
所以test_key数据写入到节点1里面。
(3)查询数据时,对要查询的键进行crc16哈希运算,得到一个值,并取模16384,判断这个值在哪个节点的范围区间。
假设crc16(“test_key”)%16384=3345,
因为3345在区间0-5460之间,
所以test_key数据应该从节点1里面获取。
以上就是redis集群采用的虚拟哈希槽的原理和计算规则说明
这种结构很容易添加或者删除节点,并且无论是添加删除或者修改某一个节点,都不会造成集群不可用的状态。使用哈希槽的好处就在于可以方便的添加或移除节点。
当需要增加节点时,只需要把其他节点的某些哈希槽挪到新节点就可以了
当需要移除节点时,只需要把移除节点上的哈希槽挪到其他节点就可以了。
Redis Cluster也提供了在线数据迁移、节点扩容缩容等功能,内部还内置了哨兵完成故障自动恢复功能,可见它是一个集成所有功能于一体的Cluster。因此它在部署时非常简单,不需要部署过多的组件,对于运维极其友好。
Redis Cluster在节点数据迁移、扩容缩容时,对于客户端的请求处理也做了相应的处理。当客户端访问的数据正好在迁移过程中时,服务端与客户端制定了一些协议,来告知客户端去正确的节点上访问,帮助客户端订正自己的路由规则。
虽然Redis Cluster提供了在线数据迁移的功能,但它的迁移性能并不高,迁移过程中遇到大key时还有可能长时间阻塞迁移的两个节点
现在越来越多的公司开始采用Redis Cluster,有能力的公司还在它的基础上进行了二次开发和定制,来解决Redis Cluster存在的一些问题,我们期待Redis Cluster未来有更好的发展。
特点:
1、无中心架构(不存在哪个节点影响性能瓶颈),少了 proxy 层。
2、数据按照 slot 存储分布在多个节点,节点间数据共享,可动态调整数据分布。
3、可扩展性,可线性扩展到 1000 个节点,节点可动态添加或删除。
4、高可用性,部分节点不可用时,集群仍可用。通过增加 Slave 做备份数据副本
5、实现故障自动 failover,节点之间通过 gossip 协议交换状态信息,用投票机制完成 Slave到 Master 的角色提升。
缺点:
1、资源隔离性较差,容易出现相互影响的情况。
2、数据通过异步复制,不保证数据的强一致性集群的必要性
所谓的集群,就是通过添加服务器的数量,提供相同的服务,从而让服务器达到一个稳定、高效的状态。
- 使用 redis 集群的必要性
问题:我们已经部署好了redis,并且能启动一个redis,实现数据的读写,为什么还要学习redis集群?
答:
(1)单个redis存在不稳定性。当redis服务宕机了,就没有可用的服务了。
(2)单个redis的读写能力是有限的。
总结:redis集群是为了强化redis的读写能力。
五、Redis集群扩容机制
操作指南
1.redis扩容的话,首先创建redis-cluster节点(具体配置和其他节点一样),然后再把他们加入到redis集群中
redis-cli --cluster add-node new_host_ip:port exsitint_host_ip:port ##这个是将新节点加入到集群中
redis-cli --cluster add-node new_host_ip:port exsitint_host_ip:port --cluster-slave ##这个将新节点加入集群中作为后面一个节点的从节点
2.迁移槽,迁移槽时要计算原节点迁移多个槽到新节点中
redis-cli --cluster reshard <host>:<port> --cluster-from <node-id> --cluster-to <node-id> --cluster-slots <number of slots>
--cluster-yes
<host>:<port>:可以指定任意一个在集群中的节点
--cluster-from:这个指的是原节点
--cluter-to:这个指的是目标节点
--cluter-slots:这个是要迁移的槽的数量
3.迁移完了之后,最后可以rebalance一下
4.缩容的话(感觉这种操作可能很少),首先也需要用2中的命令将槽给迁移到其他节点上,然后再用redis-cli --cluter del-node run_id 进行删除
redis cluster增加节点进行扩容步骤:
1.在新的服务器上部署redis cluster
2.使用工具将新部署的节点加到集群中
3.使用工具将集群槽位重新分配
4.将主从复制关系调整成交叉模式
扩容原理: 原来的节点算好要拿出多少的槽位给新加的节点,新加的节点准备导入的槽位,准备的前提条件就是加入集群,一切准备就绪后,主节点将划分出来的槽位分配给新节点,然后将相关槽位的数据迁移到新的节点
为什么Redis Cluster会设计成16384个槽呢?
为什么Redis Cluster会设计成16384个槽呢?
理论上crc16算法可以得到2^16个数值,其数值范围在0-65535之间,
取模运算key的时候,应该是crc16(key)%655351.如果槽位为65536,发送心跳信息的消息头达8k,发送的心跳包过于庞大。
2.Redis的集群主节点数量基本不可能超过1000个。
3.槽位越小,节点少的情况下,压缩率高1.redis cluster 分片为什么没有使用一致性hash算法,而是使用了哈希槽预分片?
缓存热点问题:
一致性哈希算法在节点太少时,容易因为数据分布不均匀而造成缓存热点的问题。
一致性哈希算法可能集中在某个hash区间内的值特别多,会导致大量的数据涌入同一个节点
造成master的热点问题(如同一时间20W的请求都在某个hash区间内)