您的位置:首页 > 运维架构

上亿在线用户维护最高效的设计思想,二进制位存储变更的应用场景

2017-08-21 17:10 381 查看
应用场景:在某大型互联网公司,有上亿的用户,要统计当前用户的在线人数和在线用户id,最快的实现方法是什么?

答:一般情况下,我们都使用数据库字段在用户登陆状态发生变更时进行变更,查找在线人数和在线用户id都是用select的方式。但是这种方式在实际中,调取速度非常慢,效率比较低,时效性差。

在redis中,我们知道setbit,bitcount等方法,可以直接对二进制位进行存储和变更,以及计数,根据这些我们讲述一下它的实现思想。

setbit(name,offset,value),对name对应值的二进制表示的位进行操作。参数offset,位的索引(将值变换成二进制后再进行索引,起始位0);value,值只能是1或0。

getbit(name,offset),获取name对应值的二进制表示中的某位的值(0或1)。

bitcount(key,start=None,end=None),获取name对应的值的二进制表示中1的个数。参数key,Redis的name;参数start,位起始位置;参数end,位结束位置。

注意:

通过在redis中实际检查,我们确认了以下的情况:

1.参数offset的索引的起始位为0;

2.getbit中,超出参数name指定的字符串值的索引的对应位的默认值均为0

3.在setbit中我们可以设置超出指定字符串位的索引位的相应的位值。



通过上面的实现,我们了解到我们可以在数据库中通过字段的变更和查看,我们为了维护上亿的用户的信息,提升其调用效率和速度,我们可以使用二进制位的设定。

设置一个key,如state_code,如果用户登陆,就通过“setbit state_code offset 1” 来改变用户的登陆状态(offset用唯一的用户id来指定,字符位为1的代表用户为登陆状态,0为离线状态)。

注:想要获取字符串的二进制位,可以先将其转成ascii码(ord()),再将ascii码转换成二进制位(bin())。如:ord('a'),返回97;bin(97),返回0b1100001。



通过上面的命令,我们可以发现,我们设置了用户id为0,8,10000000和1000000000的登陆状态为登陆状态(位值为1)。

再通过bitcount我们可以清楚地掌握当前的在线用户数。

想要了解当前的在线用户的id,我们可以通过for循环实现,将位值为1的依次打印出来即可。

有点:效率大大提升,10M就能存下10*1024*1024*8=83886080 八千多万的用户的登陆id和在线用户数,相对于数据库字段的调用,无论是存储,写入,修改,读取的速度都大为提升。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: