对分布式存储系统的架构和运维管理,如何保证每个Node的数据存储容量和请求量尽量均衡,是非常重要的。
本文介绍Redis大集群运维过程中,常见导致数据和请求量“倾斜”的场景,及规避措施。
Redis数据容量或请求量严重”倾斜”的影响
以下从运维的角度解释,Redis数十节点的集群,出现数据容量和请求量倾斜情况下,存在的一些痛点:
- 少数或单个节点请求量”过热”,导致Redis分布式系统失去可扩展性能力和集群的意义。类似MongoDB_id字段作为片键。
- 导致运维容量规划,扩容处理难度大。
- 增大自动化配置管理难度;单集群节点尽量统一参数配置。
- 监控告警复杂(容量,QPS,连接数的阈值等)
那我们再看生产环境中,常见导致Redis集群严重“倾斜”的场景
Redis集群常见“倾斜”的场景
这类问题一般DBA规划不当,业务键空间(keyspace)设计不合理等问题导致
- DBA在规划集群时或扩容后,导致数据槽(哈希桶)位分配不均匀;引起内存容量、键个数和请求QPS倾斜
- 业务的键空间设计不合理,所谓”热点key”,导致某少量KEY的QPS操作很大;这类节点QPS过载
- 程序大量使用 Keys hash tags, 可能导致某些数据槽位的键个数较多
- 程序存在大的集群key(hash,set,list等),导致大key所在节点的容量和QPS过高
- 工和师执行Monitor这类命令,导致当前节点client输出缓冲区增大;used_memory_rss被撑大;导致节点内存容量增大
接下来,当集群出现内存容量、键数量或QPS请求量严重倾斜时,我们应该排查定位问题呢?
Redis集群“倾斜”问题排查
检查集群每个分片的数据槽分配是否均匀
下面以Redis Cluster集群为例
确认集群中,每个节点负责的数据槽位(slots)和key个数。下面demo的部分实例存在不轻度“倾斜”
但不严重,可考虑进行reblance.
1 2 3 4 5 6 7 8 9 10 11 | redis-trib.rb info redis_ip:port nodeip:port (5e59101a...) -> 44357924 keys | 617 slots | 1 slaves. nodeip:port (72f686aa...) -> 52257829 keys | 726 slots | 1 slaves. nodeip:port (d1e4ac02...) -> 45137046 keys | 627 slots | 1 slaves. ---------------------省略------------------------ nodeip:port (f87076c1...) -> 44433892 keys | 617 slots | 1 slaves. nodeip:port (a7801b06...) -> 44418216 keys | 619 slots | 1 slaves. nodeip:port (400bbd47...) -> 45318509 keys | 614 slots | 1 slaves. nodeip:port (c90a36c9...) -> 44417794 keys | 617 slots | 1 slaves. [OK] 1186817927 keys in 25 masters. 72437.62 keys per slot on average. |
排查节点热点Key,确定top commands.
使用 redis-faina,当然有实时分析平台就更好。
从以下示例中,可见两个前缀key的QPS占比基本各为50%, 明显热点key;也能看到auth命令的异常(top commands)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | Overall Stats ======================================== Lines Processed 100000 Commands/Sec 7276.82 Top Prefixes ======================================== ar_xxx 49849 (49.85%) Top Keys ======================================== c8a87fxxxxx 49943 (49.94%) a_r:xxxx 49849 (49.85%) Top Commands ======================================== GET 49964 (49.96%) AUTH 49943 (49.94%) SELECT 88 (0.09%) |
程序是否大量使用Keys hash tags
可能导致数据存储内存量,QPS都不均匀的问题;
可使用scan扫描keyspace是否有使用hash tags的,或使用monitor, vc-redis-sniffer
程序是否使用较大的集合键
比如1kw个字段的hash key, 内存占用在几个GB. 这类集合key每次操作几个字段,很难从proxy或sdk发现key的大小。 可通过redis-cli –bigkeys
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | redis-cli --bigkeys -p 7000 # Scanning the entire keyspace to find biggest keys as well as # average sizes per key type. You can use -i 0.1 to sleep 0.1 sec # per 100 SCAN commands (not usually needed). [00.00%] Biggest string found so far 'key:000000019996' with 1024 bytes [48.57%] Biggest list found so far 'mylist' with 534196 items -------- summary ------- Sampled 8265 keys in the keyspace! Total key length in bytes is 132234 (avg len 16.00) Biggest string found 'key:000000019996' has 1024 bytes Biggest list found 'mylist' has 534196 items 8264 strings with 8460296 bytes (99.99% of keys, avg size 1023.75) 1 lists with 534196 items (00.01% of keys, avg size 534196.00) |
确认是否因monitor命令引起的输出缓冲区占用内存过大的问题
这类情况基本Redis实例内存会快速增长,很快会出现回落。通过监测client输出缓冲区使用情况
1 2 3 4 5 6 7 8 9 10 11 | 2.5.1 通过监控client_longest_output_list输出列表的长度,是否有client使用大量的输出缓冲区. redis-cli -p 7000 info clients # Clients connected_clients:52 client_longest_output_list:9179 client_biggest_input_buf:0 blocked_clients:0 2.5.2 查看输出缓冲区列表长度不为0的client。 可见monitor占用输出缓冲区370MB redis-cli -p 7000 client list | grep -v "oll=0" id=1840 addr=xx64598 age=75 idle=0 flags=O obl=0 oll=15234 omem=374930608 cmd=monitor |
如何有效避免Redis集群“倾斜”问题
- 集群部署和扩容处理,保证数据槽位分配平均
- keyspace设计时,如何避免热点key, 打散热key
- 业务在键空间设计时,中尽量避免使用大的集合类型的Key,把key设计拆分
- 程序角度尽量避免使用keys hash tag
- 避免工程师直接使用keys,monitor等命令,导致输出缓冲区堆积.
- 合量配置normal的client output buffer, 建议设置10mb(警示:和业务确认调整再修改,避免业务出错)
在实际生产业务场景中,大规模集群很难做到集群的完全均衡,只是尽量保证不出现严重倾斜问题。