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

怎么用Redis快速查数量,简单又实用的方法分享给你

说到快速查数量,比如你想知道你的网站今天有多少新用户注册,或者一个热门帖子有多少条评论,又或者你的商品库存还剩多少,这种时候如果直接去数据库里数,数据量一大就会慢得像蜗牛,Redis之所以快,主要是因为它把数据都放在内存里操作,而且它的数据结构非常高效,下面我就分享几个最常用、最直接的方法。

最直接的武器:GET 和 SET

这个方法理解起来最简单,你想统计在线用户数,当一个用户上线时,你执行一个命令,把这个数加1;用户下线时,减1,在Redis里,你可以用一个键(key)来存这个数,比如键的名字叫 user:online:count

  • 初始化:如果刚开始没有这个数,你可以先把它设为0,命令是:SET user:online:count 0
  • 用户上线INCR user:online:count,这个命令会把数量加1,并且返回加完后的新值,它的好处是,Redis保证这个操作是原子性的,也就是说即使有成千上万个用户同时上线,也不会出现数错的情况。
  • 用户下线DECR user:online:count,同理,原子性地减1。
  • 查询数量:这时候就非常简单了,直接用 GET user:online:count,Redis会瞬间把当前的值返回给你。

这种方法非常适合计数逻辑简单,只有增加和减少两种操作的场景,它的速度极快,因为只是简单的读取一个键的值。

应对复杂情况:哈希(Hash)和 HLEN

我们的需求没那么简单,你不是想统计总在线用户数,而是想统计每个省份的在线用户数,如果用上面的方法,你得为每个省份创建一个键,user:online:count:zhejiang, user:online:count:beijing,管理起来很麻烦。

怎么用Redis快速查数量,简单又实用的方法分享给你

这时候,Redis的哈希结构就派上用场了,你可以把一个哈希想象成一个小型的键值对集合,我们可以创建一个叫 user:online:info 的哈希。

  • 用户上线:假设一个浙江的用户上线了,你执行:HSET user:online:info zhejiang 1,如果浙江的计数已经存在,这个命令会覆盖旧值,但更常见的做法是,我们不直接设置值,而是用另一个命令。
  • 更优的上线操作HINCRBY user:online:info zhejiang 1,这个命令和 INCR 类似,是专门为哈希的字段(field)设计的增量命令,同样是原子操作,如果字段 zhejiang 不存在,Redis会先把它初始化为0再加1。
  • 查询某个省份的数量HGET user:online:info zhejiang
  • 查询所有省份的总在线用户数:这需要把哈希里所有字段的值加起来吗?不需要!Redis提供了一个超快的命令:HLEN user:online:info,等一下,这里有个常见的误解。HLEN 返回的是哈希中字段的数量,而不是所有字段值的总和,在这个例子里,它返回的是你统计了多少个省份,而不是总用户数,如果你要统计总用户数,还是得用第一种方法,或者遍历所有字段的值求和(这就不算“快速”了)。

HLEN 什么时候才能真正“快速查数量”呢?当你需要统计的是集合中不重复元素的个数时,你想知道今天有多少唯一用户访问了你的app(同一个用户一天只算一次),这时候,哈希的“字段”本身就起到了去重的作用。

  • 记录访问:用户ID为1001的用户访问了,你执行:HSET today:unique:users 1001 1,这里的值“1”是什么并不重要,我们关心的是字段“1001”是否存在。
  • 查询今日唯一访问用户数:直接使用 HLEN today:unique:users,这个命令会立刻返回字段的总数,也就是不重复的用户ID个数,速度飞快。

为统计唯一值而生的神器:HyperLogLog

怎么用Redis快速查数量,简单又实用的方法分享给你

上面用哈希来统计唯一值,虽然快,但如果唯一值数量极其庞大(比如数亿),还是会占用不少内存,Redis提供了一个更节省空间的解决方案——HyperLogLog,它是一种概率算法,特点是用极小的空间完成巨量数据的去重计数,代价是结果有不到1%的误差,对于很多可以接受近似值的场景(比如网站UV统计),这简直是神器。

  • 记录访问:用户ID为1001的用户访问了,命令是:PFADD today:uv 1001PFADD 命令会把这个用户ID加入到HyperLogLog结构中。
  • 查询今日UVPFCOUNT today:uv,这个命令会立刻返回一个大概的唯一用户数。

你可能也看出来了,HyperLogLog不能像哈希一样查询某个具体用户是否访问过,它唯一的功能就是做去重计数,但它的优势太明显了:一个HyperLogLog结构只需要最多12KB的内存,就能统计接近 2^64 个不重复元素的个数!这对于海量数据统计是革命性的。

总结一下

怎么选这些方法,就看你的具体需求:

  1. 简单的增减计数(总订单数、库存):用 INCR/DECRGET,最简单直接。
  2. 需要分组统计数量(按分类的商品数):用哈希(Hash)的 HINCRBYHGET
  3. 需要精确统计巨大集合的唯一值数量(精确UV):用哈希(Hash)的 HLEN 命令,但要注意内存消耗。
  4. 需要海量数据唯一值统计,且可以接受微小误差(日常UV统计、大型活动参与人数):用 HyperLogLogPFADDPFCOUNT,这是空间效率最高的方法。

这些就是Redis帮你快速查数量的几把快刀,每种都有最适合的场景,用对了就能让你的应用速度提升一个大档次。