杰克工作室 发表于 2023-2-23 15:48

美团在Redis上踩过的一些坑-3.redis内存占用飙升

<p>&nbsp;一、现象:</p>

<p>&nbsp; &nbsp; redis-cluster某个分片内存飙升,明显比其他分片高很多,而且持续增长。并且主从的内存使用量并不一致。</p>

<p>&nbsp;<img alt="" src="http://sebcxy.x.com/uploads/images/20180314/2018-03-14_18-18-19_579.jpg" title="点击查看原始大小图片" /></p>

<p>二、分析可能原因:</p>

<p>&nbsp;1. &nbsp;redis-cluster的bug (这个应该不存在)</p>

<p>&nbsp;2. 客户端的hash(key)有问题,造成分配不均。(redis使用的是crc16, 不会出现这么不均的情况)</p>

<p>&nbsp;3. 存在个别大的key-value: 例如一个包含了几百万数据set数据结构(这个有可能)</p>

<p>&nbsp;4. 主从复制出现了问题。</p>

<p>&nbsp;5. 其他原因</p>

<p>&nbsp;</p>

<p>三、调查原因:</p>

<p>&nbsp;1. 经查询,上述1-4都不存在</p>

<p>&nbsp;2. 观察info信息,有一点引起了怀疑: client_longes_output_list有些异常。</p>

<p><img alt="" src="http://sebcxy.x.com/uploads/images/20180314/2018-03-14_18-18-20_485.jpg" /></p>

<p>3. 于是理解想到服务端和客户端交互时,分别为每个客户端设置了输入缓冲区和输出缓冲区,这部分如果很大的话也会占用Redis服务器的内存。</p>

<p>&nbsp;<img alt="" src="http://sebcxy.x.com/uploads/images/20180314/2018-03-14_18-18-21_905.png" /></p>

<p>从上面的client_longest_output_list看,应该是输出缓冲区占用内存较大,也就是有大量的数据从Redis服务器向某些客户端输出。</p>

<p>于是使用client list命令(类似于mysql processlist) redis-cli -h host -p port client list | grep -v &quot;omem=0&quot;,来查询输出缓冲区不为0的客户端连接,于是查询到祸首monitor,于是豁然开朗.</p>

<p>&nbsp;<img alt="" src="http://sebcxy.x.com/uploads/images/20180314/2018-03-14_18-18-21_597.png" title="点击查看原始大小图片" /></p>

<p>monitor的模型是这样的,它会将所有在Redis服务器执行的命令进行输出,通常来讲Redis服务器的QPS是很高的,也就是如果执行了monitor命令,Redis服务器在Monitor这个客户端的输出缓冲区又会有大量&ldquo;存货&rdquo;,也就占用了大量Redis内存。</p>

<p>&nbsp;</p>

<p>&nbsp;<img alt="" src="http://sebcxy.x.com/uploads/images/20180314/2018-03-14_18-18-21_136.png" /></p>

<p>四、紧急处理和解决方法</p>

<p>进行主从切换(主从内存使用量不一致),也就是redis-cluster的fail-over操作,继续观察新的Master是否有异常,通过观察未出现异常。</p>

<p>查找到真正的原因后,也就是monitor,关闭掉monitor命令的进程后,内存很快就降下来了。</p>

<p>&nbsp;</p>

<p>五、 预防办法:</p>

<p>1. 为什么会有monitor这个命令发生,我想原因有两个:</p>

<p>(1). 工程师想看看究竟有哪些命令在执行,就用了monitor</p>

<p>(2). 工程师对于redis学习的目的,因为进行了redis的托管,工程师只要会用redis就可以了,但是作为技术人员都有学习的好奇心和欲望。</p>

<p>2. 预防方法:</p>

<p>(1) 对工程师培训,讲一讲redis使用过程中的坑和禁忌</p>

<p>(2) 对redis云进行介绍,甚至可以让有兴趣的同学参与进来</p>

<p>(3) 针对client做限制,但是官方也不建议这么做,官方的默认配置中对于输出缓冲区没有限制。</p>

<h6>client-output-buffer-limit normal 0 0 0</h6>

<p>(4) 密码:redis的密码功能较弱,同时多了一次IO</p>

<p>(5) 修改客户端源代码,禁止掉一些危险的命令(shutdown, flushall, monitor, keys *),当然还是可以通过redis-cli来完成</p>

<p>(6) 添加command-rename配置,将一些危险的命令(flushall, monitor, keys * , flushdb)做rename,如果有需要的话,找到redis的运维人员处理</p>

<h6>rename-command FLUSHALL &quot;随机数&quot;<br />
rename-command FLUSHDB &quot;随机数&quot;<br />
rename-command KEYS &quot;随机数&quot;</h6>

<p>六、模拟实验:</p>

<p>1. &nbsp;开启一个空的Redis(最简,直接redis-server)</p>

<h6>redis-server</h6>

<p>初始化内存使用量如下:</p>

<h5># Memory<br />
used_memory:815072<br />
used_memory_human:795.97K<br />
used_memory_rss:7946240<br />
used_memory_peak:815912<br />
used_memory_peak_human:796.79K<br />
used_memory_lua:36864<br />
mem_fragmentation_ratio:9.75<br />
mem_allocator:jemalloc-3.6.0</h5>

<p>client缓冲区:</p>

<h5># Clients<br />
connected_clients:1<br />
client_longest_output_list:0<br />
client_biggest_input_buf:0<br />
blocked_clients:0</h5>

<p>2. 开启一个monitor</p>

<h6>redis-cli -h 127.0.0.1 -p 6379 monitor</h6>

<p>3. 使用redis-benchmark:</p>

<h6>&nbsp;redis-benchmark -h 127.0.0.1 -p 6379 -c 500 -n 200000</h6>

<p>&nbsp;</p>

<p>4. 观察</p>

<p>(1) info memory:内存一直增加,直到benchmark结束,monitor输出完毕,但是used_memory_peak_human(历史峰值)依然很高--观察附件中日志</p>

<p>(2)info clients:&nbsp;client_longest_output_list: 一直在增加,直到benchmark结束,monitor输出完毕,才变为0--观察附件中日志</p>

<p>(3)redis-cli -h host -p port client list | grep &quot;monitor&quot; omem一直很高,直到benchmark结束,monitor输出完毕,才变为0--观察附件中日志</p>

<p>监控脚本:</p>

<pre>
while [ 1 == 1 ]
do
now=$(date &quot;+%Y-%m-%d_%H:%M:%S&quot;)
echo &quot;=========================${now}===============================&quot;
echo &quot; #Client-Monitor&quot;
redis-cli -h 127.0.0.1 -p 6379 client list | grep monitor
redis-cli -h 127.0.0.1 -p 6379 info clients
redis-cli -h 127.0.0.1 -p 6379 info memory
#休息100毫秒
usleep 100000
done</pre>

<p>完整的日志文件:</p>

<p>&nbsp;<a href="http://dl.iteye.com/topics/download/096f5da0-4318-332e-914f-6f7c7298ddc9" target="_blank">http://dl.iteye.com/topics/download/096f5da0-4318-332e-914f-6f7c7298ddc9</a></p>

<p>&nbsp;部分日志:</p>

<pre>
=========================2015-11-06_10:07:16===============================
#Client-Monitor
id=7 addr=127.0.0.1:56358 fd=6 name= age=91 idle=0 flags=O db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=0 obl=0 oll=4869 omem=133081288 events=rw cmd=monitor
# Clients
connected_clients:502
client_longest_output_list:4869
client_biggest_input_buf:0
blocked_clients:0
# Memory
used_memory:174411224
used_memory_human:166.33M
used_memory_rss:161513472
used_memory_peak:176974792
used_memory_peak_human:168.78M
used_memory_lua:36864
mem_fragmentation_ratio:0.93
mem_allocator:jemalloc-3.6.0</pre>

<h1>出处哈:<a href="http://carlosfu.iteye.com/blog/2254154">http://carlosfu.iteye.com/blog/2254154</a></h1>

<hr />
<h6>上上周和同事(龙哥)参加了360组织的互联网技术训练营第三期,美团网的DBA负责人侯军伟给大家介绍了美团网在redis上踩得一些坑,讲的都是干货和坑。</h6>

<p>&nbsp; &nbsp; 分为5个部分:</p>

<p>&nbsp; &nbsp;一、<a href="http://carlosfu.iteye.com/blog/2254566" target="_blank">周期性出现connect timeout</a></p>

<p>&nbsp; &nbsp;二、<a href="http://carlosfu.iteye.com/blog/2254570" target="_blank">redis bgrewriteaof问题</a></p>

<p>&nbsp; &nbsp;三、<a href="http://carlosfu.iteye.com/blog/2254571" target="_blank">redis内存占用飙升</a></p>

<p>&nbsp; &nbsp;四、<a href="http://carlosfu.iteye.com/blog/2254572" target="_blank">redis内存使用优化&nbsp;</a></p>

<p>&nbsp; &nbsp;五、<a href="http://carlosfu.iteye.com/blog/2254573">redis cluster遇到的一些问题&nbsp;</a></p>

<p>&nbsp; 附赠PPT:&nbsp;</p>

<p>&nbsp;(1) 本次:<a href="http://dl.iteye.com/topics/download/d50b18c7-9f10-3431-8e46-268cfcd92a10" target="_blank">美团在Redis上踩过的一些坑PPT</a></p>

<p>&nbsp;(2) 以往:<a href="http://dl.iteye.com/topics/download/922c8a86-7453-3bc0-819c-3c4a56758692" target="_blank">《Redis在新浪的大规模运维经验》-演讲人:侯军伟新浪高级DBA.pdf&nbsp;</a></p>

<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<a href="http://dl.iteye.com/topics/download/7d24a498-1c19-3d4a-9b2e-32b0c38561ec" target="_blank">&nbsp;美团数据库运维平台介绍.pdf</a></p>

<p>&nbsp;&nbsp;</p>
页: [1]
查看完整版本: 美团在Redis上踩过的一些坑-3.redis内存占用飙升