bitset
的好处很多,尤其是第一次接触到这个结构的人。觉得只需要一个key就可以很简单的处理这个标志位的数据, 甚至说几个亿的offset占用内存也会很小。
但在项目实际使用过程中还是要好好算算这笔账的。bitset
占用的内存是用最大的offset
来决定的,根本不会管你实际要存多少有效数据,计算公式为
占用内存bit = 最大offset
占用内存B = 最大offset / 8
占用内存KB = 最大offset / 8 / 1024
占用内存MB = 最大offset / 8 / 1024 / 1024
比如现在我们要存用户对一篇文章的点赞数, 以及判断用户对文章有没有点赞。
如果使用bitset
, 那么确实一篇文章只要一个key就行了,也没有hash
或set
的结构复杂,比如文章id为1, 简单点key的名字就为article:star:1
。
那么点赞确实很简单,如果用户id=100
## 点赞命令
setbit article:star:1 100 1
## 获取点赞数量
bitcount article:star:1
## 判断指定用户是否点赞
GETBIT article:star:1 100
看下占用内存忽略不计
使用起来很简单吧,效果看起来也很开心。
但如果这个时候又来了一个用户点赞,用户id=2560000呢
使用方式没有变化,也完成了点赞的统计。但是占用内存呢?
这是什么概念?记录一篇小小的文章点赞数,即使只有两个人点赞, 就占用了312.5KB,来个几百篇文章或者动态之类的,再加上其他功能也这么使用用,这要浪费吃掉多少内存。
要是系统再使用雪花算法之类的生成用户id那可真是太刺激了。
因此用bitset的时候除了考虑系统人数规模(主要是决定bitset offset值的条件),还要考虑实际会有多少人用到这个功能。即使人数达到了很大的量级,但某个功能是个很偏僻的功能,还是要少用。
总结如下
- 使用之前永远要作为第一要务考虑的就是offset的基数大小问题
- 如果uv很小,而且offset基数又很大,不要使用,offset基数很小,可以用
- 如果uv非常高,offset基数即使大一点,也可以使用,但这个要综合考虑去计算offset基数到底多大,uv又有没有高到离谱的程度。否则仍然还是set或者hash之类的更适用。