架构师之路-redis集群解析
引子

上篇《架构师之路-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集群解析的更多相关文章
- 【架构师之路】集群/分布式环境下5种session处理策略
[架构师之路]集群/分布式环境下5种session处理策略 转自:http://www.cnblogs.com/jhli/p/6557929.html 在搭建完集群环境后,不得不考虑的一个问题就是 ...
- Couchbase集群和Redis集群解析
Couchbase集群和Redis集群解析 首先,关于一些数据库或者是缓存的集群有两种结构,一种是Cluster;一种是master-salve. 关于缓存系统一般使用的就是Redis,Redis是开 ...
- linux运维、架构之路-redis集群
一.介绍 redis cluster 3.0之后的功能,至少需要3(Master)+3(Slave)才能建立集群,是无中心的分布式存储架构,可以在多个节点之间进行数据共享,解决了 ...
- (转)高性能网站架构之缓存篇—Redis集群搭建
看过 高性能网站架构之缓存篇--Redis安装配置和高性能网站架构之缓存篇--Redis使用配置端口转发 这两篇文章的,相信你已经对redis有一定的了解,并能够安装上,进行简单的使用了,但是在咱们的 ...
- (转)高性能网站架构之缓存篇—Redis集群增删节点
标签: 高性能架构集群缓存redis 上一篇文章,我们搭建了Redis-cluster集群,这篇博客跟大家讲一下如何在一个运行的集群上增加节点或者删除节点. Redis集群添加节点 首先我们要新建立一 ...
- windows下rabbitmq(架构师必备神器)集群搭建
准备2台机器,例如:computera: 10.0.0.151 computerb:10.0.0.234 都安装erlang环境和rabbitmq服务,注意otp环境和rabbitmq服务必须版 ...
- Java企业级电商项目架构演进之路 Tomcat集群与Redis分布式
史诗级Java/JavaWeb学习资源免费分享 欢迎关注我的微信公众号:"Java面试通关手册"(坚持原创,分享各种Java学习资源,面试题,优质文章,以及企业级Java实战项目回 ...
- 【原创】那些年用过的Redis集群架构(含面试解析)
引言 今天是2019年2月12号,也就是大年初八,我接到了高中同学刘有码面试失利的消息. 他面试的时候,身份是某知名公司的小码农一枚,却因为不懂自己生产上Redis是如何部署的,导致面试失败! 人间惨 ...
- 【转】那些年用过的Redis集群架构(含面试解析)
引言 今天是2019年2月12号,也就是大年初八,我接到了高中同学刘有码面试失利的消息. 他面试的时候,身份是某知名公司的小码农一枚,却因为不懂自己生产上Redis是如何部署的,导致面试失败! 人间惨 ...
随机推荐
- pycharm的常规使用
1.修改当前项目的Py版本,是py2还是py3 pycharm-->settings-->选中要运行的项目-->选择py版本(如果你两个py版本都装在本机的话) 2.显示行数 在每行 ...
- electron-vue 开发问题合集
(一)Found 'electron' but not as a devDependency, pruning anyway 原因:对electron没有严格要求的话可以忽略,不影响打包,但会影响第三 ...
- Javascript 判断 iframe 中的变量是否为对象
Javascript 判断 iframe 中的变量是否为对象 前言 公司之前的项目中,为了实现模块化,在 web 后端使用了 iframe 来组织框架和页面.由于当时没有很好地规划,iframe 子页 ...
- 微信小程序适配iphoneX的实现方法
一. 安全区域(safe area) 与iPhone6/6s/7/8相比,iPhone X 无论是在屏幕尺寸.分辨率.甚至是形状上都发生了较大的改变,下面以iPhone 8作为参照物,先看看iPhon ...
- Jenkins操作手册 - 巨详细,一篇足矣!
一.继续集成相关概念 1.1.什么是持续集成? 随着软件开发复杂度的不断提高,团队开发成员间如何更好的协同工作以确保软件开发的质量已经成为开发过程中不可回避的问题.尤其是近年来敏捷开发在软件领域越来越 ...
- Shell系列(11)- 位置参数变量(4)
作用 往shell脚本里面传递参数 位置参数变量 作用 $n n 为数字,$0 代表命令本身,$1-$9 代表第一到第九个参数,十以上的参数需要用大括号包含,如 ${10} $* 这个变量代表命令行中 ...
- Linux系列(37) - 源码包与RPM包区别(1)
源码包是不能使用[service]命令来启动服务,因为源码包的安装位置由用户指定 源码包一般安装在: /usr/local/软件名/ ,源码包安装的服务,只能用绝对路径进行服务的管理 rpm包安装后, ...
- 超详细unittest单元测试框架总结
unittest单元测试框架不仅可以适用于单元测试,还可以适用WEB自动化测试用例的开发与执行,该测试框架可组织执行测试用例,并且提供了丰富的断言方法,判断测试用例是否通过,最终生成测试结果.今天笔者 ...
- 远程连接centos7中mysql8.0
远程连接centos7中mysql8.0 1.使用Navicat for MySQL或者其它数据连接软件 2.先检查centos中防火墙是否关闭,如果关闭不需要设置,如果没有关闭防火墙,请打开3306 ...
- kafka高可用探究
kafka高可用探究 众所周知 kafka 的 topic 可以使用 --replication-factor 数和 partitions 数来保证服务的高可用性 问题发现 但在最近的运维过程中,3台 ...