背景
用户中心是授权逻辑与用户信息相关逻辑构建的应用。分布式系统中,大多数业务都需要和用户中心打交道,为了保证用户中心服务的高可用,避免不了做缓存、导入搜索引擎从而降低数据库的压力。然而有些不经过用户中心授权的业务场景查询用户中心的数据,可能引发大量无效的查询,发生缓存穿透,直接对搜索引擎和数据库造成压力。如何解决用户中心缓存穿透的问题呢?接下来就着重说一下布隆过滤器是怎么“隔档”这些无效查询的。
缓存穿透缓存穿透是指用户查询数据,在数据库没有,自然在缓存中也不会有。这样就导致用户查询的时候,在缓存中找不到对应key的value,每次都要去数据库再查询一遍,然后返回空(相当于进行了两次无用的查询)。这样请求就绕过缓存直接查数据库。
布隆过滤器 基本概念布隆过滤器(Bloom Filter)是1970年由布隆提出的。它实际上是一个很长的二进制向量(位图)和一系列随机映射函数(哈希函数)。
布隆过滤器可以用于检索一个元素是否在一个集合中。它的优点是空间效率和查询时间都远远超过一般的算法,缺点是有一定的误识别率和删除困难。
特点空间效率高和查询效率高的概率型数据结构。
对于一个元素检测是否存在的调用,BloomFilter会告诉调用者两个结果之一:可能存在或者一定不存在。
一个很长的二进制向量 (位数组)。
一系列随机函数(哈希)。
有一定的误判率(哈希表是精确匹配)。
原理布隆过滤器(Bloom Filter)的核心实现是一个超大的位数组和几个哈希函数。假设位数组的长度为m,哈希函数的个数为k。
(1) 添加元素过程
将要添加的元素给k个哈希函数。
得到对应于位数组上的k个位置。
将这k个位置设为1。
(2) 查询元素过程
将要查询的元素给k个哈希函数。
得到对应于位数组上的k个位置。
如果k个位置有一个为0,则肯定不在集合中。
如果k个位置全部为1,则可能在集合中。
相关公式很显然,根据布隆过滤器的原理和特性,bit数组大小和哈希函数的个数都会影响误判率。那么布隆过滤器是如何权衡bit数组大小和哈希函数个数的呢?
假设布隆过滤器bit数组大小为m,样本数量为n,失误率为p。
假设样本容量n=5000W,误判率是0.03,那么所需要的内存空间大小是m = -5000W * -3.057 / (0.7)^2 ≈ 318,437,500 ≈ 39.8MB
演示(1)参考地址
https://www.jasondavies.com/bloomfilter
(2)可能存在
(3)一定不存在
Guava Bloom FilterGuava中,布隆过滤器的实现主要涉及到2个类, BloomFilter和 BloomFilterStrategies。首先来看一下 BloomFilter的成员变量。需要注意的是不同Guava版本的 BloomFilter实现不同。