架构师之路-redis集群解析

本文涉及的产品
云数据库 Tair(兼容Redis),内存型 2GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
简介: 架构师之路-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
相关文章
|
2月前
|
运维 持续交付 云计算
深入解析云计算中的微服务架构:原理、优势与实践
深入解析云计算中的微服务架构:原理、优势与实践
96 1
|
2月前
|
运维 监控 负载均衡
探索微服务架构下的服务治理:动态服务管理平台深度解析
探索微服务架构下的服务治理:动态服务管理平台深度解析
|
1月前
|
运维 监控 持续交付
微服务架构解析:跨越传统架构的技术革命
微服务架构(Microservices Architecture)是一种软件架构风格,它将一个大型的单体应用拆分为多个小而独立的服务,每个服务都可以独立开发、部署和扩展。
317 36
微服务架构解析:跨越传统架构的技术革命
|
1月前
|
存储 Linux API
深入探索Android系统架构:从内核到应用层的全面解析
本文旨在为读者提供一份详尽的Android系统架构分析,从底层的Linux内核到顶层的应用程序框架。我们将探讨Android系统的模块化设计、各层之间的交互机制以及它们如何共同协作以支持丰富多样的应用生态。通过本篇文章,开发者和爱好者可以更深入理解Android平台的工作原理,从而优化开发流程和提升应用性能。
|
2月前
|
弹性计算 持续交付 API
构建高效后端服务:微服务架构的深度解析与实践
在当今快速发展的软件行业中,构建高效、可扩展且易于维护的后端服务是每个技术团队的追求。本文将深入探讨微服务架构的核心概念、设计原则及其在实际项目中的应用,通过具体案例分析,展示如何利用微服务架构解决传统单体应用面临的挑战,提升系统的灵活性和响应速度。我们将从微服务的拆分策略、通信机制、服务发现、配置管理、以及持续集成/持续部署(CI/CD)等方面进行全面剖析,旨在为读者提供一套实用的微服务实施指南。
|
1月前
|
存储 NoSQL Redis
redis主从集群与分片集群的区别
主从集群通过主节点处理写操作并向从节点广播读操作,从节点处理读操作并复制主节点数据,优点在于提高读取性能、数据冗余及故障转移。分片集群则将数据分散存储于多节点,根据规则路由请求,优势在于横向扩展能力强,提升读写性能与存储容量,增强系统可用性和容错性。主从适用于简单场景,分片适合大规模高性能需求。
58 5
|
2月前
|
存储 监控 API
深入解析微服务架构及其在现代应用中的实践
深入解析微服务架构及其在现代应用中的实践
84 12
|
2月前
|
NoSQL Java 数据处理
基于Redis海量数据场景分布式ID架构实践
【11月更文挑战第30天】在现代分布式系统中,生成全局唯一的ID是一个常见且重要的需求。在微服务架构中,各个服务可能需要生成唯一标识符,如用户ID、订单ID等。传统的自增ID已经无法满足在集群环境下保持唯一性的要求,而分布式ID解决方案能够确保即使在多个实例间也能生成全局唯一的标识符。本文将深入探讨如何利用Redis实现分布式ID生成,并通过Java语言展示多个示例,同时分析每个实践方案的优缺点。
87 8
|
2月前
|
SQL 数据可视化 数据库
多维度解析低代码:从技术架构到插件生态
本文深入解析低代码平台,涵盖技术架构、插件生态及应用价值。通过图形化界面和模块化设计,低代码平台降低开发门槛,提升效率,支持企业快速响应市场变化。重点分析开源低代码平台的优势,如透明架构、兼容性与扩展性、可定制化开发等,探讨其在数据处理、功能模块、插件生态等方面的技术特点,以及未来发展趋势。
|
2月前
|
负载均衡 Java 持续交付
深入解析微服务架构中的服务发现与负载均衡
深入解析微服务架构中的服务发现与负载均衡
114 7

推荐镜像

更多