标题:【Redis30】Redis进阶:一些简单运维技巧
Redis进阶:一些简单运维技巧
关于 Redis 的运维,我的经验仅限于安装、备份,而且还是最简单的利用一些面板工具。之前很多篇文章中我都强调过,我没有 Redis 的主从及分布式的真实项目经历。经历过的流量最大的项目也只是一台 Redis 实例就抗住了。毕竟 Redis 具有号称单机单实例写入 8万/秒 ,读取 11万/秒 的能力,咱们一般的项目根本达不到啊。而且即使机器性能有差异,减一半,甚至减三分之一,3万/秒 的读取和写入的系统咱也没接触过。(最大接触到的是 3000条数据/秒 写入 List 队列)
因此,用不上也就接触不到,简单配置的一台 Redis 的性能就比我所接触过的最高流量上限还高了很多了。很多运维及优化相关的内容没法以真实的项目经验来做为参考,这里也就只能是将一些看过的有印象的资料分享出来。
查看大 Key
Redis本身提供发现大对象的工具,对应命令:redis-cli --bigkeys 。注意,是 redis-cli 的参数哦。
➜ ~ redis-cli --bigkeys
# 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 '"a"' with 3 bytes
[00.00%] Biggest list found so far '"b"' with 4 items
-------- summary -------
Sampled 2 keys in the keyspace!
Total key length in bytes is 2 (avg len 1.00)
Biggest list found '"b"' has 4 items
Biggest string found '"a"' has 3 bytes
1 lists with 4 items (50.00% of keys, avg size 4.00)
0 hashs with 0 fields (00.00% of keys, avg size 0.00)
1 strings with 3 bytes (50.00% of keys, avg size 3.00)
0 streams with 0 entries (00.00% of keys, avg size 0.00)
0 sets with 0 members (00.00% of keys, avg size 0.00)
0 zsets with 0 members (00.00% of keys, avg size 0.00)
我这里没什么数据,所以可能看不出啥效果,虽说看不出,但咱也得简单解释一下。
Biggest string found so far '"a"' with 3 bytes
包括下面那一条,就是每个类型中所找到的最大的 Key底下还会统计每个类型中有几个,复合类型中有几个 items 或者 fields ,同时在这些内容中,一些比例信息,平均的大小等
虽说有这些内容,如果需要按照某个阈值来查找指定的大键,还是没法通过 --bigkey 来实现。这时,其实可以通过另外一个内部命令来实现。
127.0.0.1:6379> hmset c a 111111 b 22
OK
127.0.0.1:6379> DEBUG OBJECT c
Value at:0x7fc197352960 refcount:1 encoding:ziplist serializedlength:26 lru:13093574 lru_seconds_idle:12
DEBUG OBJECT
用于返回调试对象的基本信息。在这些信息中,我们可以看到它现在是 ziplist 格式,数据长度为 serializedlength
,简单地理解,它就可以看成是 strlen
查看 String 类型的结果。这样,我们就可以根据不同的 Key 占据的字节长度来确定哪些是大 Key 。怎么删除大 Key ?不记得的小伙伴赶紧来复习一下哦。
再问一个:怎么遍历所有的 Key ?忘了 SCAN
命令了?不记得的小伙伴也请赶紧来复习一下。
操作大 Key
操作大 Key 一般是读写两个方面,读的话好说,尽量用 scan
系列命令代替 KEYS *
,还包括 hscan
、sscan
、zscan
。写的话,分段写,不要一次大批量(几万上百万)的插入、更新,或者干脆别用大 Key 。删除的话,unlink
还记得吧,另外 6 以上版本,开启 lazy-free
也可以让 del
去后台运行。查询数量,llen
、hlen
、scard
、zcard
的性能没问题,链表有记录数量字段,返回很快。
记住,范围操作都很惨!全是我们之前学习过的内容,这个 bigkey 问题也是非常常见的面试题。
监控系统信息
通过 redis-cli --stat
命令,可以实时地监控当前 Redis 的使用情况。同样,它也是一个 redis-cli 的参数工具。
➜ ~ redis-cli --stat
------- data ------ --------------------- load -------------------- - child -
keys mem clients blocked requests connections
3 1.11M 1 0 92459301 (+0) 932
3 1.11M 1 0 92459302 (+1) 932
3 1.11M 1 0 92459303 (+1) 932
3 1.11M 1 0 92459304 (+1) 932
………………
………………
运行之后,会不停地输出当前 Redis 的信息,包括 Key 的数量,占用内存的大小,连接的客户端信息等等。
查看内存交换情况
内存交换就是我们 Linux 系统中的 SWAP 部分的内容。当物理内存不够的时候,会借用一些磁盘空间来当做类似 Windows 的虚拟内存空间。既然一提到磁盘了,那肯定就有一个问题,性能会剧烈下降。
那么我们要怎么知道,当前 Redis 是否使用了 SWAP 了呢?
首先看下当前 Redis 的进程 ID 。
➜ ~ redis-cli info server | grep process_id
process_id:820
然后,到操作系统的 /proc 目录下查看内存交换情况。
cat /proc/4476/smaps | grep Swap
Swap: 0 kB
………………
如果交换量都是 0kB 或者个别的是 4kB ,则是正常现象,说明Redis进程内存没有被交换。好了,现在我们知道了会有这个交换内存的情况,也知道了怎么查看有没有发生内存交换,那么预防内存交换的方法有哪些呢?
保证机器充足的可用内存。
确保所有 Redis 实例设置最大可用内存(maxmemory),防止极端情况下 Redis 内存不可控的增长。
降低系统使用swap优先级,如echo 10 > /proc/sys/vm/swappiness ,具体信息大家可以查阅 Linux 相关的资料。
连接数问题
在学习配置文件时,我们就看到过,Redis 的连接数可以通过 maxclients
这个参数进行配置,默认情况下它是 10000 。当我们有超过 10000 个客户端来连接时,Redis 就会拒绝连接。
在 info
命令下的 stats
子命令中,有一个 rejected_connections 属性,表示的就是被拒绝的连接的数量。
➜ ~ redis-cli info stats | grep rejected
rejected_connections:0
可以通过查看这个属性,获得当前我们系统的连接情况,看是不是要适当调节 maxclients 的大小。注意,如果是非本机连接,还要注意操作系统的 ulimit 情况。
内存碎片
同样在配置文件中,我们也学习过内存碎片相关的配置信息。在系统的实际运行中,其实也可以在 info memory
中查看到内存碎片的信息。
127.0.0.1:6379> info memory
# Memory
used_memory:1163184
…………
used_memory_rss:1626112
…………
…………
mem_fragmentation_ratio:1.45
…………
需要重点关注的就是上面这三个属性的值。
used_memory 使用的内存
used_memory_rss 从系统角度,显示Redis进程占用的物理内存总量,与top及ps命令看到的值是一致的
mem_fragmentation_ratio 上面这两位的比值
实际使用的内存比系统显示占用的内存小,说明有一些内存没有被正式的数据使用,而是被内存碎片占用了。如果两者相差很大,说明碎片率很严重。不过 mem_fragmentation_ratio 如果小于 1 也不是什么好事,说明 Redis 使用了 SWAP 交换内存到磁盘了。
注意到我这里的 mem_fragmentation_ratio 比值计算其实是不精准的,1626112/1163184 约等于 1.40 ,这一块并没有找到合适的资料来解释,有相关经验的小伙伴可以留言告知一下哈,或许也可能是我本地没什么数据,还有别的虚占内存被计算了之类的。要么咱们就暂且认为 mem_fragmentation_ratio 的公式并不是完全的 used_memory_rss/used_memory ,可能还有别的参数。
可以看出,这个值大于 1 ,小于 1 都不是什么好事,但也很难控制在完整的 1 上,因此,一般认为在 1 到 1.5 之间是比较健康的,超过 1.5 了就表示有 50% 的内存被碎片占用了。
内存碎片的处理,一是可以在配置文件中打开 activedefrag
让系统自动进行碎片整理,另外也可以通过命令 MEMORY PURGE
命令手动清理,但这个命令会占用主进程,如果本身 Redis 占用的内存非常大的话,会造成进程卡顿。
缓存命中率
这个问题印象很深刻啊,为啥?因为面试的时候被问到过,当时年轻的我当然毫无意外的回答不出来。其实,也是通过 info 就可以查看到缓存的命中情况,然后根据一个公式就可以计算出缓存的命中率了。
127.0.0.1:6379> info stats
# Stats
……………………
keyspace_hits:3316018
keyspace_misses:6362034
……………………
是的,就是这两个属性值。从名称就可以看出,一个是键空间命中数,一个是未命中数。
有了这两个基础值后,命中率就可以这么算:命中数/(命中数+未命中数)。
上面信息中我们的系统命中率就是 3316018/(3316018+6362034) = 0.34 ,好像有点低呀,可不是,咱这是本地测试机呀。如果确实是命中率过低,要检查缓存击穿的问题,这个很影响命中率。另外还要注意的就是缓存过期和失效的时机与架构设计,都是影响命中率的关键。
总结
Redis 正式学习系列的内容到此为止了。通过这 30 篇文章和视频的学习,相信咱们对基础的 Redis 使用应该是没有什么太大的问题了,至少大部分面试常见题也是能够轻松应对了。或者说,最差最差咱也不只是会用 GET、SET 的那一类码农了,多少还是知道 List 、Hash 、Set 、Sorted Set 这些数据类型以及它们的应用场景了。
好了,后续如果还有 Redis 相关的内容,应该也是偏优化和实战方面的内容,不会包含在这个系列中,会是单独的文章或者是其它学习系列中牵涉到 Redis 部分的一些内容。
感谢大家的支持,脚步不要停歇,咱们接下来就先进入到 Nginx 的学习中吧。
视频链接
微信文章地址:https://mp.weixin.qq.com/s/CVY5BnsyOQ6PhSBCG-59mg