Redis
[Redis 是单进程单线程的]
支持并发11万读操作、并发8万写操作。
a:定义
a.1 特点&好处
1快
/完全基于内存/数据结构简单,对数据操作也简单/采用单线程/使用多路I/O复用模型,非阻塞IO
2
3 支持事务
4丰富的特性:可用于缓存,消息,按 key 设置过期时间,过期后将会自动删除
b:类型/使用场景/基础操作指令
类型 | 使用场景 | 指令 | 底层实现 | 特点 | |
String | 序列化对象 | Sds | 一个键最大存储512M | ||
hash | 存储对象 | 压缩列表/字典 | |||
List | 1 消息队列 2 最新消息排行榜 | 压缩列表/双端链表 | 增删快 | ||
Set | 1 共同好友 2 统计独立ip | 整数集合/字典 | 元素不重复 | ||
Sorted | 1 排行耪 2 带权重的消息队列 | 压缩列表(ziplist)/ 跳跃表(skiplist) |
redis过期策略
redis使用的回收策略是:惰性删除/定期删除/定时删除
Rdb 与aof对比
名称 | 执行机制 | 优点 | 不足 |
rdb | 快照 | 性能高 | 在save配置条件之间若发生宕机,此间的数据会丢失 |
aof | 将对数据的每一条修改命令追加到aof文件 | 数据不容易丢失 | 性能较低 |
RedisTemplate和StringRedisTemplate的区别
1. 两者的关系是StringRedisTemplate继承RedisTemplate。
2. 两者的数据是不共通的;也就是说StringRedisTemplate只能管理StringRedisTemplate里面的数据,RedisTemplate只能管理RedisTemplate中的数据。
3. SDR默认采用的序列化策略有两种,一种是String的序列化策略,一种是JDK的序列化策略。
StringRedisTemplate默认采用的是String的序列化策略,保存的key和value都是采用此策略序列化保存的。
RedisTemplate默认采用的是JDK的序列化策略,保存的key和value都是采用此策略序列化保存的
回收策略:
1 volatile-lru:从已设置过期时间的数据集(server.db[i].expires)中挑选最近最少使用的数据淘汰
2 allkeys-lru:从数据集(server.db[i].dict)中挑选最近最少使用的数据淘汰
3 volatile-random:从已设置过期时间的数据集(server.db[i].expires)中任意选择数据淘汰
4allkeys-random:从数据集(server.db[i].dict)中任意选择数据淘汰
5 volatile-ttl:从已设置过期时间的数据集(server.db[i].expires)中挑选将要过期的数据淘汰
6 no-enviction(驱逐):禁止驱逐数据
>>幂规 == allkeys-lru
>> 平等 == allkeys-random
[主从同步,从从同步]
集群
(1)Redis Sentinal 着眼于高可用,在 master 宕机时会自动将 slave 提升为master,继续提供服务。
(2)Redis Cluster 着眼于扩展性,在单个 redis 内存不足时,使用 Cluster 进行分片存储
异步复制/数据库从0开始/最大节点数-16384
采用虚拟槽方式。
Redis事务命令:
Mulit/开始一个事务
exce/执行事务
discard/放弃事务
Un|Watch/取消对所有key的监视|监视
[
>>redis不保证数据强一致性。
>>如果内存用完,可读不可写。
>>一个redis实例最多可以存储232个key
>>如果大量的 key 过期时间设置的过于集中,到过期的那个时间点,redis 可能会出现短暂的卡顿现象。一般需要在时间上加一个随机值,使得过期时间分散一些
>>一般使用 list 结构作为队列,rpush 生产消息,lpop 消费消息
]
redis异常问题
缓存雪崩
造成原因:
>>原有缓存失效,新缓存未到]期间所有原本应该访问缓存的请求都去查询数据库了
造成的结果而对数据库CPU和内存造成巨大压力,严重的会造成数据库宕机
解决
>>加锁排队(不推荐:原因线程还会被阻塞,用户体验很差)
>>增加缓存标致
>>为key设置不同的过期时间
>>“二级缓存”的解决方法
缓存预热/[系统上线后,将相关的缓存数据直接加载到缓存系统]
双层缓存策略/
定时更新缓存策略/
设置不同的过期时间,让缓存失效的时间点尽量均匀
缓存穿透
定义
>>缓存穿透是指用户查询数据,在数据库没有,自然在缓存中也不会有。这样就导致用户查询的时候,在缓存中找不到对应key的value,每次都要去数据库再查询一遍,然后返回空(相当于进行了两次无用的查询)
解决
>>缓存空值/
>>采用布隆过滤器BloomFilter/[占用内存空间很小,位存储;性能特别高,使用key的hash判断key存不存在]
[
布隆过滤器:
定义:
实现:
]
缓存击穿
定义
>>在平常高并发的系统中,大量的请求同时查询一个key时,此时这个key正好失效了,就会导致大量的请求都打到数据库上面去。这种现象我们称为缓存击穿
造成的问题会造成某一时刻数据库请求量过大,压力剧增
解决方案:
使用互斥锁(mutex key)
缓存更新
常见策略:
>>定时去清理过期的缓存
>>当有用户请求过来时,再判断这个请求所用到的缓存是否过期,过期的话就去底层系统得到新数据并更新缓存
getObjectSize()来获取类的大小
缓存预热
定义:
缓存预热就是系统上线后,将相关的缓存数据直接加载到缓存系统
缓存降级
用途:
降级的最终目的是保证核心服务可用
其他:
开启基于注解的缓存,使用 @EnableCaching 标识在 SpringBoot 的主启动类上。
@Cacheable
cacheNames/value :用来指定缓存组件的名字,将方法的返回结果放在哪个缓存中,可以是数组的方式,支持指定多个缓存
key :缓存数据时使用的 key,可以用它来指定。默认是使用方法参数的值。(这个 key 你可以使用 spEL 表达式来编写)
keyGenerator :key 的生成器。 key 和 keyGenerator 二选一使用
cacheManager :可以用来指定缓存管理器。从哪个缓存管理器里面获取缓存。
condition :可以用来指定符合条件的情况下才缓存
unless :否定缓存。当 unless 指定的条件为 true ,方法的返回值就不会被缓存。
sync :是否使用异步模式,