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 别打我
但你可以来公众号挑衅我,有本事你。。。。过来呀~