1.并发量小的情况下,可以针对昵称列加数据库字段唯一键
2、并发量大的情况下,使用布隆过滤器。
- 布隆过滤器(Bloom Filter)是一种高效的概率型数据结构,主要用于判断元素是否属于集合,具有空间效率高,查询速度快的特点,但存在误判率且不支持删除操作。
①. 核心原理
-
数据结构:由位数组(二进制向量)和多个哈希函数组成,初始所有位为012。
-
插入过程:元素通过多个哈希函数映射到位数组的多个位置,并将对应位设为134。
-
查询过程:若所有哈希对应位均为1,则元素可能存在于集合中;若任一为0,则元素一定不存在14。
-
误判原因:不同元素的哈希值可能碰撞,导致误判(假阳性),但不会漏判(假阴性)25。
②. 典型应用场景
-
缓存穿透防护:在Redis缓存前过滤无效请求,避免数据库压力34。
-
网络爬虫去重:标记已访问的URL,避免重复抓取45。
-
垃圾邮件过滤:快速识别黑名单中的邮件地址26。
-
分布式系统:如海量数据去重、区块链交易验证等5。
③. 使用示例
import com.google.common.hash.BloomFilter;
import com.google.common.hash.Funnels;
import java.nio.charset.StandardCharsets;
public class BloomFilterExample {
public static void main(String[] args) {
// 初始化布隆过滤器,预计存储10万姓名,误判率0.0001
BloomFilter<String> bloom = BloomFilter.create(
Funnels.stringFunnel(StandardCharsets.UTF_8),
100000,
0.0001
);
// 模拟从数据库读取姓名并存入布隆过滤器
String[] names = {"张三", "李四", "王五", "赵六", "陈七"};
for (String name : names) {
bloom.put(name);
}
// 查询示例
String queryName = "张三";
if (bloom.mightContain(queryName)) {
System.out.println(queryName + " 可能在数据库中");
} else {
System.out.println(queryName + " 一定不在数据库中");
}
queryName = "未知名字";
if (bloom.mightContain(queryName)) {
System.out.println(queryName + " 可能在数据库中");
} else {
System.out.println(queryName + " 一定不在数据库中");
}
}
}
1、缓存穿透:查询缓存和数据库都不存在的数据,缓存没有,数据库也没有
2、缓存击穿:缓存中数据的key过期了,这时候所有请求都到数据库查询,瞬时大量请求击穿数据库
3、缓存雪崩:缓存雪崩通常是发生在大量key同一时间失效,大量请求直接打在DB上,影响整个系统。而缓存击穿是针对某一具体的缓存key失效而言,影响相对局部。