Redis位操作

Redis位操作的那些坑

BG

初创项目需要严格统计UV指标,但是APP未登陆和未注册的用户统计则带来了一些问题。因此采用uid和设备两个维度进行数据统计。从设备角度来看,我们可以简单的认为每个设备就是一个活跃的用户。因为统计指标这种事,使用关系型数据库来处理极为不便,况且这种每次都需要更新指标,使用关系型数据库也会有性能问题。
于是我们采用了Redis这种非关系型数据库。而Redis本身具有HypeLogLog这种基于技术统计的数据结构。set这种能够结构和bitmap等。由于考虑到项目初期的原因,我们需要的是精确的指标,因此我们采用了内存和精确度兼具的bitmap。
但是问题来了,设备号是无法进行位偏移操作的。因此我们首先解决的是如何将设备号和offset所关联。

位偏移量的抉择

在刚开始的时候,为了提升效率。使用数据库这块,需要引入新的数据库表设计,而且由于设备号唯一,那么势必需要在设备号上进行索引,这样在MySQL上这种无序的索引效率本身就偏差,而且需要每次进行一次数据库IO的操作,因此我们选择了不使用该方法,而是采用了hash的方式,这样在数据量小的时候,我们可以比较精确的统计出数据,在数据量大的时候,我们对冲突带来的误差也可以接受,这样避免了一次数据库IO,怎么看都是划算的。由于精确性和简单性的考虑,我们没有采用数组方式(避免冲突和扩容带来的额外操作),而是直接采用对设备号取hashCode()的方式。

噩梦的来临

就在家高高兴兴的过周末的时候,突然飞哥打电话说线上Redis的过慢,导致其它任务失败了。并且打印了出了SLOWLOG,显示计算30天的指标超过了8S。线上的逻辑是对于今天往前推30天,对30天的key进行位或得出30天内设备访问总数(位或去重)。

定位问题

猜想一

由于代码之前项目中有现场的案例,我就对比,对于Redis位操作使用方式是一样的。于是我对于两个操作分别进行了耗时统计,证明基本上只需要50ms,而唯独这个计时需要8s。那么问题出现在哪?无疑,命令是正确的,对于所有的key长的都类似,不会出现因为key的原因导致耗时增加,那么原因就是因为value。因为是刚统计的指标,所以redis中很多天对应的key的值都是nil。我怀疑是value为nil导致的。

验证一

因为我对于所有的没有value的key,全部设置为0。再进行测试,发现毫无用处。

猜想二

于是我陷入了沉思(事实上很慌)。我赶紧下载了Redis,重新设置了30个key,每个key都为0 。再验证,发现程序运行的如火箭般。现在唯一可以确定的是就是value的问题。我默默debug了一下,发现了一个惊人的事实,在计算位偏移量的时候,结果是10亿多,那么问题来了,对于每一位进行位或,一共30 个key。一旦遇到了这种value,那么以后每个key对应的值进行位或,那么岂不是灾难。

解决问题

我们采用了新的方案生成了位偏移量,(数据库)最终我们还是妥协了。

总结

事实告诉我们,开发并不是面试早火箭,每个细节都将影响着项目的情况。且行且珍惜,我只想躺平啊~~~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值