应用场景
优点和缺点
原理
应用场景
1.我们在碰到需要执行耗时特别久,且结果不频繁变动的SQL,就特别适合将运行结果放入缓存。这样,后面的请求就去缓存中读取,使得请求能够迅速响应。
@Override
public TbItem getItemById(long itemId) {
//获取商品添加缓存,不影业务响逻辑,try-catch
try {
System.out.println("缓存获取商品信息");
String json = jedisClient.get(REDIS_ITEM_PRE+":"+itemId+":BASE");
if(StringUtils.isNotBlank(json)) {
TbItem tbItem = JsonUtils.jsonToPojo(json,TbItem.class);
return tbItem;
}
}catch(Exception e) {
e.printStackTrace();
}
//缓存中没有,查询数据库
//根据主键查询
//TbItem tbItem = itemMapper.selectByPrimaryKey(itemId);
TbItemExample example = new TbItemExample();
Criteria criteria = example.createCriteria();
//设置查询条件
criteria.andIdEqualTo(itemId);
//执行查询
List<TbItem> list = itemMapper.selectByExample(example);
if (list != null && list.size() > 0) {
//结果添加到缓存
try {
System.out.println("缓存添加商品信息");
jedisClient.set(REDIS_ITEM_PRE+":"+itemId+":BASE",JsonUtils.objectToJson(list.get(0)));
//设置过期时间(1个小时)
jedisClient.expire(REDIS_ITEM_PRE+":"+itemId+":BASE",TIEM_CACHE_EXPIRE);
}catch(Exception e) {
e.printStackTrace();
}
return list.get(0);
}
return null;
}
记录用户上次的登录状态
分布式锁
比如集群下的定时任务就需要分布式锁,先判断key是否存在,如果存在直接return
原理
持久化
1.持久化的目的:防止内存中的数据丢失,写入硬盘(数据库)备份用
2.持久化的方式:
半持久化模式:即Snapshot(RDB)快照模式:也是默认方式,不定期的通过异步方式保存某一时刻的数据在磁盘;
全持久化模式:即append-only file(AOF):以日志的形式来记录每个写操作,将redis执行过的所有写指令记录下来(读操作不记录)
只允许追加文件但不可以改写文件,redis启动之初会读取该文件重新构建数据。
换言之,redis重启的话,就根据日志文件的内容将写指令从前到后执行一次以完成数据的恢复工作。
注意: 持久化的目的是备份,而不是数据交互,实际交互还是从内存取数据的,所以持久化不需要关心是不是和硬盘交互导致效率变慢;
俩种持久化的优缺点
RDB的优点:
1.在持久化过程中,redis会开启一个子进程进行io读写,父进程不需要io,所以最大提升了redis的性能
2.在文件恢复过程中,rdb要比aof速度要快
RDB的缺点:
1.由于是定时进行持久化,所以在如果刚在内存set一个值,还没有来得及进行持久化,重启的时候也就不会有这个set的值
AOF的优点:
1.和rbd的缺点相反,aof记录的是命令,所以可以保证重启后数据的一致性(无论是set还是del)
AOF的缺点:
1.在文件恢复过程中,rdb要比aof速度要快
总结:rdb备份的是数据,aof备份的是命令,所以rdb的效率高,aof的数据一致性好
清除策略(rdb适用)
当内存中的key到期消失的时候,为了确保硬盘和内存中的数据统一
redis有三种清除策略
1,定时删除:实现方式,创建定时器
2,惰性删除:每次获取键时,检查是否过期
3,定期删除:redis数据库默认每隔100ms就会进行随机抽取一些设置过期时间的key进行检测,过期则删除。
优缺点:
1,定时删除,对内存友好,但是对cpu很不友好
2,惰性删除,对cpu友好,对内存很不友好
3,定期删除,是两种折中,但是,如果删除太频繁,将退化为定时删除,如果删除次数太少,将退化为惰性删除。
Redis采用的是惰性删除+定期删除的方案。
Redis的内存淘汰策略
redis的会对过期的key进行清除,但是如果插入的速度大于清除的速度的话,服务器的内存迟早会满的,这个时候,就需要一种淘汰策略来对内存中的key再进行处理,Redis会根据用户配置的淘汰策略清除无用的key释放来内存空间,redis提供了以下八种中内存淘汰的策略:
volatile-lru: 从设置过期时间的数据集中挑选出最近最少使用的数据淘汰。没有设置过期时间的key不会被淘汰,这样就可以在增加内存空间的同时保证需要持久化的数据不会丢失。
allkeys-lru:从数据集中挑选最近最少使用的数据淘汰,该策略要淘汰的key面向的是全体key集合,而非过期的key集合。
volatile-random:从已设置过期时间的数据集中随机选择数据淘汰
allkeys-random:从全体的key集合中任意选择数据淘汰
volatile-ttl:除了淘汰机制采用LRU,策略基本上与volatile-lru相似,从设置过期时间的数据集中挑选将要过期的数据淘汰,ttl值越大越优先被淘汰。
noeviction:禁止驱逐数据,也就是当内存不足以容纳新入数据时,新写入操作就会报错,请求可以继续进行,线上任务也不能持续进行,采用no-enviction策略可以保证数据不被丢失,这也是系统默认的一种淘汰策略。
volatile-lfu:从所有配置了过期时间的键中驱逐使用频率最少的键
allkeys-lfu:从所有键中驱逐使用频率最少的键。
在开发中,对于那些重要的,绝对不能丢弃的数据(如配置类数据等),应不设置有效期,这样Redis就永远不会淘汰这些数据;对于那些相对不是那么重要的,并且能够回源的数据,可以设置有效期,这样在内存不够时Redis就会淘汰这部分数据。
redis是单线程(串行化访问)
(一)纯内存操作,速度快
(二)单线程操作,避免了频繁的上下文切换
(三)采用了非阻塞I/O多路复用机制
三个缓存问题 雪崩 刺穿