redis中bitmap使用场景结束-员工统计打卡

迭代苔原
• 阅读 1478

Redis 的 Bitmap 是一种特殊的数据结构,它可以存储一组二进制位,并对这些二进制位进行位运算。Bitmap 在 Redis 中被广泛用于计数器、统计、排重等场景。

一、命令介绍

1、SETBIT key offset value

将指定偏移量的二进制位设置为给定的值(0 或 1)。例如,SETBIT mybitmap 1001 1 将 mybitmap 中偏移量为 1001 的二进制位设置为 1。

2、GETBIT key offset

获取指定偏移量的二进制位的值(0 或 1)。例如,GETBIT mybitmap 1001 将返回 mybitmap 中偏移量为 1001 的二进制位的值。

3、BITCOUNT key [start end]

计算指定范围内所有二进制位被设置为 1 的个数。例如,BITCOUNT mybitmap 0 1023 将返回 mybitmap 中偏移量从 0 到 1023 的所有二进制位中被设置为 1 的个数。

4、BITOP operation destkey key [key ...]

对多个指定的 bitmap 进行位运算,并将结果存储到 destkey 中。operation 参数可以是 AND、OR、XOR、NOT 四种运算之一。例如,BITOP AND myresult mybitmap1 mybitmap2 将 mybitmap1 和 mybitmap2 中的所有二进制位进行 AND 运算,并将结果存储到 myresult 中。

Bitmap 的主要优点是占用的空间非常小,一个 bitmap 只需要占用 1MB 的内存,就可以存储 8 1024 1024 个二进制位。Bitmap 还支持非常高效的位运算操作,可以快速实现复杂的统计、计算等功能。

不过,由于 Redis Bitmap 只能存储二进制位,因此只适用于对数据量比较小、结构比较简单的数据进行存储和计算。对于结构比较复杂的数据或者需要高性能的大规模数据处理场景,建议使用其他类型的数据结构和分布式计算框架。

二、理解bitmap 中偏移量offset的概念

当我们使用 Redis 的 Bitmap 存储数据时,实际上是将数据转换为一组二进制位,并将这些二进制位存储在一个字符串中。偏移量 offset 指的是这个字符串中的位置,用于标识每个二进制位的位置。

下面举一个具体的例子来说明。假设我们有一个员工打卡系统,需要记录每个员工每天的打卡情况,包括上午打卡和下午打卡两个时间点。我们可以使用 Redis Bitmap 存储这些数据,其中每个二进制位表示一个员工在某个时间点是否打卡。

假设我们有 1000 个员工,需要记录每个员工在某一天的打卡情况。我们可以创建一个名为 "checkin:20220306" 的 Bitmap,用于存储这些数据。在这个 Bitmap 中,每个员工的打卡情况占用两个二进制位,一个表示上午打卡,一个表示下午打卡。偏移量 offset 表示每个员工在这个 Bitmap 中占用的位置。

假设我们规定每个员工在 Bitmap 中占用的位置为 2 个二进制位。那么,员工编号为 1001 的员工在 Bitmap 中的占用位置就是 2 * 1001 = 2002。如果这个员工在上午打卡了,我们可以使用 SETBIT 命令将这个位置的二进制位设置为

SETBIT checkin:20220306 2002 1

如果这个员工在下午也打卡了,我们可以使用 SETBIT 命令将这个位置的第二个二进制位设置为 1:

SETBIT checkin:20220306 2003 1

如果我们需要查询这个员工在某个时间点是否打卡,可以使用 GETBIT 命令查询对应的二进制位的值:

GETBIT checkin:20220306 2002  # 查询上午打卡情况
GETBIT checkin:20220306 2003  # 查询下午打卡情况

通过 Bitmap,我们可以非常高效地存储和查询大量的打卡数据,并进行一些高级的计算和统计操作。

三、上面Demo中,如何把员工编号1001转换成offset?

在上面的示例中,我们假设每个员工在 Bitmap 中占用的位置为 2 个二进制位。这意味着每个员工在 Bitmap 中的起始偏移量为 2 员工编号。例如,员工编号为 1001 的员工在 Bitmap 中的起始偏移量为 2 1001 = 2002。

具体来说,如果我们有 n 个员工,需要使用 Bitmap 存储这些数据,每个员工在 Bitmap 中占用的二进制位数为 m,那么我们可以使用如下公式将员工编号转换为偏移量 offset:

offset = m * (employee_id - 1)

其中,employee_id 是员工编号,从 1 开始编号。由于 Redis 中字符串的下标也是从 0 开始的,因此我们需要将员工编号减去 1。例如,如果我们有 1000 个员工,每个员工在 Bitmap 中占用 2 个二进制位,那么员工编号为 1001 的员工在 Bitmap 中的起始偏移量为 2 * (1001 - 1) = 2000。

redis中bitmap使用场景结束-员工统计打卡

四、bitmap中key的设计

1、从员工角度,统计员工每日,每月的打卡情况,如何设计bitmap的key和offset

对于每个员工的打卡情况,我们可以使用 Redis 的 Bitmap 来存储。对于每个员工,我们可以为其创建一个以日期为后缀的键,例如 "checkin:employee_id:20220306" 表示员工在 2022 年 3 月 6 日的打卡情况。

为了方便统计每个员工在每日、每月的打卡情况,我们可以为每个员工创建两个特殊的键,分别用于记录该员工在某个月份内的所有打卡数据和该员工在某一天内的所有打卡数据。例如:

"checkin:employee_id:daily:20220306" 表示员工在 2022 年 3 月 6 日的所有打卡数据。
"checkin:employee_id:monthly:202203" 表示员工在 2022 年 3 月的所有打卡数据。
这些键的值都是一个 Bitmap,可以使用 Redis 的 BITOP 命令对多个 Bitmap 进行位运算,从而实现对多个键对应的 Bitmap 进行统计。

对于偏移量 offset,我们可以将其设为员工的编号,例如员工编号为 1001 的员工在 "checkin:employee_id:daily:20220306" 对应的 Bitmap 中的偏移量为 1001。当员工在某一天内打卡时,我们可以使用 SETBIT 命令将该员工在对应的 Bitmap 中的位设置为

SETBIT checkin:1001:daily:20220306 1001 1

这样,我们可以快速地获取该员工在某一天内的打卡情况,例如:

GETBIT checkin:1001:daily:20220306 1001

将返回该员工在 2022 年 3 月 6 日是否打卡的信息(0 表示未打卡,1 表示已打卡)。

类似地,我们可以使用 BITOP 命令对多个 "checkin:employee_id:daily:" 和 "checkin:employee_id:monthly:" 键的 Bitmap 进行统计,从而得到每个员工在每日、每月的打卡情况。

2、从时间角度,统计每月,每日所有员工的打卡,如何设计bitmap的key和offset

要统计每月、每日所有员工的打卡情况,我们可以创建两个键:

1)一个键用于记录所有员工在某一天的打卡情况,例如 "checkin:daily:20220306" 表示所有员工在 2022 年 3 月 6 日的打卡情况。

2)另一个键用于记录所有员工在某个月份内的打卡情况,例如 "checkin:monthly:202203" 表示所有员工在 2022 年 3 月的打卡情况。

这些键的值都是一个 Bitmap,可以使用 BITOP 命令对多个 Bitmap 进行位运算,从而实现对多个键对应的 Bitmap 进行统计。

对于偏移量 offset,我们可以将其设为员工的编号,例如员工编号为 1001 的员工在 "checkin:daily:20220306" 对应的 Bitmap 中的偏移量为 1001。当员工在某一天内打卡时,我们可以使用 SETBIT 命令将该员工在对应的 Bitmap 中的位设置为 1,例如:

SETBIT checkin:daily:20220306 1001 1

这样,我们可以快速地获取某个员工在某一天内的打卡情况,例如:

GETBIT checkin:daily:20220306 1001

将返回该员工在 2022 年 3 月 6 日是否打卡的信息(0 表示未打卡,1 表示已打卡)。

类似地,我们可以使用 BITOP 命令对多个 "checkin:daily:" 和 "checkin:monthly:" 键的 Bitmap 进行统计,从而得到每日、每月所有员工的打卡情况。

五、在线网址推荐:
https://try.redis.io/

点赞
收藏
评论区
推荐文章
blmius blmius
4年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(
Wesley13 Wesley13
4年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Jacquelyn38 Jacquelyn38
4年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Stella981 Stella981
4年前
Opencv中Mat矩阵相乘——点乘、dot、mul运算详解
Opencv中Mat矩阵相乘——点乘、dot、mul运算详解2016年09月02日00:00:36 \牧野(https://www.oschina.net/action/GoToLink?urlhttps%3A%2F%2Fme.csdn.net%2Fdcrmg) 阅读数:59593
Stella981 Stella981
4年前
KVM调整cpu和内存
一.修改kvm虚拟机的配置1、virsheditcentos7找到“memory”和“vcpu”标签,将<namecentos7</name<uuid2220a6d1a36a4fbb8523e078b3dfe795</uuid
Easter79 Easter79
4年前
Twitter的分布式自增ID算法snowflake (Java版)
概述分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的。有些时候我们希望能使用一种简单一些的ID,并且希望ID能够按照时间有序生成。而twitter的snowflake解决了这种需求,最初Twitter把存储系统从MySQL迁移
Wesley13 Wesley13
4年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Stella981 Stella981
4年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Python进阶者 Python进阶者
2年前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这