Bitmap的使用

Posted by KANG's BLOG on Thursday, March 17, 2022

1 操作命令

Bitmap在Redis中并不是一个单独的数据类型,而是由字符串类型(Redis内部称Simple Dynamic String,SDS)之上定义的与比特相关的操作实现的,此时SDS就被当做位数组了。

SETBIT key offset value
getbit key offset

在redis中,借助Bitmap可实现布隆过滤器。

Redis实现bitmap是基于字符串类型的,所以使用bitmap应注意value的大小,字符串类型value最大为512M

232 / 8 = 1024 * 1024 * 512

2 使用bitmap进行日活统计

/**
 * 用户的loginInfoId的hashCode与1048576个槽进行与运算,value最大为255KB,一年为90M
 */
private int getUserKey(String systemCode, String userId) {
    redisClient.setbit(systemCode + LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd")), getUserKey(userId.hashCode()), true);
}

/**
 * 用户Id的hashCode和1048576(2 ^ 20)个槽进行与运算,value最大为255KB,一年约为90M
 * hash值做了高低位异或运算,使大于20以上高位参与低位计算
 */
private int getUserKey(int hash) {
    return (hash ^ (hash >>> 10)) & ((1 << 20) - 1);
}

槽越少,储存成本越小,但冲突概率越大,因此,20是当前方案中对存储大小和槽数的平衡。

对此,可以固定周期对统计值进行持久化后删除key,则直接使用32位的槽并取消高低位异或,即hash & ((1 << 32) - 1)