1、稳定性
- 不扩容时集群非常稳定。
- 扩容resharding时候,早期版本的Jedis端有时会出现“max-redirect”异常。
分析Jedis源码,请求重试次数达到了上限,仍然没有请求成功。两方面分析:redis连接不上?还是集群节点信息不一致? - 存活检测机制缺陷:Redis存活检测机制可能因为master节点上慢查询、阻塞式命令、或者其它的性能问题导致长时间没有响应,这个节点会认为处于failed状态,并进行切换。这种切换是没必要的。
优化策略:
a) 默认的cluster-node-timeout为15s,可以适当增大;
b) 避免使用会引起长时间阻塞的命令,比如save/flushdb等阻塞操作,或者keys pattern这种慢查询。
总体来说,redis cluster已经非常稳定了,但是要注意一些应用中的小问题,下面是5个坑,大家注意了.
2、有哪些坑?
2.1 迁移过程中Jedis“Max Redirect”异常
- github上讨论的结果是程序retry。
- max redirt issues:https://github.com/xetorthio/jedis/issues/1238
- retry时间应该大于failover 时间。
- Jedis参数优化调整:增大jedis中的‘DEFAULT_MAX_REDIRECTIONS’参数,默认值是5.
- 避免使用multi-keys操作,比如mset/mget. multi-key操作有些客户端没有支持实现。
2.2 长时间阻塞引起的不必要的failover
- 阻塞的命令。比如save/flushall/flushdb
- 慢查询。keys *、大key的操作、O(N)操作
- rename危险操作:
- rename-command FLUSHDB REDIS_FLUSHDB
- rename-command FLUSHALL REDIS_FLUSHALL
- rename-command KEYS REDIS_KEYS
2.3 同时支持ipv4和ipv6侦听服务埋下的坑
具体现象:redis启动正常,节点的协议端口只有ipv6 socket创建正常。异常节点也无法加入到集群中,也无法获取epoch。
解决方法:启动时指定网卡ipv4地址,也可以是0.0.0.0,配置文件中添加:bind 0.0.0.0
这个是在setup集群的时候发生过的一个问题,bind 0.0.0.0虽然存在一些安全性问题,但是是比较简单通用的解决方法。
2.4 数据迁移速度较慢
- 主要使用的redis-trib.rb reshard来完成数据迁移。
- redis-3.0.6版本以前migrate操作是单个key逐一操作。从redis-3.0.6开始,支持单次迁移多个key。
- redis集群内部最多只允许一个slot处于迁移状态,不能并发的迁移slots。
- redis-trib.rb reshard如果执行中断,用redis-trib.rb fix修复集群状态。
2.5 版本选择/升级建议
- 我们已经开始使用3.0.7版本,很多3.2.0修复的bug已经backport到这个版本。
- 另外我们也开始测试3.2.0版本,内存空间优化很大。
Tips
- redis-trib.rb支持resharding/rebalance,分配权重。
- redis-trib.rb支持从单个redis迁移数据到cluster集群中。
后面2点不算坑把,算是不足,tips也很实用,开始分享下最佳实践。
3、最佳实践
3.1 应用做好容错机制
- 连接或者请求异常,进行连接retry和reconnect。
- 重试时间应该大于cluster-node-time时间,还是强调容错,这个不是针对cluster,所有的应用设计都适用。
3.2 制定开发规范
- 慢查询,进程cpu 100%、客户端请求变慢,甚至超时。
- 避免产生hot-key,导致节点成为系统的短板。
- 避免产生big-key,导致网卡打爆、慢查询。
- TTL, 设置合理的ttl,释放内存。避免大量key在同一时间段过期,虽然redis已经做了很多优化,仍然会导致请求变慢。
- 合理的key命名规则。
- 避免使用阻塞操作,不建议使用事务。
PS:开发规范,使你们的开发按照最优的方式使用nosql。
3.3 优化连接池使用
- 主要避免server端维持大量的连接。
- 合理的连接池大小。
- 合理的心跳检测时间。
- 快速释放使用完的连接。
- Jedis一个连接创建异常问题(fixed):https://github.com/xetorthio/jedis/issues/1252
连接问题是redis开发使用中最常见的问题,connection timeout/read timeout,还有borrow connection的问题。
3.4 区分redis/twemproxy和cluster的使用
- redis建议使用pipeline和multi-keys操作,减少RTT次数,提高请求效率。
- twemproxy也支持pipeline, 支持部分的multi-key可以操作。
- redis cluster不建议使用pipeline和multi-keys操作,减少max redirect产生的场景。
区分redis和cluster的使用,一方面是数据分片引起的;另一方面,与client的实现支持相关。
3.5 几个需要调整的参数
1)设置系统参数vm.overcommit_memory=1,可以避免bgsave/aofrewrite失败。
2)设置timeout值大于0,可以使redis主动释放空闲连接。
3)设置repl-backlog-size 64mb。默认值是1M,当写入量很大时,backlog溢出会导致增量复制不成功。
4)client buffer参数调整
client-output-buffer-limit normal 256mb 128mb 60
client-output-buffer-limit slave 512mb 256mb 180
本内容来自唯品会Redis Cluster大规模生产实践文章。