关闭

基于bitset实现手机号的黑白名单方案

307人阅读 评论(0) 收藏 举报

目前很多app都把手机号码作为登录的账户名,本文介绍一种高效的基于手机号,来实现黑白名单的方案。

在这里我先用一个例子来说明位图。

      假设我有一个0到31的集合,集合里面的元素不重复,比如这样{0,3,1,5,2,19,7,8,31,21,10}。通过位图,我可以将这样的集合表示为11110001101000000001010000000001, 其中1表示该数值为下标的数存在在集合中,比如第一个1表示0存在集合中,第二个1表示1存在集合中,等等。通过这样做,我们起码可以得到两个好处

      1) 节省空间--我们可以用二进制一个位来存储存储两个信息,一是存不存在,而是存在的数是多少(通过一个bit就可以得到这么多信息,真了不起)。

      2) 排序--从左到右遍历这个为图,我们可以得到排序的集合,比如上例中,我们可以得到集合 {0,1,2,3,7,8,10,19,21,31}

      如果将所有这电话号码用位图表示,那么需要9999999999个bit (10个9, 考虑到手机号码的第一位都是1)。 9999999999 bit = (9999999999/8) byte = (9999999999 / (8 * 1024)) KB = (9999999999 / 8 *1024*1024) M = 1192M

      嗯....,1192M,内存占有还是太大,我们前期的黑白名单所占内存远远低于这个值。 考虑到手机号码的前3位都差不多,而且总数最多30个,所以考虑到手机号码拆分为两部分(头3位和剩余8位),这样就把位图的位数就降2个数量级了。所以如果我们要在内存中装入手机号码后8位,需要99999999(8个9)个bit,算一下

      99999999 bit = (99999999/8) byte = (99999999 / (8 * 1024)) KB = (99999999 / 8 *1024*1024) M = 11.92M 

内存中装入头2位(手机号第一位始终为1,因此只需装入后面2位),需要99(2个9)个bit,算下 
99 bit = 99/8 byte =12.375 byte。 

大约12M 内存,就能表示所有手机号码,达到黑白名单。 这个比用redis等缓存,高效很多,java里面的bitset也是这个原理。
0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:7059次
    • 积分:170
    • 等级:
    • 排名:千里之外
    • 原创:10篇
    • 转载:0篇
    • 译文:0篇
    • 评论:0条