Nodejs接入NCR redis集群连接踩坑分享

一、简介Redis集群技术

到目前为止,主流的redis集群技术的实现主要有基于redis client(客户端分片)、基于redis proxy(代理分片)与基于redis cluster三种方式。


1.  客户端分片(client分片)

这种方案将分片工作放在业务程序端,程序代码根据预先设置的路由规则,直接对多个Redis实例进行分布式访问。Redis实例的增减,都得手工调整分片程序。

这样的好处是,不依赖于第三方分布式中间件,实现方法和代码都自己掌控,可随时调整,不用担心踩到坑。这种分片机制的性能比代理式更好(少了一个中间分发环节)。但缺点是升级麻烦,对研发人员的个人依赖性强——需要有较强的程序开发能力做后盾。如果主力程序员离职,可能新的负责人,会选择重写一遍。

所以,这种方式下,可运维性较差。出现故障,定位和解决都得研发和运维配合着解决,故障时间变长。


2. 代理分片(proxy分片)

该方式将分片工作交给专门的代理程序来做。代理程序接收到来自业务程序的数据请求,根据路由规则,将这些请求分发给正确的Redis实例并返回给业务程序。

这种机制下,一般会选用第三方代理程序(而不是自己研发),因为后端有多个Redis实例,所以这类程序又称为分布式中间件。

这样的好处是,业务程序不用关心后端Redis实例,运维起来也方便。虽然会因此带来些性能损耗,但对于Redis这种内存读写型应用,相对而言是能容忍的。

代理分片目前最流行的分布式中间件有Twitter出的twemproxy、豌豆荚开发的Codis,以及网易的NCR集群。


3. redis cluster

Redis clusterredis 3.0版本开始支持的特性。

所有的redis节点彼此互联(PING-PONG机制),内部使用二进制协议优化传输速度和带宽。节点的fail是通过集群中超过半数的节点检测失效时才生效。

客户端与redis节点直连,不需要中间proxy层,客户端不需要连接集群所有节点,连接集群中任何一个可用节点即可。由于proxy方式最快的响应速度也只能达到单台redis的速度。在这一点上,大集群环境下相比proxy分片, redis cluster性能上会提升4倍以上。

redis-cluster把所有的物理节点映射到[0-16383]slot,cluster 负责维护node<->slot<->value

redis cluster的容错机制是:

    a:如果集群任意master挂掉,且当前master没有slave.集群进入fail状态,也可以理解成进群的slot映射[0-16383]不完成时进入fail状态.

    b:如果进群超过半数以上master挂掉,无论是否有slave集群进入fail状态。


二、nodejs接入NCR踩得坑

    Redis官方推荐的nodejs redis-client连接件且至今依然维护稳定的有支持clusterioredisthunk-redisfast-redis-cluster和不支持clusternode_redisspaderedis-fast-driver

    经过跟NCR确认,接入NCRredis-cli不需要额外支持redis-cluster协议,redis节点版本为redis2.8,即采用官方推荐的node_redis作为连接件。

    安装命令:npm install redis –save

    配置项:

    


    然而并不能正常连接,错误日志:

由于只使用了connect命令和auth命令,笔者并没有添加其他的redis指令。初期分析并不存在使用了NCR所不支持的redis命令(由于ncr使用proxy代理,诸如keysmultiredis命令并不支持,如果使用相关命令会强制中断连接而不报错。)

咨询了NCR,该错误大概率还是由于使用了NCR所不支持的命令导致,连接被强制中断(而单节点redis则不报错)。

查看node_redis源码,哪里会发送所不支持的redis命令呢?

最后发现node_redis原理(包括ioredis等中间件),发送请求连接以后,会默认发送一个info指令,等到info得到响应成功以后即进入ready状态。

而恰恰是这个info指令导致了NCR中断连接。

重新配置:

加入no_ready_check,即不允许ncr连接以后发送info请求,即可正常使用ncr了。

网易云新用户大礼包:https://www.163yun.com/gift

本文来自网易实践者社区,经作者陈盛授权发布。