当前位置:首页 > 问答 > 正文

Redis性能调优那些事儿,配置怎么折腾才算真极致优化呢?

主要参考自Redis官方文档、阿里云开发者社区的相关实践文章以及部分高流量互联网公司的技术博客分享)

Redis这东西,速度快是快,但你要是不懂怎么“伺候”它,它分分钟也能给你掉链子,想把Redis的性能榨干,达到那种“极致优化”的状态,光会敲几个命令可不行,得从里到外、从硬件到软件、从配置到代码都琢磨透了,咱们今天就聊聊这些折腾的事儿。

Redis性能调优那些事儿,配置怎么折腾才算真极致优化呢?

最基础的,你得知道你的Redis在干嘛,很多人Redis跑得慢,第一反应就是“是不是内存不够了?”,其实不然,你得先打开慢查询日志(slowlog),这玩意儿就像个黑匣子,专门记录那些执行得比较慢的命令,怎么开呢?在配置文件里设置 slowlog-log-slower-than 这个参数,单位是微秒,比如你设为10000,就是超过10毫秒的命令都会被记下来,然后再配合 slowlog-max-len 设定最多保存多少条记录,定期看看慢查询日志,你可能会发现罪魁祸首是某个没加索引的KEYS命令(这命令在生产环境基本是禁用的),或者是一个复杂度O(N)的查询在操作一个超级大的List,这是优化的第一步,也是最重要的一步:揪出慢操作。

咱们说说内存这块,Redis是内存数据库,内存怎么用至关重要,别以为把数据往里一塞就完事了。内存优化(参考Redis官方文档Memory Optimization章节)有个很关键的配置叫 hash-max-ziplist-entrieshash-max-ziplist-value,这俩是干嘛的?简单说,Redis为了节省内存,在小数据量的Hash、List、Set、Zset这几种数据结构上,会用一种叫ziplist(压缩列表)的紧凑格式来存储,而不是用标准的结构,比如一个Hash结构,如果字段数量小于 hash-max-ziplist-entries(默认512)且每个字段的值长度小于 hash-max-ziplist-value(默认64字节),Redis就会用ziplist存,能省不少内存,你可以根据你业务数据的特点,适当调大这两个值,比如调到1000和100,只要你的数据大部分符合这个特征,就能有效降低内存占用,但注意,调得太大会影响读写效率,因为操作ziplist需要解码编码,这是个权衡。

Redis性能调优那些事儿,配置怎么折腾才算真极致优化呢?

然后就是持久化了,Redis有两种持久化方式:RDB和AOF。RDB是拍快照,在某个时间点把整个数据库存成一个文件,它的性能瓶颈主要在fork子进程的那一刻,如果内存数据量大,fork操作可能会卡住主线程一阵子。save 指令的触发频率别设得太高,比如别动不动就“每分钟存一次”。AOF是记录每一条写命令,数据更安全,但写盘策略很关键。appendfsync 这个参数有三个选项:always(每个写命令都刷盘,最安全但最慢)、everysec(每秒刷一次,是默认值,也是性能和安全的较好平衡)、no(让操作系统决定何时刷盘,最快但可能丢失较多数据),绝大多数场景下,用默认的 everysec 就够了,如果你用了AOF,文件会越来越大,记得定期执行 BGREWRITEAOF 命令(或者配置自动重写)来瘦身。

网络和连接池也是性能的关键,别让Redis成为瓶颈,客户端的用法也得讲究,要使用连接池(参考各类客户端连接池最佳实践),避免频繁地创建和关闭连接,那个开销很大,尽量使用管道(pipeline) 技术,把多个命令打包一次发送,减少网络往返次数,这对性能提升是立竿见影的,尤其是在需要连续执行多个命令的场景下。

硬件和系统层面也有讲究,Redis是单线程模型的(指处理命令的核心模块),所以它并不吃多核CPU,但非常吃CPU的主频和内存带宽,给它配一颗高主频的CPU比多核更重要。内存不足时操作系统会使用Swap,一旦Redis的数据被换到硬盘上,性能就会断崖式下跌,所以务必确保服务器有足够的内存,并且通过配置 vm.overcommit_memory=1 来告诉操作系统“尽量别捣乱,老实分配内存”。

说说“极致优化”的一个高级玩法:数据结构的选择和使用,你想存一组用户的在线状态(上线/下线),是用String类型每个用户存一个键值对,还是用一个Set类型把所有在线用户ID存起来?前者可能键数量爆炸,后者可能在一个大Set上操作效率低,再比如,用HyperLogLog来做基数统计(比如统计UV),能节省海量内存,这种优化已经超出了配置文件的范畴,需要你对业务和Redis提供的各种数据结构有深刻理解,从设计层面就选择最合适的那个,这才是真正意义上的“极致优化”。

Redis性能调优不是简单地改一两个参数就能一劳永逸的,它是个系统工程,需要你持续地监控(看慢查询、看内存占用、看持久化延迟)、分析瓶颈、然后有针对性地进行调整和代码改造,从关闭危险的KEYS命令,到调整ziplist参数省内存,再到用好管道和连接池,每一步都是在为Redis的极致性能添砖加瓦。

Redis性能调优那些事儿,配置怎么折腾才算真极致优化呢?