Redis位图-"抠抠搜搜过日子"

133 阅读3分钟

14亿个手机号,如何去重?

HashMap/HashSet

用HashMap的key唯一来去重。
弊端:手机号码是11位数字,每个数字都是0-9之间的数字,因此每个数字占用4个bit,4 * 11 = 44 bit,44 / 8 = 5.5 byte,向上取整为6byte14亿 * 6Byte /1024/1024/1024 = 7.8G

文件切割

避免内存过大。可以通过hashcode进行拆分,相同的手机号码会被拆分到同一个小文件中,之后在每个小文件去重。
弊端:海量文件操作。效率低下

Redis位图

Redis位图是什么
Redis位图(Bitmap)是一种使用单个Redis字符串来存储二进制位的数据结构。通过使用位运算来设置、获取或者清除单个位,可以使用位图来表示和压缩大量二进制数据。
查重原理
每个手机号码代表一个整数位,然后将该整数对应的位设为1表示该号码存在,0表示该号码不存在。
具体步骤:
1.首先创建一个位图,长度为2048(字节)(考虑偏移量可以偏大一点),命名为phone_bitmap。(11为数字转化为二进制最大为:11111111111,高位进一:100000000000,2048字节,理论最大占用内存 2048/1024 = 2KB)

2.使用SETBIT命令将对应位设为1。例如手机号码为13800138000,对应的bit位设为1 :SETBIT phone_bitmap 13800138000 1 。

3.判断一个号码是否存在,使用GETBIT命令获取对应的位。例如查询手机号码13800138000是否存在:
GETBIT phone_bitmap 13800138000

4.如果返回值为1,则说明该号码存在;如果返回值为0,则说明该号码不存在。
常用业务场景
1.统计在线用户数量:使用Redis位图可以方便地记录用户的在线状态,当用户登录时将其在位图中的对应位置设置为1,退出时将其位置设置为0,这样可以通过位图中1的数量来快速统计在线用户数量。

2.统计用户活跃度:可以将位图理解为一个布隆过滤器,每个位代表一个元素是否存在,因此可以快速地判断一个用户是不是活跃用户。

3.压缩数据:Redis位图经常被用于压缩一些只包含01的数据,比如用户行为数据或者设备状态数据等等。将这些数据存储在Redis位图中,可以减少存储空间的使用,并且通过位运算可以快速查询这些数据。

可操作步骤列表:

1.设置位图:使用SETBIT命令可以将某个位置设置为1,例如SETBIT user:1 1000 1可以将user:1的位图中,第1000位设置为12.获取位图:使用GETBIT命令可以获取某个位置的值,例如GETBIT user:1 1000可以获取user:1的位图中,第1000位的值。

3.统计位图中1的数量:使用BITCOUNT命令可以统计位图中1的数量,例如BITCOUNT user:1可以统计user:1的位图中1的数量。

4.求多个位图的并、交、异或等操作:使用BITOP命令可以对多个位图执行并、交、异或等操作,例如BITOP AND result user:1 user:2可以将user:1user:2的位图进行与操作,并将结果存储到result中。

5.使用位图进行过滤:可以将位图理解为一个布隆过滤器,将一些只包含01的数据存储在位图中,使用位运算快速判断某个元素是否存在。