经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 数据库/运维 » Redis » 查看文章
优化 Redis 集群缓存分配:解决节点间分配不均导致内存溢出问题
来源:cnblogs  作者:查拉图斯特拉面条  时间:2023/8/16 9:14:20  对本文有异议

一、Redis 集群部署简介

在现代应用程序中,缓存被广泛应用以提高性能和减轻后端数据库的压力。本文将探讨面对 Redis 集群缓存分配不均问题时的解决方法。

我们的 Redis 集群部署包括 3 主 3 从,每个节点分配内存 4G(服务器总内存32G),内存淘汰策略相同:volatile-lru

二、问题描述

在性能测试过程中,通过 pinpoint 监控发现报错:OOM

  1. Error in execution; nested exception is io.lettuce.core.RedisCommandExecutionException: OOM command not allowed when used memory> 'maxmemory'

三、排查、分析问题过程

1. 查看内存使用情况

清空缓存后,再次执行性能测试一段时间,使用 info memory 查看各节点内存使用情况,发现 2、6 节点内存快速上升,其它节点内存使用率很低。

例如,2 节点内存达到 3.81G,6 节点内存达到 3.8G,而其他 4 个节点内存仅为 80M 左右。

  1. [root@iZ2ze3e0bvnd1hf5xbkxn3Z redis01]# ./redis-cli -h 192.168.0.213 -p 6692 -c -a Tiye@54L2!
  2. Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
  3. 192.168.0.213:6692> info memory
  4. # Memory
  5. used_memory:4095914816
  6. used_memory_human:3.81G
  7. used_memory_rss:4473937920
  8. used_memory_rss_human:4.17G
  9. used_memory_peak:4105896552
  10. used_memory_peak_human:3.82G
  11. used_memory_peak_perc:99.76%
  12. used_memory_overhead:5159996
  13. used_memory_startup:1483832
  14. used_memory_dataset:4090754820
  15. used_memory_dataset_perc:99.91%
  16. allocator_allocated:4095978056
  17. allocator_active:4728315904
  18. allocator_resident:4765335552
  19. total_system_memory:33019609088
  20. total_system_memory_human:30.75G
  21. used_memory_lua:30720
  22. used_memory_lua_human:30.00K
  23. used_memory_scripts:0
  24. used_memory_scripts_human:0B
  25. number_of_cached_scripts:0
  26. maxmemory:4096000000
  27. maxmemory_human:3.81G
  28. maxmemory_policy:volatile-lru
  29. allocator_frag_ratio:1.15
  30. allocator_frag_bytes:632337848
  31. allocator_rss_ratio:1.01
  32. allocator_rss_bytes:37019648
  33. rss_overhead_ratio:0.94
  34. rss_overhead_bytes:-291397632
  35. mem_fragmentation_ratio:1.09
  36. mem_fragmentation_bytes:378064128
  37. mem_not_counted_for_evict:0
  38. mem_replication_backlog:1048576
  39. mem_clients_slaves:20512
  40. mem_clients_normal:2603516
  41. mem_aof_buffer:0
  42. mem_allocator:jemalloc-5.1.0
  43. active_defrag_running:0
  44. lazyfree_pending_objects:0
  45. lazyfreed_objects:0
  1. [root@iZ2ze3e0bvnd1hf5xbkxn3Z redis02]# ./redis-cli -h 192.168.0.213 -p 6691 -c -a Tiye@54L2!
  2. Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
  3. 192.168.0.213:6691> info memory
  4. # Memory
  5. used_memory:84125536
  6. used_memory_human:80.23M
  7. used_memory_rss:107753472
  8. used_memory_rss_human:102.76M
  9. used_memory_peak:109050608
  10. used_memory_peak_human:104.00M
  11. used_memory_peak_perc:77.14%
  12. used_memory_overhead:9292232
  13. used_memory_startup:1483832
  14. used_memory_dataset:74833304
  15. used_memory_dataset_perc:90.55%
  16. allocator_allocated:84208120
  17. allocator_active:102572032
  18. allocator_resident:108343296
  19. total_system_memory:33019609088
  20. total_system_memory_human:30.75G
  21. used_memory_lua:30720
  22. used_memory_lua_human:30.00K
  23. used_memory_scripts:0
  24. used_memory_scripts_human:0B
  25. number_of_cached_scripts:0
  26. maxmemory:4096000000
  27. maxmemory_human:3.81G
  28. maxmemory_policy:volatile-lru
  29. allocator_frag_ratio:1.22
  30. allocator_frag_bytes:18363912
  31. allocator_rss_ratio:1.06
  32. allocator_rss_bytes:5771264
  33. rss_overhead_ratio:0.99
  34. rss_overhead_bytes:-589824
  35. mem_fragmentation_ratio:1.28
  36. mem_fragmentation_bytes:23669520
  37. mem_not_counted_for_evict:0
  38. mem_replication_backlog:1048576
  39. mem_clients_slaves:20512
  40. mem_clients_normal:2603360
  41. mem_aof_buffer:0
  42. mem_allocator:jemalloc-5.1.0
  43. active_defrag_running:0
  44. lazyfree_pending_objects:0
  45. lazyfreed_objects:0

2. 分析主从关系

 使用 cluster nodes 命令获取 Redis 集群中所有节点的信息,并判断各节点主从关系。
  1. [root@iZ2ze3e0bvnd1hf5xbkxn3Z redis06]# ./redis-cli -h 192.168.0.213 -p 6696 -c -a Tiye@54L2!
  2. Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
  3. 192.168.0.213:6696> cluster nodes
  4. e73a5ec3e26ed23e9b4bf56811527c8820a7bd79 192.168.0.213:6696@16696 myself,slave e2a678a004bc99e76180a16a6a41e2cad1c96052 0 1691992895000 2 connected
  5. 25317f0f8f7b2eebdbdc0914c659ab96ed3dab18 192.168.0.213:6693@16693 master - 0 1691992897074 3 connected 10923-16383
  6. 27aba75f54cccbb42125edb20f2f9d7c2f777d6c 192.168.0.213:6695@16695 slave 5e08015f75cdb05b1c7ed78dead1d85cdb0e838f 0 1691992895070 1 connected
  7. 5e08015f75cdb05b1c7ed78dead1d85cdb0e838f 192.168.0.213:6691@16691 master - 0 1691992894068 1 connected 0-5460
  8. 053916b96426f790244d984cad3f69f9151e4ece 192.168.0.213:6694@16694 slave 25317f0f8f7b2eebdbdc0914c659ab96ed3dab18 0 1691992896072 3 connected
  9. e2a678a004bc99e76180a16a6a41e2cad1c96052 192.168.0.213:6692@16692 master - 0 1691992894000 2 connected 5461-10922

根据节点信息中的master字段判断该节点是主节点还是从节点。如果节点的master字段为空,则表示它是主节点;如果master字段不为空,则表示它是从节点,并且该字段的值是对应的主节点ID。
e2a678a004bc99e76180a16a6a41e2cad1c96052 节点是主节点,e73a5ec3e26ed23e9b4bf56811527c8820a7bd79 节点是从节点,并且它的主节点是 e2a678a004bc99e76180a16a6a41e2cad1c96052

综上判断:redis集群6个节点,其中2节点的从节点是6节点。

3. 分析哈希槽数量分配

在 Redis 集群中的任意一个节点上执行 cluster slots 命令,分析哈希槽数量分配是否均匀

  1. 192.168.0.213:6692> cluster slots
  2. 1) 1) (integer) 0
  3. 2) (integer) 5460
  4. 3) 1) "192.168.0.213"
  5. 2) (integer) 6691
  6. 3) "5e08015f75cdb05b1c7ed78dead1d85cdb0e838f"
  7. 4) 1) "192.168.0.213"
  8. 2) (integer) 6695
  9. 3) "27aba75f54cccbb42125edb20f2f9d7c2f777d6c"
  10. 2) 1) (integer) 5461
  11. 2) (integer) 10922
  12. 3) 1) "192.168.0.213"
  13. 2) (integer) 6692
  14. 3) "e2a678a004bc99e76180a16a6a41e2cad1c96052"
  15. 4) 1) "192.168.0.213"
  16. 2) (integer) 6696
  17. 3) "e73a5ec3e26ed23e9b4bf56811527c8820a7bd79"
  18. 3) 1) (integer) 10923
  19. 2) (integer) 16383
  20. 3) 1) "192.168.0.213"
  21. 2) (integer) 6693
  22. 3) "25317f0f8f7b2eebdbdc0914c659ab96ed3dab18"
  23. 4) 1) "192.168.0.213"
  24. 2) (integer) 6694
  25. 3) "053916b96426f790244d984cad3f69f9151e4ece"

根据提供的哈希槽信息,我们可以计算出以下三个哈希槽的数量:

  • 第一个哈希槽范围:0到5460,共计5461个槽位。
  • 第二个哈希槽范围:5461到10922,共计5462个槽位。
  • 第三个哈希槽范围:10923到16383,共计5461个槽位。

综上判断:这三个哈希槽的数量分别是5461、5462和5461。即,哈希槽数量分配均匀。

四、尝试解决方案

方法一:使用 Predixy 代理

跟产品开发人员沟通,没有做predixy适配,但可以尝试配置。最后发现产品启动服务报错,放弃该方案。尝试过程记录如下:

1. 下载安装包

  1. wget https://github.com/joyieldInc/predixy/releases/download/1.0.5/predixy-1.0.5-bin-amd64-linux.tar.gz

2. 解压&修改配置文件

  1. tar zxvf predixy-1.0.5-bin-amd64-linux.tar.gz
  2. cd predixy-1.0.5

① 编辑conf/predixy.conf文件

  1. Include cluster.conf #Include cluster.conf解开注释
  2. # Include sentinel.conf
  3. # Include try.conf #注释掉Include try.conf
  1. ## Worker threads
    WorkerThreads 3 #从1改为3,表示开启的进程数

② 编辑conf/cluster.conf文件

  1. lusterServerPool {
  2. MasterReadPriority 0 #设置为0代表开启读写分离
  3. Password Tiye@54L2! #redis集群密码
  4. StaticSlaveReadPriority 50
  5. DynamicSlaveReadPriority 50
  6. RefreshInterval 1
  7. ServerTimeout 1
  8. ServerFailureLimit 10
  9. ServerRetryTimeout 1
  10. KeepAlive 120
  11. Servers {
  12. + 192.168.0.213:6691 #redis集群节点
  13. + 192.168.0.213:6692
  14. + 192.168.0.213:6693
  15. + 192.168.0.213:6694
  16. + 192.168.0.213:6695
  17. + 192.168.0.213:6696
  18. }
  19. }

   配置文件解析文档:https://github.com/joyieldInc/predixy/blob/master/doc/config_CN.md

3. 创建脚本文件

① 创建启动和停止脚本,放到predixy-1.0.5目录下

  1. mkdir -p /opt/predixy-1.0.5/logs/
  2. cd /opt/predixy-1.0.5/bin

② 创建启动脚本up.sh

  1. #!/bin/bash
  2. path=`pwd`
  3. nohup $path/bin/predixy conf/predixy.conf > $path/logs/predixy.log 2>&1 &

③ 查看日志

  1. tail -f logs/predixy.log

④ 创建停止脚本down.sh

  1. #!/bin/bash
  2. path=`pwd`
  3. pid=`ps -ef | grep $path/bin/predixy | grep -v grep | awk '{print $2}'`
  4. kill -9 $pid

4. 测试predixy代理

  1. ./redis-cli -p 7617
  2. 127.0.0.1:7617> mset b1 b2
  3. OK
  4. 127.0.0.1:7617> get b1
  5. "b2"

5. 启动应用验证predixy代理

将应用配置文件中的集群地址修改为predixy地址,应用服务启动报错:

  1. ...Autowired annotation is not supported on static fields...

方法二:缩减为 4 个节点

尝试缩减为 4 个节点,以提升单个节点的内存配置。但创建集群时提示至少需要 3 个主节点,因此该方案也不可行。

  1. *** ERROR: Invalid configuration for cluster creation.
  2. *** Redis Cluster requires at least 3 master nodes.
  3. *** This is not possible with 4 nodes and 1 replicas per node.
  4. *** At least 6 nodes are required 

方法三:修改集群节点内存

最终解决方案是修改集群节点内存:1、3、4、5 节点分配内存 3G,2、6 节点分配内存 8G。

五、结论

面对 Redis 集群缓存分配不均的问题,我们可以通过逐步的优化方法来解决。首先,了解节点信息、主从关系和缓存占用情况,然后分析哈希槽分布情况,尝试不同的优化方案,最后通过调整内存分配来解决问题。

原文链接:https://www.cnblogs.com/n00dle/p/17631331.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号