关于Redis集群的数据分区和故障转移,这应该是全网最清晰的一篇
mhr18 2024-11-15 22:09 21 浏览 0 评论
redis 集群
根据之前的诸多分析,我们知道单机的redis有很多的局限性,所以可以使用多台机器来实现分区存储,构建更大的数据库,满足更高的业务需求。
之前我们实现的主从复制,可以实现一主多从的架构,但是抽象来看,其实也只是一个redis架构,只有一个主库实现读写,并不是多主多从的结构,所以我们需要redis集群来分散单台服务器的访问压力,实现负载均衡,同时减轻单机的存储上限,提高扩展性。
单机架构
在redis3.0时,提供了redis cluster来满足集群搭建的需求,可以进行手动搭建,分配节点和节点握手,然后手动分配槽。
同时官方提供了redis-trib.rb的ruby脚本,推荐使用该脚本来实现快速搭建和管理。值得一提的是,单机redis本身是有0-15个数据库的,而集群中每个redis节点只有db0。
集群架构
数据分区
如果是单机存储的话,直接将数据存放在单机redis就行了。但是如果是集群存储,就需要考虑到数据分区了。
数据分区通常采取顺序分布和hash分布。
分布方式 | 顺序分布 | 哈希分布 |
数据分散度 | 分布倾斜 | 分布散列 |
顺序访问 | 支持 | 不支持 |
顺序分布保障了数据的有序性,但是离散性低,可能导致某个分区的数据热度高,其他分区数据的热度低,分区访问不均衡。
哈希分布也分为多种分布方式,比如区域哈希分区,一致性哈希分区等。而redis cluster采用的是虚拟槽分区的方式。
虚拟槽分区
redis cluster设置有0~16383的槽,每个槽映射一个数据子集,通过hash函数,将数据存放在不同的槽位中,每个集群的节点保存一部分的槽。
每个key存储时,先经过哈希函数CRC16(key)得到一个整数,然后整数与16384取余,得到槽的数值,然后找到对应的节点,将数据存放入对应的槽中。
集群通信
但是寻找槽的过程并不是一次就命中的,比如上图key将要存放在14396槽中,但是并不是一下就锁定了node3节点,可能先去询问node1,然后才访问node3。
而集群中节点之间的通信,保证了最多两次就能命中对应槽所在的节点。因为在每个节点中,都保存了其他节点的信息,知道哪个槽由哪个节点负责。这样即使第一次访问没有命中槽,但是会通知客户端,该槽在哪个节点,这样访问对应节点就能精准命中。
- 节点A对节点B发送一个meet操作,B返回后表示A和B之间能够进行沟通。
- 节点A对节点C发送meet操作,C返回后,A和C之间也能进行沟通。
- 然后B根据对A的了解,就能找到C,B和C之间也建立了联系。
- 直到所有节点都能建立联系。
这样每个节点都能互相直到对方负责哪些槽。
集群伸缩
集群并不是建立之后,节点数就固定不变的,也会有新的节点加入集群或者集群中的节点下线,这就是集群的扩容和缩容。但是由于集群节点和槽息息相关,所以集群的伸缩也对应了槽和数据的迁移
集群扩容
当有新的节点准备好加入集群时,这个新的节点还是孤立节点,加入有两种方式。一个是通过集群节点执行命令来和孤立节点握手,另一个则是使用脚本来添加节点。
- cluster_node_ip:port: cluster meet ip port new_node_ip:port
- redis-trib.rb add-node new_node_ip:port cluster_node_ip:port
通常这个新的节点有两种身份,要么作为主节点,要么作为从节点:
- 主节点:分摊槽和数据
- 从节点:作故障转移备份
其中槽的迁移有以下步骤:
集群缩容
下线节点的流程如下:
- 判断该节点是否持有槽未持有槽就跳转到下一步持有槽则先迁移槽到其他节点
- 通知其他节点(cluster forget)忘记该下线节点
- 关闭下线节点的服务
需要注意的是如果先下线主节点,再下线从节点,会进行故障转移,所以要先下线从节点。
故障转移
除了手动下线节点外,也会面对突发故障。下面提到的主要是主节点的故障,因为从节点的故障并不影响主节点工作,对应的主节点只会记住自己哪个从节点下线了,并将信息发送给其他节点。故障的从节点重连后,继续官复原职,复制主节点的数据。
只有主节点才需要进行故障转移。在之前学习主从复制时,我们需要使用redis sentinel来实现故障转移。而redis cluster则不需要redis sentinel,其自身就具备了故障转移功能。
根据前面我们了解到,节点之间是会进行通信的,节点之间通过ping/pong交互消息,所以借此就能发现故障。集群节点发现故障同样是有主观下线和客观下线的
主观下线
对于每个节点有一个故障列表,故障列表维护了当前节点接收到的其他所有节点的信息。当半数以上的持有槽的主节点都标记某个节点主观下线,就会尝试客观下线。
客观下线
故障转移
集群同样具备了自动转移故障的功能,和哨兵有些类似,在进行客观下线之后,就开始准备让故障节点的从节点“上任”了。
首先是进行资格检查,只有具备资格的从节点才能参加选举:
- 故障节点的所有从节点检查和故障主节点之间的断线时间
- 超过cluster-node-timeout * cluster-slave-validati-factor(默认10)则取消选举资格
然后是准备选举顺序,不同偏移量的节点,参与选举的顺位不同。offset最大的slave节点,选举顺位最高,最优先选举。而offset较低的slave节点,要延迟选举。
当有从节点参加选举后,主节点收到信息就开始投票。偏移量最大的节点,优先参与选举就更大可能获得最多的票数,称为主节点。
当从节点走马上任变成主节点之后,就要开始进行替换主节点:
- 让该slave节点执行slaveof no one变为master节点
- 将故障节点负责的槽分配给该节点
- 向集群中其他节点广播Pong消息,表明已完成故障转移
- 故障节点重启后,会成为new_master的slave节点
集群的读写分离
在集群模式下的从节点是只读连接的,也就是说集群模式中的从节点是拒绝任何读写请求的。当有命令尝试从slave节点获取数据时,slave节点会重定向命令到负责该数据所在槽的节点。
为什么说是只读连接呢?因为slave可以执行命令:readonly,这样从节点就能读取请求,但是这只是在这次连接中生效。也就是说,当客户端断开连接重启后,再次请求又变成重定向了。
集群模式下的读写分离更加复杂,需要维护不同主节点的从节点和对于槽的关系。
通常是不建议在集群模式下构建读写分离,而是添加节点来解决需求。不过考虑到节点之间信息交流带来的带宽问题,官方建议节点数不超过1000个。
单机?集群?
集群并不是最优选,而是根据不同的业务需求来判断是否搭建集群,当较小的业务利用单机redis和redis sentinel就能满足需求时,不需要强行搭建集群。
集群也有部分限制:
- redis事务操作的key必须在一个节点上
- 批量操作如mset、mget必须在一个槽里
- 只有一个数据库db0
- 有些命令无法跨节点,如scan、flush、keys
- 更难以维护
所以集群搭建还要考虑单机redis是否已经不能满足业务的并发量,在redis sentinel同样能够满足高可用,且并发并未饱和的前提下,搭建集群反而是画蛇添足了。
相关推荐
- 如何通过 Redis 日志排查连接超时问题
-
Redis是一种高性能的内存数据存储服务,但在高并发或误配置情况下,可能会出现连接超时问题。借助Redis日志,可以快速定位并解决连接超时的根本原因。以下是具体的排查和解决步骤:1.什么是R...
- 给你1亿的Redis key,如何高效统计?
-
前言有些小伙伴在工作中,可能遇到过这样的场景:老板突然要求统计Redis中所有key的数量,你随手执行了KEYS*命令,下一秒监控告警疯狂闪烁——整个Redis集群彻底卡死,线上服务大面积瘫痪。今天...
- Redis分布式锁的安全性分析与实践指南
-
一、Redis分布式锁的核心原理Redis分布式锁通过SETNX(SetifNotExists)和EXPIRE(Expire)指令实现原子性操作,结合UUID生成唯一标识符,确保锁的互斥性和安全...
- 高可用Redis分布式锁:秒杀系统中的锁战
-
引言在分布式系统中,“程序猿的终极武器是并发控制”。当多个服务实例同时访问共享资源时,如何避免数据不一致和重复操作?答案是分布式锁。Redis凭借其高性能和原子性操作,成为实现分布式锁的首选方案。...
- Redis分布式锁(redis分布式锁解决超卖)
-
场景描述简单模拟一个高并发库存扣减场景,商品库存加载到Redis缓存,如:127.0.0.1:6379>setproduct:stock:101200无锁状态操作从缓存中获取对应商品的库存...
- Redis 分布式锁和 ZooKeeper分布式锁
-
Redis分布式锁和ZooKeeper(简称zk)分布式锁都是用来解决在分布式系统中多个节点之间竞争资源的问题。它们各自有不同的特点和适用场景。Redis分布式锁Redis实现分布式锁主要是...
- Redis vs ZooKeeper锁:高并发下的生死对决,谁才是最终赢家?
-
在分布式系统中,锁是控制资源访问的重要机制。Redis和ZooKeeper作为两种主流的分布式锁实现方案,各有优劣。本文将从原理、性能、代码实现三个维度进行硬核对比,助你做出最佳技术选型。一、原理对比...
- 说说Redis的大key(redis key大小限制)
-
一句话总结Redis大key指存储超大值(如字符串过大、集合元素过多)的键。主要成因包括:1.设计不合理,未拆分数据结构;2.业务需求(如缓存整页数据);3.数据持续积累未清理;4.使用不当的集合类型...
- PHP Laravel框架底层机制(php框架的底层原理)
-
当然可以,Laravel是最受欢迎的PHP框架之一,以优雅的语法和丰富的生态而闻名。尽管开发体验非常“高端”,它的底层其实是由一系列结构清晰、职责分明的组件构成的。下面我从整体架构、核心流程、...
- PHP性能全面优化-值得收藏(php优化网站性能)
-
PHP项目卡顿频发,老技巧失灵?隐藏漏洞竟在代码循环里。上周公司服务器突然开始卡顿,测试发现用户请求响应时间翻倍。我们先按以前学的方法做了基准测试,用AB工具压测时发现2000并发就有5%错误,换成S...
- PHP+UniApp:低成本打造外卖系统横扫App+小程序+H5全平台
-
在餐饮行业数字化转型中,外卖系统开发常面临两大痛点:高昂的开发成本(需独立开发App、小程序、H5)和多端维护的复杂性。PHP+UniApp的组合通过技术复用与跨平台能力,为中小商家和开发者提供了“降...
- 从需求到上线:PHP+Uniapp校园圈子系统源码的架构设计与性能优化
-
一、需求分析与架构设计1.核心功能需求用户体系:支持手机号/微信登录、多角色权限(学生、教师、管理员)。圈子管理:支持创建/加入兴趣圈子(如学术、电竞)、标签分类、动态发布与审核。实时互动:点赞、评...
- PHP 8.0性能翻3倍?四年亲测:这些项目升了哭晕!
-
2020年那个感恩节,当PHP8.0带着“性能翻倍”的豪言横空出世时,无数程序员连夜备份代码准备升级。四年过去了,那些宣称“性能提升3倍”的项目,真的跑出火箭速度了吗?还记得当时铺天盖地的宣传吗?“...
- 我把 Mac mini 托管到机房了:一套打败云服务器的终极方案
-
本内容来源于@什么值得买APP,观点仅代表作者本人|作者:薯仔不爱吃薯仔我把我积灰的Macmini托管到机房了,有图有真相。虽然画质又渣又昏暗,但是!这就是实锤。作为开发者,谁不想拥有个自己的服...
- 从phpstudy到Docker:我用一个下午让开发效率翻倍的实战指南
-
一、为什么放弃phpstudy?上周三下午,我花了3小时将本地开发环境从phpstudy迁移到Docker,没想到第二天团队反馈:环境部署时间从2小时压缩到5分钟,跨设备协作bug减少70%。作为一个...
你 发表评论:
欢迎- 一周热门
- 最近发表
- 标签列表
-
- oracle位图索引 (74)
- oracle批量插入数据 (65)
- oracle事务隔离级别 (59)
- oracle 空为0 (51)
- oracle主从同步 (56)
- oracle 乐观锁 (53)
- redis 命令 (83)
- php redis (97)
- redis 存储 (67)
- redis 锁 (74)
- 启动 redis (66)
- redis 时间 (56)
- redis 删除 (67)
- redis内存 (57)
- redis并发 (52)
- redis 主从 (69)
- redis 订阅 (51)
- redis 登录 (54)
- redis 面试 (58)
- 阿里 redis (59)
- redis 搭建 (53)
- redis的缓存 (55)
- lua redis (58)
- redis 连接池 (61)
- redis 限流 (51)