redis客户端实现高可用读写分离的方式详解


Posted in Redis onJuly 04, 2021

背景

(1) redis单机的读写性能轻松上大几万,不过线上环境不会只部署光秃秃的一个节点,还是会配合 sentinel 再部署一个 slave作为高可用节点的;
但是standby的slave节点是不对外提供服务端的,一定程度上造成了浪费资源

(2) 当业务不断发展,原来单节点缓存的数据(如,商品信息缓存、配置信息等)的查询qps不断升高(写qps增长不多),突破十几万、几十万的的时候,此时一个节点就扛不住了,我们就需要增加几个redis slaves节点来分担这些查询的压力 也就是读写分离

但是,常用的 redis 客户端jedis并不支持读写分离能力

实现方式

(1) 从配置中心获取 master 和 slaves 的连接信息,分别初始化好一个连接master的写连接池和一组slave的读连接池
(2) 将命令进行分类:执行写命令则从 master的连接池取连接然后执行,如果是读命令则从slave的连接池中取出连接执行
可能有多个slave节点,可以按照一定的策略进行负载均衡(权重、随机、轮询...etc) 从其中一个 slave节点的连接池获取连接

大概长这样:

redis客户端实现高可用读写分离的方式详解

高可用版本

前面的实现方式正常情况下是可以的

但是:
(1) 如果运行期间 master挂了怎么办? 如何自动 failover 切换?
(2) 如果流量突增,需要动态扩容一个或多个 slave节点,如何动态生效?

那就不能从配置文件取master和slaves的 ip+port 了,得从redis ha的组件去动态获取 当前master 和可用slave列表的节点信息 => sentinel

1.初始化

向 sentinel 发送命令获取master和slaves的节点信息

//获取当前masterName标识的当前master节点信息,哨兵可监控多个 mater ha,所以要用<masterName>区分
SENTINEL get-master-addr-by-name <masterName>
//获取可用的slaves列表信息
SENTINEL slaves <masterName>

redis客户端实现高可用读写分离的方式详解

拿到连接后,继续用开头的方式去创建连接池就行了

2. 动态failover、扩容

初始化完毕后,在运行期间master节点,和slaves还是可能变化的, 如
(1) master故障、网络分区,sentinel 提升一个slave为新的master
(2) 新增slave节点应对突增流量

我们如何能不重启客户端的情况下,动态切换?

sentinel 在进行master切换、slave变更等操作的时候都会向对应的 channel 发布事件,我们可以基于这些事件感知到相应的变化
参考: https://redis.io/topics/sentinel

2.1 failover切换 master

当 sentinel 进行master failover切换的时候,它会向channel: switch-master 发送通知,我们在客户端订阅这个channel,收到事件后,重新进行初始化的步骤即可

redis客户端实现高可用读写分离的方式详解

2.2 扩容slave

当新的 slave 节点加入, sentinel 感知到则会向channel: +slave 发布事件,我们监听到后,重新获取slaves节点信息重建slaves的连接池就可以了(这边不涉及master的变化)

redis客户端实现高可用读写分离的方式详解

总结

基于 sentienl 获取和动态感知 master、slaves节点信息的变化,我们的读写分离客户端就能具备高可用+动态扩容感知能力了;

到此这篇关于redis客户端实现高可用读写分离的文章就介绍到这了,更多相关redis读写分离内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Redis 相关文章推荐
使用Redis实现秒杀功能的简单方法
May 08 Redis
分布式锁为什么要选择Zookeeper而不是Redis?看完这篇你就明白了
May 21 Redis
redis哨兵常用命令和监控示例详解
May 27 Redis
redis cluster支持pipeline的实现思路
Jun 23 Redis
Redis做数据持久化的解决方案及底层原理
Jul 15 Redis
Redis 持久化 RDB 与 AOF的执行过程
Nov 07 Redis
linux下安装redis图文详细步骤
Dec 04 Redis
Redis高并发缓存架构性能优化
May 15 Redis
Redis基本数据类型Zset有序集合常用操作
Jun 01 Redis
Redis Lua脚本实现ip限流示例
Jul 15 Redis
如何使用注解方式实现 Redis 分布式锁
Jul 23 Redis
使用Redis实现实时排行榜功能
Jul 02 #Redis
redis使用不当导致应用卡死bug的过程解析
Redis主从配置和底层实现原理解析(实战记录)
浅谈Redis中的RDB快照
聊一聊Redis与MySQL双写一致性如何保证
k8s部署redis cluster集群的实现
Jun 24 #Redis
浅析Redis Sentinel 与 Redis Cluster
You might like
DISCUZ 论坛管理员密码忘记的解决方法
2009/05/14 PHP
学习php设计模式 php实现策略模式(strategy)
2015/12/07 PHP
详谈php静态方法及普通方法的区别
2016/10/04 PHP
Laravel 对某一列进行筛选然后求和sum()的例子
2019/10/10 PHP
javascript 24小时弹出一次的代码(利用cookies)
2009/09/03 Javascript
禁用键盘上的(全局)指定键兼容iE、Chrome、火狐
2013/05/14 Javascript
Javascript 多浏览器兼容总结(实战经验)
2013/10/30 Javascript
js实现同一页面可多次调用的图片幻灯切换效果
2015/02/28 Javascript
jQuery给指定的table动态添加删除行的操作方法
2016/10/12 Javascript
使用jquery datatable和bootsrap创建表格实例代码
2017/03/17 Javascript
jQuery点击页面其他部分隐藏下拉菜单功能
2018/11/27 jQuery
微信小程序分享功能onShareAppMessage(options)用法分析
2019/04/24 Javascript
vue h5移动端禁止缩放代码
2019/10/28 Javascript
vue实现导航标题栏随页面滚动渐隐渐显效果
2020/03/12 Javascript
[48:39]Ti4主赛事胜者组第一天 EG vs NEWBEE 2
2014/07/19 DOTA
Python内置函数之filter map reduce介绍
2014/11/30 Python
利用selenium 3.7和python3添加cookie模拟登陆的实现
2017/11/20 Python
python matplotlib 注释文本箭头简单代码示例
2018/01/08 Python
Python标准库笔记struct模块的使用
2018/02/22 Python
python使用__slots__让你的代码更加节省内存
2018/09/05 Python
详解django的serializer序列化model几种方法
2018/10/16 Python
python3 实现对图片进行局部切割的方法
2018/12/05 Python
spark dataframe 将一列展开,把该列所有值都变成新列的方法
2019/01/29 Python
python多线程下信号处理程序示例
2019/05/31 Python
在SQLite-Python中实现返回、查询中文字段的方法
2019/07/17 Python
浅谈pytorch grad_fn以及权重梯度不更新的问题
2019/08/20 Python
python tkinter 设置窗口大小不可缩放实例
2020/03/04 Python
使用Python构造hive insert语句说明
2020/06/06 Python
英国领先的奢侈品零售商之一:CRUISE
2016/12/02 全球购物
小学生学习感言
2014/03/10 职场文书
劳动竞赛口号
2014/06/16 职场文书
学校副校长四风对照检查材料整改措施
2014/09/25 职场文书
幽默导游词应该怎么写?
2019/08/26 职场文书
关于flex 上下文中自动 margin的问题(完整例子)
2021/05/20 HTML / CSS
详解MySQL中的pid与socket
2021/06/15 MySQL
HTML页面中使两个div并排显示的实现
2022/05/15 HTML / CSS