
起源于我在一个短视频中分享的一道面试题,当然,这道面试题我确实在工作中用过,只是业务场景不同。
题目是:假设有这样一个需求场景,需要将所有用户的商品id存储到redis缓存,某个接口要求判断请求的商品id是否在数据库中,也就是是否在redis缓存中,请问你觉得使用哪种数据结构类型缓存商品id最合适?
这道题考察面试者:
- 对
redis数据结构类型的了解,能够根据业务场景使用合适的类型 bitmap算法,也是考察算法- 遇到
id值很大,即超过int类型的最大值时,如何应对,即思维能力
1
某位朋友提问:
请教个问题,网上说bitmap常用来进行用户活跃度,签到的统计。它的bit位也只能存储0或1,为什么用bitmap能提升性能呢?
我的回答:
Set集合查询时间复杂度是O(1),但是有Hash冲突,可能带有链表的遍历,而bitmap访问相当于数组下标。
bitmap只用1bit存一个商品id,在商品id分布均匀情况下,节省的内存是存储商品id字符串的多少倍?需求场景是只需判断一个商品id是否在缓存中,那么0和1还不够吗?setbit key 商品id 0/1
追问:
我懂了,命令SETBIT key offset value,这里是将id作为offset使用,不同的id对应不同的位,而不是作为key使用,多谢解答[赞]。
另一位朋友作出的解答很好:
你确定bitmap一定可以?我要是没记错key范围是int,很多id都是long。
我的解释:
确实[赞]。这时候就是下一个问题了。
key不是只能有一个,可以用多个key存储,这就是分桶的概念。假设第一个桶,也就是key1,用来存1到100000000的id,那么第二个桶就可以存100000000到200000000亿的id,不过是先将id减去100000000。有没有必要分桶,主要还是看商品数量到一个什么级别,以及商品id的最大值。
2
某位朋友提问:
我们项目里用户id是uuid生成的14位数值,本来想存bitmap,想想还不如sql统计登陆的日志呢[泪奔]
我的回答:
非整数类型用不了这种数据类型存储,可以借用布隆过滤器插件实现,但是有误差存在,需要确保误差不会影响正常业务。
一般都是使用自增主键。id作为主键索引,使用自增主键比用uuid的插入性能高,这是索引B+树的知识点。
追问:
如果是分布式数据库用自增主键可能会有冲突吧?
我的回答:
分布式数据库可以用雪花算法等分布式 id生成算法,id可以不是自增,但最好是保持增长的,单个数据库节点的单个表的主键确保是增长的。uuid这种太随机。
提问者的自我回答:
对,因为插入时候b+数是按顺序向右扩展的。