之前专门聊过令牌桶算法,而类似的方案还有布隆过滤器。它一般用于高效地查找一个元素是否在一个集合中。
用js实现如下所示:
class BloomFilter {
constructor(size, hashFunctions) {
this.size = size;
this.bitArray = new Array(size).fill(0);
this.hasFunctions = hashFunctions;
}
add(item) {
for (let i = 0; i < this.hasFunctions.length; i++) {
const index = this.getHash(this.hasFunctions[i], item) % this.size;
this.bitArray[index] = 1;
}
}
contain(item) {
for (let i = 0; i < this.hasFunctions.length; i++) {
const index = this.getHash(this.hasFunctions[i], item) % this.size;
if (this.bitArray[index] === 0) return false;
}
return true;
}
getHash(hasFunction, item) {
return hasFunction(item);
}
}
const basicHashFunction = (item) => {
// Transform the item to string
const chars = String(item);
let hash = 0;
// Perform a simple hash calculation on each character in the string
for (let i = 0; i < chars.length; i++) {
hash = (hash << 5) + chars.charCodeAt(i); // combination of the bit operations and character ending
hash = hash & hash;
hash = Math.abs(hash);
}
return hash;
}
const secondHashFunction = (item) => {
let hash = 0;
for (let i = 0; i < item.length; i++) {
const char = item.charCodeAt(i);
hash = (hash << 5) - hash + char;
}
return hash;
}
// usage
const hashFunctions = [basicHashFunction, secondHashFunction];
const bloomFilter = new BloomFilter(1000, hashFunctions);
bloomFilter.add("item01");
bloomFilter.add("item02");
console.log(bloomFilter.contain("item02")); // output: true
console.log(bloomFilter.contain("item02")); // output: false
在上述代码中我们通过多个哈希函数计算元素的哈希值,减少哈希冲突问题。哈希函数还可以用第三方库,不一定非要自己实现,我给出的都是一些简单实现。
布隆过滤器有很多应用场景:
- 防止缓存穿透。判断数据是否在缓存中,以免不走缓存。
- 优化数据库请求。
- 防止恶意访问。如果该请求ip已经在保存恶意IP的布隆过滤器中,则阻止该请求。