当前位置: 首页 > news >正文

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

目录

  • 一:背景介绍
  • 二: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 runoob1) "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官网并画思维导图。

五:升华

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

相关文章:

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

目录一&#xff1a;背景介绍二&#xff1a;redis1&#xff09;redis数据类型①String&#xff08;字符串&#xff09;②Hash&#xff08;哈希&#xff09;③List&#xff08;列表&#xff09;④Set&#xff08;集合&#xff09;2)缓存同步①设置有效期②同步双写③异步通知3&am…...

电话号码管理

电话号码管理 文章目录 电话号码管理综述链表结构initcreatedeleteallfreeANSI颜色转义颜色列表如下:字背景颜色范围:40--49 字颜色: 30--39输出特效格式控制:光标位置等的格式控制:Makefile顶层Makefilescripts Makefilesearch main init include display delete create all…...

Shell 教程

Shell 是一个用 C 语言编写的程序&#xff0c;它是用户使用 Linux 的桥梁。Shell 既是一种命令语言&#xff0c;又是一种程序设计语言。 Shell 是指一种应用程序&#xff0c;这个应用程序提供了一个界面&#xff0c;用户通过这个界面访问操作系统内核的服务。 Ken Thompson 的…...

Shader 阴影

阴影生成原理 以平行光为例&#xff0c;把相机移动到光源位置&#xff0c;计算阴影映射纹理&#xff08;shadowmap&#xff09;&#xff0c;这张shadowmap本质上是一张深度图&#xff0c;它记录了从该光源的位置出发、能看到的场景中距离它最近的表面位置&#xff08;深度信息&…...

【冲刺蓝桥杯的最后30天】day2

大家好&#x1f603;&#xff0c;我是想要慢慢变得优秀的向阳&#x1f31e;同学&#x1f468;‍&#x1f4bb;&#xff0c;断更了整整一年&#xff0c;又开始恢复CSDN更新&#xff0c;从今天开始更新备战蓝桥30天系列&#xff0c;一共30天&#xff0c;如果对你有帮助或者正在备…...

docker系列1:docker安装

传送门 docker官网地址&#xff1a; Docker: Accelerated, Containerized Application Development 安装地址&#xff1a;Install Docker Engine docker hub地址 docker hub&#xff1a;Docker 安装步骤 前置条件 由于安装docker&#xff0c;需要根据操作系统版本选择…...

内核角度谈谈Linux进程和线程

目录前言内核对进程和线程的表示创建进程的过程创建线程的过程创建进程和线程的异同揭秘 do_fork 系统调用结论前言 昨天面试的时候&#xff0c;面试官问我了个平平淡淡的问题–>“聊聊Linux中进程和线程”; 相比大家不管是在考试还是面试中或多或少都遇到过这个问题&…...

【mmdeploy部署系列】使用Tensorrt加速部署mmpose人体姿态库

【mmdeploy部署系列】使用Tensorrt加速部署mmpose人体姿态库0.引言1.安装mmcv2.使用mmpose&#xff08;1&#xff09;安装mmpose&#xff08;2&#xff09;运行mmpose3.使用mmdeploy&#xff08;1&#xff09;安装ppl.cv&#xff08;2&#xff09;编译安装mmdeploy&#xff08;…...

IDEA 每次新建工程都要重新配置 Maven 解决方案

IDEA 每次新建工程都要重新配置 Maven 解决方案 IDEA 每次新建工程都要重新配置 Maven&#xff0c;是一件相当浪费时间的事情。这是因为在创建一个项目后&#xff0c;在 File -> Settings -> Build,Execution,Deployment -> Build Tools -> Maven下配置了 Maven h…...

【C++修炼之路】25.哈希应用--布隆过滤器

每一个不曾起舞的日子都是对生命的辜负 布隆过滤器前言一.布隆过滤器提出二.布隆过滤器概念三. 布隆过滤器的操作3.1 布隆过滤器的插入3.2 布隆过滤器的查找3.3 布隆过滤器的删除四.布隆过滤器的代码4.1 HashFunc的仿函数参考4.2 BloomFilter.h五.布隆过滤器的优缺点六.布隆过滤…...

linux入门---权限

目录标题什么是权限人的分类为什么会有所属组查看文件属性文件的分类如何查看权限文件不同权限的表现rwx权限修改八进制权限修改umask有关内容文件中人的修改目录不同权限的表现rwx什么是权限 首先来看一个例子&#xff1a;比如说我没有爱奇艺的vip&#xff0c;那么我也就没有…...

Unity记录2.1-动作-多段跳、蹬墙跳、墙体滑落

文章首发及后续更新&#xff1a;https://mwhls.top/4450.html&#xff0c;无图/无目录/格式错误/更多相关请至首发页查看。 新的更新内容请到mwhls.top查看。 欢迎提出任何疑问及批评&#xff0c;非常感谢&#xff01; 汇总&#xff1a;Unity 记录 摘要&#xff1a;实现跳跃、蹬…...

Spring Boot结合IDEA自带Maven插件快速切换profile | Spring Cloud 10

一、前言 IDEA是目前 Java 开发者中使用最多的开发工具&#xff0c;它有着简约的设计风格&#xff0c;强大的集成工具&#xff0c;便利的快捷键。 在项目项目整个开发运维周期中&#xff0c;我们的的项目往往需要根据不同的环境&#xff0c;使用不同的文件配置。 比如以下部…...

ES 7.7.0 数据迁移

本文使用 elasticdump 做数据迁移&#xff0c;支持在线和离线俩种方式&#xff0c;适用于数据量比较小的情况。 1、Node 安装 由于elasticdump 依赖于 node&#xff0c;首先需要安装下node。 1.1、 Linux 安装 $ wget https://nodejs.org/dist/v10.15.0/node-v10.15.0-linu…...

【玩转c++】vector讲解和模拟底层实现

本期主题&#xff1a;vector的讲解和模拟实现博客主页&#xff1a;小峰同学分享小编的在Linux中学习到的知识和遇到的问题小编的能力有限&#xff0c;出现错误希望大家不吝赐vector的介绍及使用1.1vector的介绍vector其实就是一个数组的模板 &#xff0c;存放的数据可以改变而已…...

基本类型、包装类型、引用类型、String等作为实参传递后值会不会改变?

看了半天帖子&#xff0c;讲得乱七八糟&#xff0c;坑死了 [1] 先说结论 基本类型、包装类型、String类型作为参数传递之后&#xff0c;在方法里面修改他们的值&#xff0c;原值不会改变&#xff01;引用类型不一定&#xff0c;要看是怎么修改它的。 [2] 为什么基本类型、包装类…...

Tomcat服务器配置以及问题解决方案

文章目录01 Tomcat简介02 Tomcat的安装03 Tomcat的使用启动Tomcat服务器 &#xff08;解决一闪而过&#xff09;测试 Tomcat 是否启动Tomcat 服务器的关闭04 Tomcat的配置配置端口控制台配置&#xff08;乱码解决&#xff09;部署工程到Tomcat中01 Tomcat简介 Tomcat是一款开源…...

【Node.js】HTTP协议、HTTP的请求报文和响应报文

HTTP协议、HTTP的请求报文和响应报文HTTP协议HTTP主要特点HTTP的请求报文和响应报文请求报文请求行请求消息头空行请求体响应报文响应状态行响应消息头空行响应体总结HTTP协议 HTTP 全称为超文本传输协议&#xff0c;是用于从WWW服务器传输超文本到本地浏览器的传送协议&#…...

CodeForce 455A. Boredom

题目链接 CodeForce 455A. Boredom 思路 因为跟序列的下标无关&#xff0c;所以先对数组a排个序。那么每次选择只会影响两侧的元素。 记号 令dp[i]dp[i]dp[i]表示排序后a[1..i]a[1..i]a[1..i]能够获得的最大点数。 但是这样不足以区分是否当前元素可以被使用&#xff0c;所…...

geoserver之BlobStores使用

概述 geoserver是常用的地图服务器之一&#xff0c;除了基本的能力之外&#xff0c;也提供了很多的插件方便大家使用。在本文&#xff0c;讲述一下如何在geoserver中使用BlobStores和gwc-sqlite-plugin插件实现地图的切片和部署。 BlobStores简介 在geoserver中&#xff0c;…...

【Axure高保真原型】引导弹窗

今天和大家中分享引导弹窗的原型模板&#xff0c;载入页面后&#xff0c;会显示引导弹窗&#xff0c;适用于引导用户使用页面&#xff0c;点击完成后&#xff0c;会显示下一个引导弹窗&#xff0c;直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…...

应用升级/灾备测试时使用guarantee 闪回点迅速回退

1.场景 应用要升级,当升级失败时,数据库回退到升级前. 要测试系统,测试完成后,数据库要回退到测试前。 相对于RMAN恢复需要很长时间&#xff0c; 数据库闪回只需要几分钟。 2.技术实现 数据库设置 2个db_recovery参数 创建guarantee闪回点&#xff0c;不需要开启数据库闪回。…...

Qt/C++开发监控GB28181系统/取流协议/同时支持udp/tcp被动/tcp主动

一、前言说明 在2011版本的gb28181协议中&#xff0c;拉取视频流只要求udp方式&#xff0c;从2016开始要求新增支持tcp被动和tcp主动两种方式&#xff0c;udp理论上会丢包的&#xff0c;所以实际使用过程可能会出现画面花屏的情况&#xff0c;而tcp肯定不丢包&#xff0c;起码…...

练习(含atoi的模拟实现,自定义类型等练习)

一、结构体大小的计算及位段 &#xff08;结构体大小计算及位段 详解请看&#xff1a;自定义类型&#xff1a;结构体进阶-CSDN博客&#xff09; 1.在32位系统环境&#xff0c;编译选项为4字节对齐&#xff0c;那么sizeof(A)和sizeof(B)是多少&#xff1f; #pragma pack(4)st…...

Cesium1.95中高性能加载1500个点

一、基本方式&#xff1a; 图标使用.png比.svg性能要好 <template><div id"cesiumContainer"></div><div class"toolbar"><button id"resetButton">重新生成点</button><span id"countDisplay&qu…...

django filter 统计数量 按属性去重

在Django中&#xff0c;如果你想要根据某个属性对查询集进行去重并统计数量&#xff0c;你可以使用values()方法配合annotate()方法来实现。这里有两种常见的方法来完成这个需求&#xff1a; 方法1&#xff1a;使用annotate()和Count 假设你有一个模型Item&#xff0c;并且你想…...

OkHttp 中实现断点续传 demo

在 OkHttp 中实现断点续传主要通过以下步骤完成&#xff0c;核心是利用 HTTP 协议的 Range 请求头指定下载范围&#xff1a; 实现原理 Range 请求头&#xff1a;向服务器请求文件的特定字节范围&#xff08;如 Range: bytes1024-&#xff09; 本地文件记录&#xff1a;保存已…...

【android bluetooth 框架分析 04】【bt-framework 层详解 1】【BluetoothProperties介绍】

1. BluetoothProperties介绍 libsysprop/srcs/android/sysprop/BluetoothProperties.sysprop BluetoothProperties.sysprop 是 Android AOSP 中的一种 系统属性定义文件&#xff08;System Property Definition File&#xff09;&#xff0c;用于声明和管理 Bluetooth 模块相…...

第一篇:Agent2Agent (A2A) 协议——协作式人工智能的黎明

AI 领域的快速发展正在催生一个新时代&#xff0c;智能代理&#xff08;agents&#xff09;不再是孤立的个体&#xff0c;而是能够像一个数字团队一样协作。然而&#xff0c;当前 AI 生态系统的碎片化阻碍了这一愿景的实现&#xff0c;导致了“AI 巴别塔问题”——不同代理之间…...

从零实现STL哈希容器:unordered_map/unordered_set封装详解

本篇文章是对C学习的STL哈希容器自主实现部分的学习分享 希望也能为你带来些帮助~ 那咱们废话不多说&#xff0c;直接开始吧&#xff01; 一、源码结构分析 1. SGISTL30实现剖析 // hash_set核心结构 template <class Value, class HashFcn, ...> class hash_set {ty…...