本文并非介绍如何搭建一个集群,也不是介绍集群如何使用,重点是分享一些大家在使用集群过程中经常遇到的,经常提出来的问题:
问题一 Exception: Could not get resource from pool
使用jedis客户端,无论缓存是以集群模式还是单点模式部署,凡是遇到这种问题,归结于无法从连接池中获取到连接,那么哪些原因导致获取链接失败呢?
1.1 跨机房访问,注意网络是否可以访问,有无防火墙;
1.2 本机访问,若redis以单机模式部署,注意是否启用密码认证;
1.3 redis.conf配置bind是否绑定本地ip地址(建议绑定本地真实ip地址);
1.4 若前置已部署代理,检查代理服务是否正常运行;
1.5 最后必须保证redis服务正常运行,另外配置的ip与port都是正确的;
问题二 JedisRedirectionException: Too many cluster directions
问题分析有两种异常造成:
2.1 JedisMovedDataException:节点迁移后重新renew本地slot与redis节点的映射Map
2.2 JedisAskDataException:数据正在迁移,发生asking问题, 获取asking的 Jedis,此过程最多循环redirections次。
这种异常说明重定向redirections次,仍然没有找到可以处理的节点来完成本次redis操作。原因主要包括但不限于以下几点:
1. 压测遇到的超时比较多,默认超时时间是2000ms
1.1 网络原因:比如是否存在跨机房、网络闪断等。
1.2 存在慢查询的操作,因为redis是单线程,如果有慢查询的话,会阻塞后续操作。
1.3 value值过大(如二进制流),可能性非常小
1.4 aof文件正在重写,rdb文件或 aof文件正在fork进程
2. 节点之间槽位发生变化,会发生JedisMovedDataException
3. 节点之间发生数据迁移,会发生JedisAskDataException
问题三 ASK转向与MOVED转向区别及场景介绍
MOVED转向通常发生在集群稳定状态下:若向node-1节点发送key1请求,经过CRC算法计算出key1的slot值,若slot值属于node-1节点的处理范围则直接处理,若不属于node-1节点的处理范围则返回moved异常和能够处理该slot的节点信息(格式:-MOVED SLOT IP:PORT),注:集群中每个节点都记录其他节点的信息。客户端的实现会根据返回的-MOVED转向来将请求再次转发到正确的节点处理。若集群slot不断地发生迁移,那么客户端会不断地根据服务端返回的-MOVED转向重新转发。
ASK转向通常发生在集群slot迁移过程中:若集群正在发生slot迁移,slot迁移实质上是迁移slot中每一个key的过程,若key1经过计算slot值后路由到node-1发现slot正在发生迁移,而且该key位置已经迁移到node-2,同时这次迁移过程并没有结束(即仍然有key存在于node-1中),那么返回给客户端ASK转向。客户端根据ASK转向将key1转发到node-2中,注意这次转发是基于请求的临时转发,下次请求key2依然根据CRC算法计算slot值若位于node-1将继续转发请求到node-1。若迁移过程结束,所有的key请求经过计算slot值永久的路由到实际的目标节点。
问题四 集群通信方式以及选举过程介绍
集群节点通过gossip协议进行互相关注(ping),若集群发现某个节点长期没有收到(+pong)响应,那么会每秒一次进行跟踪疑似下线的节点。选举是通过raft算法进行选举,选举过程不予介绍。重点介绍集群在选举过程中可能存在的问题:若master节点跟随的slave节点比较多的话,那么选举的过程耗时略微长一点。那么在这个过程中,所有被路由到这个节点处理的请求均抛出异常。
5. 集群不支持的功能大汇总
5.1 事务,不管是数据库还是缓存跨节点的事务很棘手
5.2 Pipeline,队列命令涉及到命令的分发和结果聚合
5.3 密码认证,多节点认证比较难以协调
5.4 mget/mset,多命令操作涉及到命令分发与聚合
5.5 涉及到multi-key的操作或者跨节点的操作均不支持
6. 停机数据备份或迁移简单方案介绍
不少网友问到数据迁移,如跨级房迁移,或者select 1迁移至select 0,这样的场景最简便的方案是备份物理文件拷贝过去,注意若将select 1迁移到select 0,只需要将aof文件中的select 1改成select 0,redis服务启动默认优先通过aof来恢复数据的。
7. 是否有必要开启rdb或者aof备份
开启rdb,aof的好处就是备份,主从复制,最新的redis已经支持diskless的发送复制流(即无需将复制的信息写入磁盘而是直接发送给slave节点,见redis.conf参数repl-diskless-sync),当然这个功能现在使用的也很少,风险比较大。那么开启rdb,aof的缺点,fork进程,作者使用高压测试,发现后台fork进程复制的速度是比较慢的,起码肉眼能看到。
。。。待完善。。。