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

Redis读写慢?教你用缓存技巧提升读取效率,速度蹭蹭往上涨

Redis读写慢?教你用缓存技巧提升读取效率,速度蹭蹭往上涨

你是不是遇到过这种情况:明明用了Redis这个号称速度飞快的缓存,怎么感觉有时候还是卡卡的?尤其是当用户量一上来,或者数据量变大之后,一些读取操作好像没那么利索了,别急,这很可能不是Redis本身的问题,而是你的“用法”可以再优化一下,今天我们就来聊几个实实在在的技巧,让你的Redis读取效率真正飞起来。

咱们得有个基本概念,Redis慢,多半是慢在网络上(比如一次命令来回要1毫秒),或者慢在了一些不合理的操作上(比如一次性获取几十万条数据),内存里的操作其实是非常非常快的,我们的优化核心就两点:减少网络通信次数避免执行耗时的命令

第一招:变多次为一次,善用批量操作

想象一下,你要从仓库里拿十件货品,最笨的方法是跑十趟,一趟拿一件,聪明的方法当然是推个小车,一趟全拉走,Redis也是这个道理。

你的前端页面需要展示一个商品列表,这个列表包含了10个商品的基本信息,这些信息都存在Redis里,键名是product:商品ID,新手可能会写一个循环,执行10次GET product:1GET product:2... 这意味着你的应用和Redis服务器之间要来回通信10次,网络延迟的代价就在这里被放大了。

正确的做法是使用批量命令,Redis提供了像MGETMSET这样的命令。(根据Redis官方文档说明)MGET可以让你一次性地获取多个键的值,上面那个例子,只需要一条命令MGET product:1 product:2 ... product:10就搞定了,网络通信从10次变成了1次,效率的提升是立竿见影的。

对于集合、列表等数据类型,也有相应的批量操作,比如使用LRANGE一次获取列表的多个元素,而不是多次调用LPOP

第二招:别让“热”数据被“冷”数据挤走,合理设置内存淘汰策略

Redis的内存是有限的,当内存用满后,再有新数据写进来,就得淘汰掉一些老数据,Redis提供了几种淘汰策略(根据Redis官方文档关于maxmemory-policy的说明),这个策略的选择非常关键。

默认的策略可能是noeviction(不淘汰,新写入会报错)或者volatile-lru(在设置了过期时间的键中淘汰最近最少使用的),如果你的业务中,有些数据是访问频率非常高的“热”数据(比如热门新闻、爆款商品信息),而有些数据很久才被访问一次,你肯定不希望那些“热”数据因为内存满了而被意外淘汰掉,导致下次读取时不得不去慢吞吞的数据库里查,那体验就差了。

这时候,你可以考虑使用allkeys-lru策略,这个策略会从所有的键中淘汰最近最少使用的,这样就能保证Redis里长期存放的,大多是那些被频繁访问的热点数据,缓存命中率会很高,如果你的业务场景里,有些数据是绝对不能丢的,那需要更精细地设置键的过期时间和选择其他策略,关键是,不要用默认策略就不管了,要根据你的数据特性来配置。

第三招:把计算放在Redis服务器端,使用Lua脚本

一个复杂的读取逻辑可能包含一些简单的计算和判断,你先要读取一个用户的积分,然后根据积分判断他的等级,最后再把等级信息返回,常规做法是:客户端先GET user:123:score,拿到积分值,然后在应用程序里计算等级,这又是两次网络通信(一次读积分,一次写回等级)。

对于这种简单的、有依赖关系的操作,我们可以使用Lua脚本。(根据Redis官方文档关于Lua脚本的说明)Lua脚本可以让你把多个Redis命令打包成一个脚本,在服务器端原子性地执行,上面的例子,你可以写一个Lua脚本,直接在Redis服务器上完成“读取积分 -> 计算等级 -> 存储并返回等级”这一系列操作,对于客户端来说,只是一次网络请求,就拿到了最终结果,这极大地减少了网络延迟带来的影响。

第四招:优化数据结构和巨型键

不合理的“大”数据也会导致问题,你用一个Hash结构存储了整个网站的用户信息,这个Hash可能有几十万个子项,当你使用HGETALL命令来获取整个Hash时,虽然只是一次网络请求,但Redis需要序列化并返回海量数据,这个过程本身会消耗大量CPU资源,并且巨大的网络报文传输也需要时间。

对于这种场景,要考虑拆分,是不是可以按用户ID的区间拆分成多个小的Hash?或者,是不是真的需要一次性获取所有数据?也许99%的场景下,你只需要HGET某一个特定的用户信息,避免使用像KEYS *这样的危险命令,以及谨慎处理包含大量元素的集合、列表等。

第五招:别忘了基本功,检查慢查询

Redis提供了一个非常实用的功能叫慢查询日志(根据Redis官方文档关于slow log的说明),你可以设置一个时间阈值,比如5毫秒,任何执行时间超过5毫秒的命令都会被记录下来,定期检查这个慢查询日志,你就能准确地知道到底是哪些操作拖慢了系统,从而进行针对性的优化,这就像是给Redis做了一个“体检”,能发现最突出的问题。

让Redis速度飞涨,不是去折腾Redis的配置参数(当然基础配置要正确),而是要转变使用方式:多想想怎么减少网络往返,怎么让最频繁访问的数据留在内存里,怎么把能合并的操作合并,把这些技巧用上,你的Redis缓存才能真正成为提升系统性能的利器。

Redis读写慢?教你用缓存技巧提升读取效率,速度蹭蹭往上涨