背景面试
先澄清一下,整个过程问题都不是我解决的,我在里面就是起了个打酱油的角色。由于实际上我负责这个项目,整个过程也比较清楚。以前也跟具体负责的同事说过,等过段时间带他作作项目复盘。结果一直忙,以前作的事情都快忘了也没带他作复盘。因此趁着还记得,总结一下这个问题,也算一块儿作个复盘总结了。redis
本周一的时候,咱们测试环境遇到一个问题:启动一个服务就会致使后端调用耗时增长。当时咨询了对这个问题以前有了解的同事获得的答复是由于一笔请求发到两套测试环境(一个请求须要在两套环境下运行结果作对比),由于这两套环境共用同一套redis集群。收到第二个相同请求的时候,会将这笔请求标记为重复请求。下游接收到这笔请求是重复的,须要从新查询数据库验证请求是否重复,不是的话作一个纠正。因此这时候会形成请求延迟升高。数据库
负责解决这个问题的同事小A就问我:那是否是再搭建一套将两套Redis集群分开就解决了。我说不必定,还有解释不通的地方:一个环境服务不启动不写redis,另外一个环境服务启动写redis的时候也会遇到这个问题。后端
因而小A找了这个服务相关负责的同事了解业务。由于测试环境的总责任人是我,因此了解业务的时候,小A也把我拉了一块儿了解。经过同事的讲述了解到一个环境中服务要写两个机房。若是两个机房的Redis是同一套也会被标记成重复请求。缓存
至此,解决环境问题的方法有了答案:每套环境要搭建两套Redis集群,两个环境4套Redis集群来解决问题。服务器
每每,一个答案只是一系列问题的开始。架构
时间线ssh
咱们的搭建方案是直接在使用Redis的服务上搭建链接它的两套Redis集群,只改下端口,多跑两个进程。tcp
问题1:服务器退出登陆Redis服务会中止分布式
小A告诉我遇到问题的现象:按照网上经典的安装启动教程,启动成功了。可是当干会儿别的,ssh自动退出登陆以后再看Redis服务就中止了。
我听到这里首先想到的是这个现象基本能够判定是以非daemon进程在运行,因而我上网上找了以deamon方式运行的命令发给小A:
redis-server ./redis.conf --daemonize yes
小A看了解决方法补充到那必定也能够在配置文件里直接配置daemon方式运行。我表示赞同,他也是这么作的。我当时没有点破,相信刚毕业的他不久也本身会发现配置文件和显示命令其实是一回事。只是一个是永久生效,一个是每次运行时生效。而直接用这条命令只是为了说明本质问题。
问题2:服务链接Redis报错Not Auth
小A又向我反馈报了一个错,说他在网上查的是Redis版本问题,估计须要从新搭建Redis。我过去看了一下:Redis集群是3.X的版本,jedis客户端用的是2.9的版本。没有据说过Redis3.X的版本有不向下兼容的问题,同时由于这个Redis是从负责Redis的团队要过来的安装包,应该和如今跑着的是一个版本。若是怀疑Redis的团队发的安装包与以前不同的话,我也确信以前确定版本不会低于3.0,由于Redis是从3.0以后才支持集群的。因此我断定不是Redis版本问题。让他再查查。实际上个人意思是让他换关键词来查。好比能够按照报错的提示缘由来查,也能够按照异常来查,不一样的关键词搜索能够得到不一样的信息。
而后我看了报的错:其余的没细看,只见赫然写着:Not Auth。我就问:Redis服务有没有设置密码。他说没有,还演示了一下,我在旁边确认了没有。就查看客户端配置有没有配置密码。果真客户端里有密码配置。这就与服务端不匹配了。
问题3:报错cluster support disabled
小A将客户端密码去掉从新打包部署以后,Not Auth的错不报了,可是其实报了两个错,还有一个错没解决:就是提示cluster support disabled。
我说集群方式启动应该就是一个配置,应该有个cluster-enabled什么的从no改为yes。我还出了个馊主意(注意这里用到的馊主意,想一想《红楼梦》里每句话都是剧透,这里也不例外):我说理论上一台集群也能够算一个集群。应该能够直接改个配置就以集群方式启动了。
小A按照我说的思路用直接改配置为集群的方法,客户端再启动果真没有报错了。
问题4:请求延迟没有好转,Redis服务端没有写入成功数据
客户端没有报错以后,小A重试原问题现场,请求延迟没有好转。另外,还发现Redis服务端没有写入成功的数据。
此次我和小A首先一块儿排查配置有没有配置对。发现配置没有问题,我就跟小A说:让他多打日志。客户端链接的地方打一些,读写数据的地方打一些。
经过这个方法,小A定位到客户端链接的链接池为空。最终本身排查到是一台机器的集群的哈希槽在一台机器状况下哈希槽分配有问题,数据写入失败。最后每一个集群多起了2个Redis进程作成3个节点的集群解决了问题。
可优化的排查思路分析
在问题4排查的时候,我和小A一块儿检查了配置是否正确来确认Redis请求是请求到了正确的服务端。其实,有个更为直接和说明问题的方法:抓包。能够tcpdump端口查请求流量是否是正确从客户端发出来了,被转发到了哪里。
在《技术方案设计的方法》里我也提到,不少时候搜索不到本身想要的信息极可能是关键词的问题。排查问题的时候也能够试着换换关键词来搜索。
根本缘由分析
这里面有个问题没有完全搞清楚:为何一台机器的Redis集群会有问题。
问了小A,当时异常时getSlots方法时返回了空。就是说问题实际上多是slot没有被分配。
我就问他单台机器的时候有没有在redis-cli客户端上运行cluster info命令。他给我发了下面的运行状况截图。
这张截图验证了个人猜测,slot没有被分配,集群状态为失败,因此链接不上。
那须要链接上的条件并不是是集群里有几个节点,而是slots分配,集群状态成功。
为了验证这个猜测,我搭建了一个一个节点的集群,手动cluster addslots了0到16383个slot。集群判断16384个slot都分配完毕,自动状态改为OK。
这整个过程说明了:网上都是说Redis集群必须是3个节点以上的最好是单数个节点来启动。单数个节点是为了投票的时候能够三局两胜得出结论:一半以上的节点挂掉整个集群不可用。而对于Redis根本上判断集群是否可用是根据slot有没有完整的16384个slot在提供服务决定的。
总结
我以为在整个过程当中小A的表现我以为很OK的。有4点:
1>主观能动性
在过程当中,他本身经过网上搜素找资源,本身解决了不少问题。整个问题处理过程当中其实没花费我多少时间,花时间的事情他都本身解决了。
2>合理的利用了各类资源
对于业务不理解,他找了理解业务的同事。技术问题搞不定他找了我。由于我对项目负责,因此找我是很合情合理的。同时,我是很但愿他遇到这种事情来找个人。由于他找我证实他是信任个人,相信我能必定程度帮到他。第二,他找我是把我当成一种资源。做为资源我被须要,是有价值的。被须要让人以为很踏实。
我在有搞不定的事情的时候也向上寻求帮助。好比以前须要其余组协做的时候人家有排期遇到困难,领导出面帮忙搞定了。还有申请资源因为暂时性资源紧张,申请不到,也是更上级出面帮忙搞定了。一个称职的上级必定能够成为一种资源,也愿意让本身成为资源。可是成为资源的形式不一样,有的可能提供的是战略,有的提供的是精神支持等。
3>过后总结
问题解决后,小A有本身写wiki总结事情通过,避免后人采坑,同时自身也有总结收获。
4>及时沟通
中间过程当中,他每一个关键步骤都有及时跟我沟通。由于解决完后他反馈给我:他本身以为对于redis原理尚未理解,因此不清楚为何3个节点就OK的缘由。我由于了解他的想法,因此才本身又实验给出一个根本缘由分析。
关于Redis,就一句话:那些不少人说只有面试的时候才能用到的东西,我老是发现实际工做中颇有用。
相关阅读