架构师之路-redis集群解析

本文涉及的产品
云数据库 Redis 版,社区版 2GB
推荐场景:
搭建游戏排行榜
云数据库 RDS MySQL Serverless,0.5-2RCU 50GB
云数据库 RDS MySQL Serverless,价值2615元额度,1个月
简介: 架构师之路-redis集群解析

引子


1112728-20211031224736164-1593479514.png


上篇《架构师之路-https底层原理》里我提到了上面的整体视图,文章也介绍了想要真正能在工作中及时正确解决问题的基本功:原理理解透彻。今天以redis集群解析为例介绍一个及时敏锐的发现问题的基本功:深入分析。


我认为达到深入分析有三个步骤:


第一步,深入理解


第二步,学以致用


第三步,千人千问


第一步redis集群各种原理介绍的人也很多;第二步很多人实际项目中大概也对redis集群不陌生;所以本文主要讲第三步:千人千问。

 

提出问题



"redis集群使用时有什么注意事项?"这是之前有段时间我面试喜欢问的一个问题。我的一个观点是作为redis集群的使用方而不是开发者首先要做的是用好。通过这个问题确定候选人用好了,再去挖掘他是通过了解了怎么用好的。所以我通常不会一开始就问一些中间件的原理,而是先从使用者的角度提出问题。


下面列举了6条代表性的回答:


1>防止集中失效


2>单线程执行,注意不要卡住


3>注意客户端和服务端的版本匹配


4>分片要保持流量均匀


5>注意超时时间配置


6>当内存缓存用,推荐删除代替更新


每条问题前面加上个为什么,就引出了6条新的问题。

 

解决问题



Q1:为什么要防止缓存集中失效?


A:缓存穿透、缓存集中失效和缓存雪崩并称为缓存世界的三大问题。先来总结理解一下这三个概念。这三个概念都是建立在缓存的一大作用就是对后端存储,比如mysql的保护。缓存没有保护住mysql,一个或一些到mysql了,那就是穿透;一个时间点缓存数据没有了,打到mysql了就是集中失效;缓存完全丧失了保护mysql的能力,请求全打到mysql了,就是雪崩。


所以防止缓存集中失效是对后端存储的保护。


Q2:为什么单线程执行,注意不要卡住?


A:卡住换个专业点的词就是阻塞嘛。什么叫阻塞呢,一辆小轿车A在单行道跑,遇到前面一辆车B停了,那A就被阻塞了。如果A和B都在高速单行道上跑,A开了160迈、B开了140迈。就算高速的允许最高速度是120迈(咱就当路过的是没有摄像头的路段,这俩车肆无忌惮),那A是不是还是被B给阻塞了呢?所以卡住造成的最直接影响就是快的快不起来,因为单线程不能绕行嘛。


有人说不是可以多开几个redis嘛。是滴,但是客户端分请求使用的是crc16,根本不会先探测哪个服务端比较空闲呀。所以后面来的总会被阻塞。


注意不要卡住还有个大家更常听到的名字:“避免大key问题”。其实我刚听到这个名字的时候是觉得很奇怪的。因为避免大key实际上是要避免key所对应的value不要太大。我之前一直觉得这个名字取的不对。那应该叫“避免大value问题”。后来想想这确实是正宗的中国话。比如张三的媳妇,人家都怎样叫呢?一般都是张三媳妇、张三家的。因为他家主要是张三出来抛头露面。那redis取值也一样,一般是先知道key,从key取value。用这个key取出来的数据大,就是大key问题啦。


Q3:如果不注意客户端和服务端版本匹配会引发什么问题?


A:先来思考客户端做了什么事情。我理解它就做了两件事:第一是使用RESP(Redis自定义的序列化协议)传输客户端命令并返回结果。第二是为了做第一件事,因为Redis集群是直连服务端模式,所以计算命令要落在哪个节点、哪个哈希槽上也是客户端来做的,我就称为选节点吧。


其实要回答客户端和服务端不匹配会引发什么问题,正规的方法应该是查看客户端版本升级都做过什么更新。


一般升级会做的是客户端依赖的jar包变了。这个可能会引起程序启动错误,但是这个往往启动成功了就不会再有问题,和服务端版本没有直接关系。


十年前还在用memcache的时候,发生过一次升级客户端版本,因为算法发生了变化,所以导致缓存全部不命中的问题。Redis最近的算法一直是crc16。如果不存在分布式算法不兼容问题的话,下一个要考虑的是大迭代是Redis3.0版本,支持了集群,集群模式是必须要匹配的。


Q4:为什么分片要保持流量均匀?


A:要提分片先来回忆一下redis集群的发展史,从单机版到主从版,后来有了大家可能很耳熟的哨兵模式。哨兵模式就是给主从增加一个监控,发现主节点挂了自动把从节点升级为主节点,有了故障自动迁移的功能。但是直到哨兵时代都只有一个主节点,也就是处理写请求的节点,不能称之为真正的集群。这也是很无奈的事情,一旦多个节点写一份数据,就涉及到数据一致性的问题。


一个蜂巢只能有一个蜂后,多出来一个,蜜蜂们就不会正常提供采蜜服务了,都打架去了。但是分成两个蜂巢呢?秩序就会恢复。所以现在的集群基本都是分片的原理。之前主从和哨兵的经验不能废弃,加上分片。redis集群就是将一个完整服务数据分成几份,每份都带着从节点,故障时可自动转移的一个整体。之前在《Redis集群搭建采坑总结》里讲过,1个节点的集群会有问题,最少需要3主3从也就是6个redis进程。3个主方便在1个挂掉之后重新选主。


梳理了这个之后,分片保持流量均匀这件事也很容易了。就是Q2的问题,均匀更不容易阻塞嘛。


Q5:为什么要注意超时时间配置?


A:提到redis的key的过期时间,首先想到的是redis的术语中,带过期时间的key又叫volatile key,就是不稳定key。怎么不稳定呢?就相当key这个对象有value和过期时间2个属性。过期时间这个属性1s改变一次(redis领域内时间都是以秒为单位),一直在变,当然不稳定。


如果把过期时间理解为key的一个属性,那也很好理解:对其进行del、set命令时过期时间也会删除;rename会把过期时间传给新的key;incr、lpush、hset等命令改变的是key的存储容器,没有改变key这个对象本身所以不会影响过期时间。


值得注意的是persist命令就是持久化保存的意思,将不稳定变成稳定,过期时间也自动删除了。


Redis在服务端有过期策略,但是对客户端是不感知的。客户端访问过期的就是一个表现,访问不到了。实际上服务端是有两种策略配合使用,一个是惰性删除,就是访问的时候发现过期了,就直接删除了;另一个策略会定期去删除,这个是为了防止一个过期的key总是不被访问到,还占着资源不释放。


Q6:为什么当内存缓存用,推荐删除代替更新?


A:一般大家出于数据一致性的考虑,会选择删除代替更新。这都是基于更新一定要更新数据库的固有思路。并发场景下,A的值1先被更新到数据库再更新缓存时,又来了一个更新请求把A的值更新为2。如果这时候执行更新为1的服务器性能不好或者网络传输速度比更新为2的慢,导致2在数据库是最新值,而设置为1的后更新了缓存。缓存就和数据库不一致了。


但只是记住删除代替更新不太够。如果先删除缓存再更新数据库,其他请求可能会把数据库老的值再加载到缓存中。记得之前有人介绍缓存还有三大种模式:Cache-Aside、Read-Through/Write-Through、Write-Behind。


Cache-Aside就是先更新数据库再删除缓存数据,可以避免上面提到的持续脏读的问题,顶多就是更新数据库的那一小段时间有更新延迟可见。我们给Cache-Aside起个中文名,叫经典模式。


Read-Through/Write-Through就是数据以缓存为准,数据库的操作是缓存发起的。


Read-Through是在读数据时发现缓存过期了,那缓存自己去数据库加载新的数据,读数据还是读取缓存值。Write-Through写数据时调用方只负责写缓存,缓存自己去同步更新数据库。Read-Through/Write-Through一般配合使用。


Write-Behind和Write-Through的区别是虽然都是是写数据时调用方只负责写缓存,但是Write-Behind缓存自己去异步更新数据库。


因为Read-Through/Write-Through、Write-Behind都是以缓存为准,缓存不可靠,所以还是推荐经典模式。

 

后记


一些朋友问我一边上班一边写文章哪有那么多时间呀。细心的朋友可能会发现我的文章一般是周末或者周一,再不就是节假日或者哪天失眠了发出来。因为内容都是非上班时间写的,但是每次下笔腹稿都是提前打好的。个人意见哈,作为架构师,很多人都会形成随时随地为工作思考和总结的习惯。所以很多人看着下班很早,人家回家路上,晒太阳的时候……未必没在想工作的事情。


架构师三件占时间的事:会议、评审和演讲。对应有三大难:提出有水平的问题、做出有水平的总结和建议、做出有水平的回答。所以每天有很多的腹稿要打。腹稿按照一定的框架结构整理就是文章。

如果大家都架构师的三大难有兴趣,我可以举一些具体的示例和解决方法。大家投票吧,如果在看超过10个,我就写这个。

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore     ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库 ECS 实例和一台目标数据库 RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
4天前
|
缓存 NoSQL Redis
深度解析Redis的缓存双写一致性
【4月更文挑战第20天】
29 1
|
5天前
|
存储 NoSQL Redis
Redis入门到通关之数据结构解析-SkipList
Redis入门到通关之数据结构解析-SkipList
21 0
|
5天前
|
存储 NoSQL 安全
Redis入门到通关之数据结构解析-动态字符串SDS
Redis入门到通关之数据结构解析-动态字符串SDS
12 0
|
5天前
|
存储 NoSQL Java
Redis入门到通关之数据结构解析-Dict
Redis入门到通关之数据结构解析-Dict
11 2
|
5天前
|
消息中间件 存储 缓存
|
5天前
|
存储 NoSQL 算法
Redis 搭建分片集群
Redis 搭建分片集群
14 2
|
8天前
|
存储 NoSQL Java
Redis 实现延迟任务的深度解析
【4月更文挑战第17天】
121 0
|
20天前
|
存储 NoSQL 算法
09- Redis分片集群中数据是怎么存储和读取的 ?
Redis分片集群使用哈希槽分区算法,包含16384个槽(0-16383)。数据存储时,通过CRC16算法对key计算并模16383,确定槽位,进而分配至对应节点。读取时,根据槽位找到相应节点直接操作。
54 12
|
20天前
|
NoSQL Linux Redis
06- 你们使用Redis是单点还是集群 ? 哪种集群 ?
**Redis配置:** 使用哨兵集群,结构为1主2从,加上3个哨兵节点,总计分布在3台Linux服务器上,提供高可用性。
325 0

推荐镜像

更多