Redis中BitMap使用
# BitMap介绍
Bitmap是一串连续的2进制数字(0或1),用1个bit位来表示一个数据是否出现过,0为没有出现过,1表示出现过,使用的时候可以根据某一个位是否为0表示此数是否出现过。8个bit可以组成一个Byte,所以bitmap本身会极大的节省储存空间。
# Redis中bitmap
Redis从2.2.0版本开始新增了setbit
,getbit
,bitcount
等几个bitmap相关命令,虽然是新命令,但是并没有新增新的数据类型,因为setbit
等命令只不过是在set上的扩展。
# 相关命令
setbit
- 指令
SETBIT key offset value
- 复杂度:
O(1)
- 指令
getbit
- 指令
GETBIT key
- 复杂度:
O(1)
- 指令
bitcount
- 指令
BITCOUNT key
- 复杂度:
O(1)
- 指令
# 使用场景
基于bitmap极低的时间和空间复杂度,在大数据标记等类似布隆过滤的场景有广泛的用武之地。以在线用户统计为例,设置用户ID为offset,如果在线就设置为1,不在线就设置为0,使用bitmap,1000W用户只需要1.2MB的空间。
require 'vendor/autoload.php';
$redis = new Predis\Client([
'host' => '127.0.0.1',
'port' => 6379
]);
// 连接redis
$redis->connect();
// 上线
function online($uid)
{
global $redis;
$redis->setbit('online', $uid, 1);
}
// 下线
function offline($uid)
{
global $redis;
$redis->setbit('online', $uid, 0);
}
// 判断是否在线
function isonline($uid)
{
global $redis;
$redis->getbit('online', $uid);
}
// 在线统计
function total()
{
global $redis;
return $redis->bitcount('online');
}
// 批量设置在线状态
$uids = range(1, 10000);
foreach ($uids as $uid) {
online($uid);
}
// 批量设置下线状态
$i = 0;
$max = mt_rand(1000, 3000);
while ($i < $max) {
offline(mt_rand(1, 10000));
$i++;
}
echo '当前在线人数: ', total(), PHP_EOL;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# 参考文档
上次更新: 2022/12/01, 11:09:34