首页 > 数据库 >【教学典型案例】01.redis只管存不管删除让失效时间删除的问题

【教学典型案例】01.redis只管存不管删除让失效时间删除的问题

时间:2023-03-11 19:31:31浏览次数:39  
标签:缓存 删除 0.1 redis 127.0 6379 01 key


目录

  • ​​一:背景介绍​​
  • ​​二:redis​​
  • ​​1)redis数据类型​​
  • ​​①String(字符串)​​
  • ​​②Hash(哈希)​​
  • ​​③List(列表)​​
  • ​​④Set(集合)​​
  • ​​2)缓存同步​​
  • ​​①设置有效期​​
  • ​​②同步双写​​
  • ​​③异步通知​​
  • ​​3)key的过期时间​​
  • ​​具体设置方式​​
  • ​​三:问题分析过程​​
  • ​​四:总结​​
  • ​​五:升华​​

一:背景介绍

此案例是通过Reids查询该课程下所有的班级信息,如果从reids中没有查询到数据,那么就会从数据库中查询并把查询到的数据存入到redis中。

存在的问题:没有再更新课程下的班级数据时删除缓存,这样会导致如果更新了该课程下的班级数据,那么缓存中的数据和数据中的数据出现不一致的情况。

二:redis

1)redis数据类型

redis支持五种数据类型:string(字符串)、hash(哈希)、list(列表)、set(集合)

①String(字符串)

string是redis最基本的类型,可以理解成与Memcached一模一样的类型,一个key对应一个value。redis的string可以包含任何数据,比如jpg图片或者序列化的对象。

redis 127.0.0.1:6379> SET runoob "Hello"
OK
redis 127.0.0.1:6379> GET runoob
"Hello"

以上实例我们使用了Redis的SET和GET命令,键为runoob,对应的值为"Hello"

②Hash(哈希)

Redis hash是一个键值(key=>value)对集合,是一个string类型的field和value的映射表,用于存储对象
DEL runoob用于删除前面测试用过的key,不然会报错:(error) WRONGTYPE Operation against a key holding the wrong kind of value

redis 127.0.0.1:6379> DEL runoob
redis 127.0.0.1:6379> HMSET runoob field1 "Hello" field2 "World"
"OK"
redis 127.0.0.1:6379> HGET runoob field1
"Hello"
redis 127.0.0.1:6379> HGET runoob field2
"World"

以上实例我们使用了Redis HMSET,HGET命令,HMSET设置了两个field=>value对,HGET获取对应field对应的value。

③List(列表)

Redis列表是简单的字符串列表,按照插入顺序排序

redis 127.0.0.1:6379> DEL runoob
redis 127.0.0.1:6379> lpush runoob redis
(integer) 1
redis 127.0.0.1:6379> lpush runoob mongodb
(integer) 2
redis 127.0.0.1:6379> lpush runoob rabbitmq
(integer) 3
redis 127.0.0.1:6379> lrange runoob 0 10
1) "rabbitmq"
2) "mongodb"
3) "redis"
redis 127.0.0.1:6379>

④Set(集合)

Redis的Set是string类型的无序集合,集合是通过哈希表实现的
sadd命令
添加一个string元素到key对应的set集合中,成功返回1,如果元素已经在集合中返回0.

sadd key member
redis 127.0.0.1:6379> DEL runoob
redis 127.0.0.1:6379> sadd runoob redis
(integer) 1
redis 127.0.0.1:6379> sadd runoob mongodb
(integer) 1
redis 127.0.0.1:6379> sadd runoob rabbitmq
(integer) 1
redis 127.0.0.1:6379> sadd runoob rabbitmq
(integer) 0
redis 127.0.0.1:6379> smembers runoob

1) "redis"
2) "rabbitmq"
3) "mongodb"

以上实例中rebbitmq添加了两次,但根据集合内元素的唯一性,第二次插入的元素将被忽略

2)缓存同步

①设置有效期

给缓存设置有效期,到期后自动删除。再次查询时更新。
优点: 简单,方便
缺点: 时效性差,缓存过期之前可能不一致
场景: 更新频率较低,时效性要求低的业务

②同步双写

在修改数据库的同时,直接修改缓存
优点: 时效性强,缓存与数据库强一致
缺点: 有代码侵入,耦合度高
场景: 对一致性,时效性要求较高的缓存数据

③异步通知

修改数据库时发送事件通知,相关服务监听到通知后修改缓存数据
优点: 低耦合,可以同时通知多个缓存服务
缺点: 时效性一般,可能存在中间不一致状态
场景: 时效性一般,有多个服务需要同步

3)key的过期时间

Redis过期时间设置命令有两种:
PEXPIRE:以毫秒为单位设置key的生存时间
EXPIPE:以秒为单位设置key的生存时间

具体设置方式

  • EXPIRE key seconds //将key的生存时间设置为ttl秒
  • PEXPIRE key milliseconds //将key的生成时间设置为ttl毫秒
  • EXPIREAT key timestamp //将key的过期时间设置为timestamp所代表的的秒数的时间戳
  • PEXPIREAT key milliseconds-timestamp //将key的过期时间设置为timestamp所代表的的毫秒数的时间戳

三:问题分析过程

Redis如果只是将数据存入缓存以提高效率并设置缓存时间,带来的问题是如果数据发生变化之后就得等key失效之后查询数据才会得到正确的数据。

public List<TbContent> getContentListByCid(long cid) {
//查询缓存
try {
//如果缓存中有直接响应结果
String json = jedisClient.hget(CONTENT_LIST, cid + "");
if (StringUtils.isNotBlank(json)) {
//json转列表,TbContent.class是list中每个元素的类型
List<TbContent> list = JsonUtils.jsonToList(json, TbContent.class);
return list;
}
} catch (Exception e) {
e.printStackTrace();
}
//如果缓存没有就查询数据库
TbContentExample example = new TbContentExample();
Criteria criteria = example.createCriteria();
//设置查询条件
criteria.andCategoryIdEqualTo(cid);
//执行查询
List<TbContent> list = contentMapper.selectByExampleWithBLOBs(example);

//把结果添加到缓存
try {
jedisClient.hset(CONTENT_LIST, cid + "", JsonUtils.objectToJson(list));
jedisClient.expire(CONTENT_LIST, 3600);
} catch (Exception e) {
e.printStackTrace();
}
return list;
}

应该采取的做法是在对数据进行添加、修改和删除操作时删除数据,查询数据时发现缓存中已删除就从数据库中查询得到最新的数据,将最新的数据重新插入到缓存保证缓存中数据的准确性。

public E3Result addContent(TbContent content) {

content.setCreated(new Date());
content.setUpdated(new Date());
contentMapper.insert(content);
//缓存同步
jedisClient.hdel(CONTENT_LIST, content.getCategoryId().toString());
return E3Result.ok();
}

四:总结

1、如果开发人员要开发已有的代码,需要和写此代码的开发人员进行沟通,避免出现问题。
2、对于redis如何在项目中应用,要及时查阅,做总结。建议至少看三遍redis官网并画思维导图。

五:升华

不怕不知道,就怕不知道。


标签:缓存,删除,0.1,redis,127.0,6379,01,key
From: https://blog.51cto.com/u_15903651/6114802

相关文章

  • [POI2001][HAOI2007] 反素数 题解
    前置知识:一些关于约数的小常识。唯一分解定理对于所有正整数\(n\),一定有唯一分解方式\(n=p_1^{c_1}p_2^{c_2}\cdotsp_m^{c_m}\),其中\(p_1<p_2<\cdots<p_m\),......
  • redis数据类型-set类型
    不存在重复元素的集合常用场景去重用户画像标签常用命令SADDkeymember...为set增加元素SCARDkey返回set中元素的数量SDIFFkey1key2返回两个set的差......
  • P3530[POI2012 FES-Festival] 题解
    题面链接简要题意对于数列\(\{v_n\}\),有两种约束\(v_i=v_j+1\)和\(v_i\gev_j\),问\(\{v_n\}\)最多有多少个不同的项。解法考虑先建图,注意到如果约束图是DAG,那么......
  • 小技巧001-后台运行Linux程序
    小技巧001-后台运行Linux程序 以运行icoFoam为例,当我们运行一个算例程序时,终端的输入输出渠道被占用,无法运行其他程序,使用VNCsever可以解决这一问题,但是需要新建termnia......
  • 04-面试必会-Redis篇
    01-你们项目中哪里用到了Redis?在我们的项目中很多地方都用到了Redis,Redis在我们的项目中主要有三个作用:使用Redis做热点数据缓存/接口数据缓存使用Redis存储一......
  • 01-面试必会-JAVA基础篇
    1.Final有什么用?被final修饰的类不可以被继承被final修饰的方法不可以被重写被final修饰的变量不可以被改变,被final修饰不可变的是变量的引用,而不是引用指向的内容,......
  • SpringMVC-day01
    SpringMVC-day01SpringMVC,底层是把Servlet、Filter、Listener再次封装课程内容SpringMVC介绍请求与响应RESTful风格请求交互SSM整合(注解版)拦截器学习目标掌握......
  • Spring-day01
    Spring-day01#前置课程1.javase 1).面向对象:封装,继承,多态(面向接口) 2).反射 3).动态代理2.javaweb 1).servlet编程规范 2).网络编程3.数据库 1).......
  • Redis常用命令
    5种类型操作string类型命令作用stringsetkeyval设置键值对setkeyvalnxextimeout设置键值对,nx代表不存在则设置,ex表示过期时间设置delk......
  • android camera拍照/录像后查看图片/视频并删除所有内容后自动回到camera预览界面
    在JB2版本上,在camera中拍照/录像,后点击右下角缩略图/向左滑动来查看图片/视频,当点击“删除”menu来删除所有的image/video后,camerapreview只显示在屏幕左边约四分之一的地......