Skip to content

手机号存储相关

Published: at 12:08 AM

国内手机号为11位数字,第1-3位—网络识别号;第4-7位—地区编码;第8-11位—用户号码。

如:

199      0000     1111
网络识别号 地区编码  用户号码

目前有效号段有57个,每个号段可表示10^8 1亿个手机号。

130,131,132,133,134,135,136,137,138,139,141,145,146,147,148,149,150,151,152,153,155,156,157,158,159,162,165,166,167,170,171,172,173,174,175,176,177,178,180,181,182,183,184,185,186,187,188,189,190,191,192,193,195,196,197,198,199

那如何存储所有有效号段呢?换句话说怎么存储以1大头的11位数字呢

还是以上文19900001111为例,各种形式表示占用空间大小。

手机号存储

使用bigint存储

(8*5700000000)/1024/1024/1024 = 42.46G

占用空间还是太大了,对于实时性要求比较高的场景,比如验证是否是黑名单等,需要响应速度快,存储空间小。

使用bit(位)存储,通过标记位是0或1表示数据是否存在,这其实是通过计算换存储的方式。

比如验证数字5是否存在,从右往左数,第5位为1即存在。

      5

0 0 0 1 0 0 0 0

那如何表示19900001111呢?

上文有提到19900001111二进制表示为35位,而一般的bitset(bitmap)限制数量为 2^32个。

以Redis Bitmaps为例,bit数量上限为2^32,数据存储大小上限为512MB。

2^32 = 4294967296

4294967296/8/1024/1024 = 512MB

而要存储的手机号需要2^35个bit,所以我们需要对其进行拆分。

还是以19900001111为例,199做key,剩余值10^8=1亿,而1亿需要多少存储呢?

100000000 / 8 / 1024 / 1024 ≈ 12MB

而有效号段57个,于是总共需要 12*57=684MB,就可以存储所有有效手机号。

补充个操作示例:

getbit b_199 12345678

setbit b_199 12345678 1

手机号&对应MD5存储

按bit存储,手机号和对应MD5值,57个有效号段需要约108G

(((35+128)/8) * 5700000000)/1024/1024/1024 = 108.16G

由于MySQL bit 最长64位,这里使用手机号使用bigint(8byte),MD5使用字符串格式存储(32byte)

((8+32)*5700000000)/1024/1024/1024 = 212.34G

再加上索引还需要乘2,约425G