27.上的了天但落不了地的BloomFilter

吹牛拍码

共 1263字,需浏览 3分钟

 ·

2023-03-04 11:33

1 BloomFilter是个好东西

它思路清奇,辗转腾挪,号称可解决Redis缓存三大困境之首的穿透问题,是后端面试必备的佳品,但你见过有文章介绍过BloomFilter怎么落地么?似乎没有~

Redis缓存三大困境:穿透、击穿、雪崩。null object可以解决正常的穿透问题,然而面对黑客人恶意制作的穿透则无能为力,但BloomFilter可以。以用户注册登录为例,BloomFilter通过预先收集所有有效uid,并创建一个多hash的bitmap向量,可以有效拦截恶意uid登录的情况。

好了,从这里开始,几乎所有文章都会转向介绍BloomFilter如何优秀,或者其实现原理如何如何。但却故意跳过了一个很关键的问题:BloomFilter如何更新?

仍然以用户注册登录为例。我们预先创建一个包含所有uid的bitmap向量没有问题,但是当有新用户注册后,如何把新注册用户的uid加入到BloomFilter中呢?


2 看似可行的方案

1 Dual Write

中文翻译为交叉写或双写,即在新注册用户成功后,立马把新注册用户的uid加入到BloomFilter中。

这个方案的优点是实时性很好。但问题是:万一新注册用户成功了,但写Redis失败了怎么办?比如有新用户的注册的时候,刚刚在MySQL注册成功,但还未来得及写入到Redis时,由于网络闪断,写Redis超时了。此时MySQL就比Redis中多一个新注册的用户uid,该用户在登录系统就无法通过BloomFilter验证了。

只所以把Dual Write翻译为『交叉写』,是暗含着在并发情形下,写入MySQL的顺序与写入Redis的顺序可能并不相同。这在很多情况下是无法接受的,比如用户转账类业务,也因此导致Dual Write不是一个常规方案。但在BloomFilter应用场景中,恰好对不同用户uid的写入顺序不敏感。


2  Change Data Capture

数据变更捕获,简称CDC。在我们的前述应用场景中,简化的思路是新启动一个服务进程,把自己模拟成MySQL的从库,通过解析binlog,拿到新注册用户的uid,然后再将这个uid写入到BloomFilter中。

正式的CDC过程,通常会先把解析出来的binlog写入到kafka之类的消息队列中,通过消息队列相关的可靠性方案保证新用户的uid一定会写入到BloomFilter中,因此不会有丢消息的情形。

这个方案的优点是可靠性很好。但问题是:kafka消息消费可能有延迟。假如我们新注册了一个用户,但1分钟之后才消费到该用户的注册消息,那么这1分钟之内该新用户登录系统也是通不过BloomFilter验证的。

3 落地方案

讲了半天,应该如何既要XX又要XX呢?

说穿了一文不值:既然我们既想要Dual Write的实时性,又要CDC的可靠性,那么我们只要同时使用这两个方案就好了~


4 别打我

但你可以来公众号挑衅我,有本事你。。。。过来呀~

5 References

  1. 16.从核酸检测到BloomFilter




浏览 25
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报