12 | 有一亿个keys要统计,应该用哪种集合?(list,set,zset,bitmap,hyperloglog)

601 阅读4分钟

0.基本概念

  • 四种统计模式

    • 聚合统计
    • 排序统计
    • 二值状态
    • 基数统计
  • 根据不同的统计模式,选择不同的元素集合

1.聚合统计(set)

  • 基本概念:就是指统计多个集合元素的聚合结果

  • 举个栗子:

    • 统计多个集合的共有元素(交集统计)\

    • 统计其中一个集合独有的元素(差集统计)\

    • 统计多个集合的所有元素(并集统计)\

  • 举个实际栗子

    • 统计手机 App 每天的新增用户数和第二天的留存用户数\

    • 实现

      • 可以用一个集合记录所有登录过 App 的用户 ID(全部用户)\

        • 使用Set 类型

        • 把 key 设置为 user:id\

        • value 就是一个 Set 集合,里面是所有登录过 App 的用户 ID\

      • 用另一个集合记录每一天登录过 App 的用户 ID(每天登录用户)\

        • 使用set类型

        • key 是 user:id 以及当天日期\

        • value 是 Set 集合,记录当天登录的用户 ID

      • 将当天登录用户与总终于进行差集结果 获取新增用户 SDIFFSTORE

      • 将当天登录用户与总用户进行并集结果 获取全量用户 SUNIONSTORE\

      • 将不同天数的用户进行交集 获取留存用户 SINTERSTORE

  • set非常适合对多个集合进行聚合计算操作

  • 不过Set 的差集、并集和交集的计算复杂度较高,在数据量较大的情况下,如果直接执行这些计算,会导致 Redis 实例阻塞

    • 可以选择选择一台从库负责聚合计算
    • 将数据读取到客户端,由客户端进行觉操作

\

2.排序统计(zset)

  • 基本概念:对集合进行排序\

  • 举个栗子:最新评论列表

  • 集合类型:List、Hash、Set、Sorted Set

    • List 和 Sorted Set 就属于有序集合\

    • List 是按照元素进入 List 的顺序进行排序的\

    • Sorted Set 可以根据元素的权重来排序\

  • 使用list

    • List 包含了对这个商品的所有评论,而且会按照评论时间保存这些评论

    • 每来一个新评论,就用 LPUSH 命令把它插入 List 的队头\

    • 可能存在的问题

      • 由于会有元素加入新的队头,因此分页会导致结果错误
  • 使用sorted set

    • 可以按评论时间的先后给每条评论设置一个权重值,然后再把评论保存到 Sorted Set 中\

    • Sorted Set 也能通过 ZRANGEBYSCORE 命令准确地获取到按序排列的数据\

    • 不会存在分页结果错误

    • ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count]

  • 展示最新列表、排行榜等场景时,如果数据更新频繁或者需要分页显示,建议你优先考虑使用 Sorted Set\

3.二值状态统计(bitmap)

  • 基本概念:这里的二值状态就是指集合元素的取值就只有 0 和 1 两种

  • 举个栗子:

    • 每个用户一天的签到用 1 个 bit 位就能表示,一个月(假设是 31 天)的签到情况用 31 个 bit 位就可以,而一年的签到也只需要用 365 个 bit 位\
  • 一些操作

    • Bitmap 本身是用 String 类型作为底层数据结构实现的一种统计二值状态的数据类型\

    • Bitmap 提供了 GETBIT/SETBIT 操作,使用一个偏移值 offset 对 bit 数组的某一个 bit 位进行读和写\

    • Bitmap 还提供了 BITCOUNT 操作,用来统计这个 bit 数组中所有“1”的个数\

    • Bitmap 支持用 BITOP 命令对多个 Bitmap 按位做“与”“或”“异或”的操作,操作的结果会保存到一个新的 Bitmap 中\

  • 优点:存储小 set 日期 存储大\

\

4.基数统计

  • 基本概念:基数统计就是指统计一个集合中不重复的元素个数

  • 如果使用redis set,每次都SADD,获取总量SCARD(存储很大,效率较低)

  • 使用Hash 类型记录 UV HSET page1:uv user1 1\

  • 使用 HyperLogLog

    • HyperLogLog 是一种用于统计基数的数据集合类型,它的最大优势就在于,当集合元素数量非常多时,它计算基数所需的空间总是固定的,而且还很小\

    • 可以用 PFADD 命令(用于向 HyperLogLog 中添加新元素)把访问页面的每个用户都添加到 HyperLogLog 中\

    • 可以用 PFCOUNT 命令直接获得 page1 的 UV 值了,这个命令的作用就是返回 HyperLogLog 的统计结果\

    • 需要注意的是:HyperLogLog 的统计规则是基于概率完成的,所以它给出的统计结果是有一定误差的,标准误算率是 0.81%

    • 不适合精细的计算

5.小结

  • 统计方式

    • 聚合统计\

    • 排序统计\

    • 二值状态统计\

    • 基数统计

\

\