解锁缓存姿势
1. 访问缓存场景分析。
1.1 缓存穿透
现象: 每次请求直接穿透缓存层, 直接访问数据库, 给数据库带来巨大的访问压力。
原因: 访问数据会先访问缓存, 如果缓存不存在数据才会查询数据库, 但是如果数据库也没有数据, 则当前访问的数据永远不会写入缓存。这样就会导致,每次请求都会到db层, 造成数据库负担过大。
解决方案:
- 如果db查询不到数据, 保存空对象到缓存层, 设置较短的失效时间;
- 针对业务场景的参数进行有效性校验, 防止非法请求。
1.2 缓存击穿
现象: 当某个key失效时, 造成大量请求到db层, 击垮储存层。
原因: 为了保证缓存数据的时效性,通常会设置一个失效时间,如果是热点key, 高并发时会有大量请求直接越过缓存层到数据库, 会给数据库造成负担过大。
解决方案:
-
使用互斥锁, 当缓存数据失效时 ,保证一个请求能够访问到数据库, 并更新缓存,其他线程等待并重试。
public String get(key) { String value = redis.get(key); if (value == null) { //代表缓存值过期 //设置3min的超时,防止del操作失败的时候,下次缓存过期一直不能load db if (redis.setnx(key_mutex, 1, 3 * 60) == 1) { //代表设置成功 value = db.get(key); redis.set(key, value, expire_secs); redis.del(key_mutex); } else { //这个时候代表同时候的其他线程已经load db并回设到缓存了,这时候重试获取缓存值即可 sleep(50); get(key); //重试 } } else { return value; } }
1.3 缓存雪崩。
现象: 多个key失效, 造成大量请求到db层, 导致db层负担过重。
原因: 缓存雪崩是指在我们设置缓存时采用了相同的过期时间, 导致缓存在某个时刻同时失效, 请求全部到db层, 导致数据库负担过大。
解决方案:
- 使用互斥锁的方式, 保证只有单个线程能够到达db层。
- 每个key的失效时间在基础时间上加上1-5分钟的随机值, 这样就能保证大规模key集体失效的概率。
数据更新场景
1.先更新数据库再失效缓存 :这是推荐的更新数据时采用的方式。
Redis支持的数据类型
String 字符串
- 格式: set key value
- string类型是二进制安全的。意思是string可以包含任何数据。一个键能储存512MB
Hash(哈希)
- 格式: hmset name key1 value1 key2 value2
- Redis hash 是一个键值(key- value)对集合。
List(列表)
Redis列表是简单的字符串列表, 按照插入顺序排序。可以添加一个元素到列表的头部或者尾部
- 格式: lpush name value
- 在key对应list的头部添加字符串元素。
- 格式: rpush name value
- 在key对应list的尾部添加字符串元素。
- 格式: lrem name index
- key对应list 中删除count个和value相同的元素
- 格式: llen name
- 返回key对应list的长度。
Set(集合)
- 格式: sadd name value
- redis的Set是string类型的无序集合, 集合成员是唯一的,这就意味着集合中不能出现重复的数据
- 集合是通过哈希表实现的, 所以添加, 删除, 查找的复杂度都是O(1)
Zset(sorted set: 有序集合)
- 格式: zadd name score value
- 不同的是每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序。
- zset的成员是唯一的,但分数(score)却可以重复。
Redis中两种持久化机制RDB和AOF
1、RDB机制
RDB就是把数据以快照的形式保存在磁盘上。快照可以理解为把当前时刻的数据拍成一张照片保存下来, 提供了三种机制: save、bgsave、自动化。
-
save触发方式
该命令会阻塞当前Redis服务器,执行save命令期间,Redis不能处理其他命令,直到RDB过程完成为止。具体流程如下:
执行完成时候如果存在老的RDB文件, 就会用新的代替叼。
-
bgsave触发方式
执行该命令时,Redis会在后台异步进行快照操作,快照同时还可以响应客户端请求。具体流程如下:
就是创建子进程,用于持久化操作。阻塞只发生在创建子进程阶段,一般时间很短。基本上Redis内部所有RDB操作都是采用bgsave命令。
-
自动触发
自动触发是由我们配置文件来完成。
-
save与bgsave区别
2、AOF机制
-
持久化原理: 每当有一个写命令时,就直接保存在AOF文件中。
- 文件重写原理: AOF的方式也带来了另外一个问题, 持久化文件会变得越来越大。redis提供了bgrewriteaof命令。创建一个子进程讲内存中的数据重写, 和快照有点类似。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Uuz2PoVO-1589448113473)(C:\Users\rookie\Desktop\笔记\img\13.jpeg)]
-
AOF也有3钟触发机制
-
每修改同步always:同步持久化 每次发生数据变更会被立即记录到磁盘, 性能较差但数据完整性比较好
-
每秒同步everysec: 异步操作,每秒几率, 如果一秒内宕机, 会有数据丢失。
-
不同no: 从不同步。
3. RDB和AOF到底该如何选择
选择的话,两者加一起才更好。因为两个持久化机制你明白了,剩下的就是看自己的需求了,需求不同选择的也不一定,但是通常都是结合使用。有一张图可供总结: