• 海量数据情况下,怎么用Bitmap进行签到统计?


    在 Web 和移动应用的业务场景中,我们经常需要保存这样一种信息:统计用户在手机 App 上的签到打卡信息。

    在签到打卡的场景中,我们只用记录签到(1)或未签到(0),它就是非常典型的二值状态。在签到统计时,每个用户一天的签到用 1 个 bit 位就能表示,一个月(假设是 31 天)的签到情况用 31 个 bit 位就可以,而一年的签到也只需要用 365 个 bit 位。

    Bitmap 数据类型介绍

    Redis 恰好有这样一种数据结构:Bitmap。Bitmap 本身是用 String 类型作为底层数据结构实现的一种统计二值状态的数据类型。String 类型是会保存为二进制的字节数组,所以,Redis 就把字节数组的每个 bit 位利用起来,用来表示一个元素的二值状态。你可以把 Bitmap 看作是一个 bit 数组。

    那么,具体该怎么用 Bitmap 进行签到统计呢?

    假设我们要统计 ID 3000 的用户在 2022 年 10 月份的签到情况,就可以按照下面的步骤进行操作。

    第一步,执行下面的命令,记录该用户 10 月 1 号已签到(bit 位设置为 1)。

    SETBIT uid:sign:3000:202210 0 1
    
    • 1

    第二步,检查该用户 10 月 1 日是否签到。

    GETBIT uid:sign:3000:202210 0
    
    • 1

    第三步,统计该用户在 10 月份的签到次数(bit 数组中所有“1”的个数)。

    BITCOUNT uid:sign:3000:202210
    
    • 1

    这样,我们就知道该用户在 10 月份的签到情况了。

    Bitmap 的 BITOP 命令

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

    我以按位“与”操作为例来具体解释一下。从下图中,可以看到,三个 Bitmap bm1、bm2 和 bm3,对应 bit 位做“与”操作,结果保存到了一个新的 Bitmap 中(示例中,这个结果 Bitmap 的 key 被设为“resmap”)。

    BITOP命令示意图

    回到我们的标题:如果记录了 1 亿个用户 10 天的签到情况,你有办法统计出这 10 天连续签到的用户总数吗?

    在统计 1 亿个用户连续 10 天的签到情况时,你可以把每天的日期作为 key,每个 key 对应一个 1 亿位的 Bitmap,每一个 bit 对应一个用户当天的签到情况。

    接下来,我们对 10 个 Bitmap 做“与”操作,得到的结果也是一个 Bitmap。在这个 Bitmap 中,只有 10 天都签到的用户对应的 bit 位上的值才会是 1。最后,我们可以用 BITCOUNT 统计下 Bitmap 中的 1 的个数,这就是连续签到 10 天的用户总数了。

    现在,我们可以计算一下记录了 10 天签到情况后的内存开销。每天使用 1 个 1 亿位的 Bitmap,大约占 12MB 的内存(10^8/8/1024/1024),10 天的 Bitmap 的内存开销约为 120MB,内存压力不算太大。不过,在实际应用时,最好对 Bitmap 设置过期时间,让 Redis 自动删除不再需要的签到记录,以节省内存开销。

    所以,如果只需要统计数据的二值状态,例如商品有没有、用户在不在等,就可以使用 Bitmap,因为它只用一个 bit 位就能表示 0 或 1。在记录海量数据时,Bitmap 能够有效地节省内存空间。

    本篇摘自极客时间《Redis核心技术与实战》(蒋德钧)第12讲。

  • 相关阅读:
    【计算机网络学习之路】Windows下的socket编程
    4. DDPM, DDIM, Analytic-DPM, Extended Analytic-DPM
    C语言实现DNS请求器
    FastASR——PaddleSpeech的C++实现
    [Linux]下制作myshell
    1932. 合并多棵二叉搜索树 并查集+DFS
    小白学习-ElasticSearch教程(4) -文档查询之bool查询
    你以为的直线,在多维空间里是复杂的曲线
    Connection closed by foreign host
    数据结构---查找
  • 原文地址:https://blog.csdn.net/yang237061644/article/details/127587710