Redis 学习笔记
Redis 理论
redis是一个key-value存储系统,和Memcached类似,支持存储的value类型相,包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash(哈希类型)。这些数据类型都支持push/pop、add/remove及取交集并集和差集等,而且这些操作都是原子性的。在此基础上,redis支持各种不同方式的排序。与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。
Redis 问题
Redis 雪崩
一般缓存都是定时任务去刷新,或者查不到之后去更新缓存的,如果出现某一时刻同时到期,那么大量访问就会转嫁到数据库上,而数据库无法承载,就会挂掉。
解决:
1、在批量往 Redis 存数据的时候,把每个 Key 的失效时间加个随机值保证数据不会再同一时间大面积失效。
setRedis(key, value, time+Math.random()*10000);
2、如果 Redis 是集群部署,将热点数据均匀分布在不同的 Redis 库中也能避免全部失效。
3、设置热点数据永不过期,有更新操作就更新缓存
缓存穿透
缓存穿透是指缓存和数据库中都没有的数据,而用户(黑客)不断发起请求。由于 Redis 在没有数据时会向数据库查询。于是,超出数据库承受能力的高访问量直接穿透 Redis 缓存层,压垮数据库,类似 DOS 攻击。
解决:
1、用户鉴权,参数做校验。
2、高级用法布隆过滤器(Bloom Filter),利用高效的数据结构和算法快速判断出 Key 是否在数据库中存在,不存在 return,存在就去查 DB 刷新 KV 再 return。
缓存击穿
我又接着说:缓存击穿是指一个 Key 非常热点,在不停地扛着大量的请求,大并发集中对这一个点进行访问,当这个 Key 在失效的瞬间,持续的大并发直接落到了数据库上,就在这个 Key 的点上击穿了缓存。
解决:
1、设置热点数据永不过期。
2、加互斥锁。
public static String getData(String key) throws InterruptedException {
//从Redis查询数据
String result = getDataByKV(key);
//参数校验
if (StringUtils.isBlank(result)) {
try {
//获得锁
if (reenLock.tryLock()) {
//去数据库查询
result = getDataByDB(key);
//校验
if (StringUtils.isNotBlank(result)) {
//插进缓存
setDataToKV(key, result);
}
} else {
//睡一会再拿
Thread.sleep(100L);
result = getData(key);
}
} finally {
//释放锁
reenLock.unlock();
}
}
return result;
}
参考:
https://baijiahao.baidu.com/s?id=1660009541007805174&wfr=spider&for=pc