Redis用bitset(bitmap)来统计日活跃量

面对大量用户登录数据,使用传统方式存储会带来巨大数据库压力。本文介绍如何利用Redis的bitmap(bitset)功能,以1bit表示用户是否登录,大大降低数据存储量。以4个用户为例,展示了统计两天日活跃用户的实现过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

假设这样一个场景,假如每个网站有1亿的用户,那么我们怎么来统计这个网站的日登陆数或者说有哪些用户登录过这个网站。

最常见的做法就是设计一张用户登录表:

user_login:

user_uid    login_date

0                   2017-7-1

1                   2017-7-1

0                   2017-7-2

如果平均一个人一天登录1次,那么1亿个用户一个星期就会产生1 * 1 * 7 = 7亿条数据,一个月就会产生30亿条数据,这对数据库的压力是很大的,只是统计一下用户登录,没必要花费这么多的资源。

这个时候我们就可以用reids 的bitmap来解决。

用户是否登录可以用0/1来表示,0代表用户不登陆,1表示登录,那么1bit 就可以表示用户是否登录。

1亿个用户一天的数据量也就 1 0000 0000bit  = 11.92m,也就是说用户一天的登录信息也就产生11.92m的数据量。一个月也就357.63m的数据量。

具体实现过程(为了实验方便,我们就假设4个用户0,1,2,3,统计两天的登录量):

mon: 1010 (用户0未登录,用户1登录,用户2未登录,用户3登录)

tue:    1101 (用户0登录,用户1未登录,用户2登录,用户3登录)

127.0.0.1:6379> setbit mon 0 0
(integer) 1
127.0.0.1:6379> setbit mon 1 1
(integer) 1
127.0.0.1:637
Redis中,`BITSET` 是一种用于操作二进制位(bit)的强大命令,允许开发者将 Redis 的字符串值视为位数组(bit array)进行操作。由于 Redis 中的字符串本质上是字节数组,因此可以通过 `BITSET`、`GETBIT`、`BITCOUNT` 等命令实现高效的位图(bitmap)处理。 ### BITSET 命令的基本用法 `BITSET` 命令用于设置某个键中指定偏移位置的二进制位为 0 或 1。其语法如下: ``` BITSET key offset value ``` - `key`:存储数据的键。 - `offset`:从 0 开始的偏移,表示要设置的是第几位。 - `value`:要设置的值,只能是 0 或 1。 例如: ```bash BITSET mykey 7 1 ``` 此命令会将键 `mykey` 的第 8 位(索引从 0 开始)设为 1。如果该键不存在,则 Redis 会自动创建一个新字符串,并根据需要填充零位[^1]。 ### GETBIT 命令 获取某一位的状态使用 `GETBIT` 命令: ``` GETBIT key offset ``` 示例: ```bash GETBIT mykey 7 ``` 返回值为 0 或 1,表示对应位置的位是否被设置。 ### BITCOUNT 命令 统计一个字符串键中被设置为 1 的位数可以使用 `BITCOUNT`: ``` BITCOUNT key [start end] ``` 可选参数 `start` 和 `end` 用于指定字节范围,若不提供则统计整个字符串。 ### BITOP 命令 `BITOP` 可以对多个位图执行位运算(AND, OR, XOR, NOT),常用于用户行为分析或标签系统中的集合运算: ``` BITOP operation destkey key [key ...] ``` 例如,计算两个位图的交集: ```bash BITOP AND resultKey key1 key2 ``` ### 实际应用场景 - **用户签到系统**:可以用一个位图记录用户每月的签到情况,每一位代表一天是否签到。 - **去重计数**:使用 `BITCOUNT` 统计独立访问人数,节省内存空间。 - **权限管理**:某些轻级权限控制场景下,可以将权限信息编码到位中。 ### 示例代码(Java + Lettuce 客户端) 以下是一个使用 Lettuce 客户端操作 Redis Bitset 的简单示例: ```java import io.lettuce.core.RedisClient; import io.lettuce.core.api.StatefulRedisConnection; import io.lettuce.core.api.sync.RedisCommands; public class BitsetExample { public static void main(String[] args) { RedisClient client = RedisClient.create("redis://localhost:6379"); StatefulRedisConnection<String, String> connection = client.connect(); RedisCommands<String, String> commands = connection.sync(); // 设置 bit commands.bitSet("bitset:key", 0, true); // 将偏移0设为1 commands.bitSet("bitset:key", 1, false); // 将偏移1设为0 // 获取 bit boolean bitValue = commands.bitGet("bitset:key", 0); System.out.println("Bit at position 0 is " + bitValue); // 计算1的数 long count = commands.bitCount("bitset:key"); System.out.println("Number of bits set to 1: " + count); connection.close(); client.shutdown(); } } ``` ### 总结 Redis 提供了丰富的位操作命令,如 `BITSET`、`GETBIT`、`BITCOUNT` 和 `BITOP`,这些命令非常适合用于高效处理大规模位图数据,且内存占用极低。结合合适的客户端库(如 Lettuce 或 Jedis),可以在应用层轻松实现复杂逻辑。 ---
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值