Redis项目实战——商户查询缓存
目录
- 为什么要用Redis实现商户查询缓存?
- 用Redis实现商户查询缓存的基本思路?
- 使用Redis缓存的问题及解决方法?
- 一、如何保持数据库数据和Redis缓存数据的一致性?
- 1 内存淘汰机制
- 2 超时剔除机制
- 3 主动更新机制(胜)
- 如何实现主动更新机制?
- 操作缓存和数据库时应该更新缓存还是删除缓存?
- 如何保证缓存与数据库的操作的原子性?
- 先删除缓存还是先操作数据库?
- 二、缓存穿透?
- 解决方案1 缓存空对象
- 解决方案2 布隆过滤器
- 三、缓存雪崩?
- 解决方案1 随机TTL值
- 解决方案2 redis集群
- 解决方案3 服务熔断和降级
- 解决方案4 多级缓存
- 四、缓存击穿?热点key问题?
- 解决方案1 互斥锁
- 解决方案2 逻辑过期
为什么要用Redis实现商户查询缓存?
- 缓存是数据交换的缓冲区,是存储频繁用的数据的临时区,要求读写性能高,redis基于内存读写的高性能特点恰恰满足这一要求
- 用redis实现缓存可以降低后端负载,提高读写效率
- 增加缓存功能会增加成本,如数据一致性成本,代码维护成本,运维成本等,因此要根据业务场景选择合适的redis功能和机制
用Redis实现商户查询缓存的基本思路?
实战视频
- 如果没有缓存,客户端频繁发出请求查询一个数据时,每次请求都会直接到达数据库,数据库的压力会很大
- Redis缓存相当于在客户端和数据库之间增加了一个拦截,当客户端发出请求查询数据时,先到达Redis查询,如果命中直接返回查询结果,因此该请求就不会到达数据库,降低了数据库的压力
- 如果在Redis中请求没有命中,该请求才会继续去数据库,将数据库的查询结果返回客户端
- 若该客户端多次重复请求这个在Redis中不存在的数据,还是会多次请求数据库,这并不是我们希望的结果,因此数据库应该将查询结果返回客户端的同时,将查询结果也写入redis缓存中
使用Redis缓存的问题及解决方法?
一、如何保持数据库数据和Redis缓存数据的一致性?
- 数据一致性要求较低:数据变化频率较低,用内存淘汰机制就行
- 数据一致性要求较高:数据变化频率较高,用主动更新,并用超时剔除当兜底
1 内存淘汰机制
- redis为了解决内存不足的问题,自带的一种功能,会在内存不足时自动淘汰部分数据,下次查询该数据时更新缓存,在一定程度上可以保持数据的一致性
- 优点:维护成本几乎为0,全程有Redis自己管
- 缺点:不知道会淘汰掉哪些数据,什么时候淘汰,所以数据一致性比较差
2 超时剔除机制
- 给缓存数据添加TTL时间,到期后自动删除缓存,下次查询时更新缓存
- 优点:维护成本较低,只需要在原来数据的基础上增加一个过期时间
- 缺点:可以控制哪些数据什么时候淘汰,数据一致性比内存淘汰机制好一些,但也不强
3 主动更新机制(胜)
- 在修改数据库中数据的同时,更新缓存
- 优点:数据一致性比较好
- 缺点:维护成本高,需要自己编写大量的业务逻辑,比较难
如何实现主动更新机制?
- 实现的第一种方案:自己写代码,在更新数据库的同时更新缓存(实际业务中用的最多)。
- 实现的第二种方案:将缓存与数据库整合成一个服务,只需调用该服务,数据一致性由服务内部自己实现。但维护该服务比较难,也较难找到现成的服务可用
- 实现的第三种方案:调用者不管数据库,只在缓存中增删改查,缓存一直保持最新的数据。由一个专门的线程通过异步的方式将缓存的数据更新到数据库中,保证数据最终一致。异步机制可以大大提升效率,主要体现的场景为,假如缓存中的某个数据更新了n次,此时异步线程来检查缓存中的数据有没有变化,然后将最新的数据写入数据库,相当于数据库只更新了1次,而数据库的读写比缓存读写费劲多,所以节省了更新n-1次数据库浪费的时间。缺点是维护异步线程的成本、Redis宕机丢失数据、在异步线程更新数据库之前数据完全不一致。
操作缓存和数据库时应该更新缓存还是删除缓存?
- 更新缓存:每次更新数据库时都需要更新缓存,对于缓存来说无效的写操作比较多
- 删除缓存:更新数据库时删除缓存中的数据,更新n次也只删一次,只有客户端用到该数据时,访问redis缓存,redis中没有该数据,才会从数据库中取最新的数据写到缓存中。
如何保证缓存与数据库的操作的原子性?
- 意思就是更新数据库的时候必须保证删除缓存也成功执行,二者要么都成功,要么都失败
- 对于单体系统:将缓存与数据库操作放在一个事务中
- 对于分布式系统:利用TCC等分布式事务方案
先删除缓存还是先操作数据库?
- 在多线程情景下,二者的执行顺序不一样会造成不一样的后果
- 先删除缓存:假设线程1先删缓存后更新数据库,线程2在线程1刚删完缓存还没更新数据库时突然请求,此时缓存中的数据已经被删,线程2会去数据库中查询,但线程1还没更新数据库,因此线程2查到的是旧数据,还会把旧数据按照流程写入缓存,此时线程1再更新数据库,就会造成数据不一致
- 先更新数据库:假设线程1先更新数据库后删除缓存,线程2在线程1更新数据库之前请求,恰好缓存由于某些原因失效,线程2便查询数据库返回客户端一个旧数据,此时线程2正常更新数据库删除缓存,线程1再继续将刚才从数据库中读到的旧数据写入缓存,此时就会造成数据不一致
- 先更新数据库造成的数据不一致的可能性更低,且可以为缓存增加TTL,在一定程度上避免该问题的发生,因此应该先更新数据库后删除缓存
二、缓存穿透?
客户端请求的数据在缓存和数据库中都没有,无法建立缓存,如果多次请求这个不存在的数据,这些请求就会全部打到数据库,给数据库造成压力
解决方案1 缓存空对象
- 简单暴力,返回一个空值null,下次请求再来时会在缓存命中null,不会继续请求数据库
- 优点:实现简单,好维护
- 缺点1:如果有很多不同的请求的数据不存在,就会在缓存中存很多null,造成额外的内存消耗。解决方法:可以给null也增加一个TTL,避免长期占用缓存空间。
- 缺点2:在null过期之前的请求得到的数据都是null,如果此时数据库更新了数据,就会造成短期的不一致。解决方法:用主动更新机制,在更新数据库的同时替换掉null
解决方案2 布隆过滤器
- 在客户端和Redis之间增加布隆过滤器,当客户端发出一个请求时,首先由布隆过滤器判断该数据是否存在,若存在则放行,请求会继续执行正常流程,若不存在则拒绝,禁止请求频繁访问缓存和数据库
- 布隆过滤器是一个bit数组,每一位非0即1,可以快速判断一个元素是否存在
- 存数据:根据k个不同的hash函数将数据映射到bit数组的k个位置上,将k个位置置1
- 判断数据:根据k个不同的hash函数将数据映射到bit数组的k个位置上,若k个位置有0,则该数据肯定不存在,拦截,若k个位置全为1,则该数据可能存在(hash可能冲突,所以存在误判),允许通过
- 优点:速度快,占用空间小
- 缺点:实现复杂,存在误判
三、缓存雪崩?
大量redis缓存中的key同时失效或过期,或者redis服务器宕机,大量请求直接到达数据库,给数据库造成巨大压力
解决方案1 随机TTL值
如果给大量key设置一样的TTL,就会在同一时间大量key同时失效,因此可以给不同的key添加分布较均匀的随机TTL
解决方案2 redis集群
宕机一个redis还有其他redis
解决方案3 服务熔断和降级
- redis宕机时暂停redis缓存服务(熔断),预防出现雪崩
- 若redis直接爆炸,只能降级服务,不理睬请求,直接返回错误
解决方案4 多级缓存
在多个层面建立缓存(比如浏览器、数据库等),一级缓存和二级缓存失效时间不同,一级缓存失效用二级缓存
四、缓存击穿?热点key问题?
部分热点key(被高并发访问且缓存重建业务较复杂的key)在缓存中失效或过期,如果第一次请求未命中,会去数据库查询并写入缓存,但若在此期间有大量同样的请求涌入,就会有大量请求涌到数据库要求查询,给数据库造成巨大压力
解决方案1 互斥锁
- 当线程1查询缓存未命中时,尝试获取锁,获取成功才能去数据库查询,写缓存后释放锁。在此期间,其他同样的请求查询缓存未命中时,同样尝试获取锁,但获取失败,就会等待一段时间重新尝试查询缓存并获取锁
- 优点:没有额外的内存消耗,数据一致性更好,实现简单
- 缺点:其他线程需要一直等待,直到获取到锁的线程写入缓存或释放锁,还有死锁风险
解决方案2 逻辑过期
- 不再设置TTL,而是设置一个逻辑过期时间,TTL相当于倒计时,逻辑过期时间相当于一个具体的时间
- 当线程1查询缓存时,发现该缓存的逻辑时间已经过期,便尝试获取互斥锁,并开启一个新线程2来进行查询数据库重建缓存,无需等待线程2执行完,直接返回一个过期的数据
- 线程3若紧跟线程1之后也来查询该缓存,发现逻辑时间已过期,也尝试获取互斥锁,但此时锁被线程2占用,获取失败,则直接放弃,返回过期数据
- 只有在释放锁之后到来的线程4才能命中缓存中没有过期的数据
- 优点:线程无需等待,性能较好
- 缺点:数据一致性较差,有额外的内存消耗,实现复杂
相关文章:

Redis项目实战——商户查询缓存
目录 为什么要用Redis实现商户查询缓存?用Redis实现商户查询缓存的基本思路?使用Redis缓存的问题及解决方法?一、如何保持数据库数据和Redis缓存数据的一致性?1 内存淘汰机制2 超时剔除机制3 主动更新机制(胜ÿ…...

重磅OpenAI发布ChatGPT企业版本
8月29日凌晨,Open AI官网发布ChatGPT企业版本! 企业版简介: ChatGPT企业版提供企业级安全和隐私、无限的高速 GPT-4 访问、用于处理更长输入的更长上下文窗口、高级数据分析功能、自定义选项等等。人工智能可以协助和提升我们工作生活的各个…...
# Go学习-Day7
文章目录 断言文件打开/关闭文件读取文件写入文件 命令行参数解析Argsflag包 JSON 个人博客:CSDN博客 断言 type Node struct {x inty int }func main() {var a interface{}var n Node Node{1, 2}a nvar b Nodeb a.(Node)fmt.Println(b) }此处我们有一个结构体…...

uniapp-form表单
<template><view class"ptb-20 plr-30 bg min100"><view class"bg-white radius-20 pd-30"><view class"bold mt-30 mb-50 size-32">选择方式:</view><u--form labelPosition"left" :mod…...
漏洞挖掘-利用
一、文章简介 整合一些web漏洞,以及对漏洞的理解。 二、Web漏洞 1.SQL注入 (1)定义 开发者程序编写过程中,对传入用户数据过滤不严格,将可能存在的攻击载荷拼接到SQL查询语句当中,再将这些查询语句传递到…...
React钩子函数之useDeferredValue的基本使用
在React中,使用钩子函数可以方便地管理组件的状态和副作用。useDeferredValue是React 18中新引入的钩子函数之一,它可以帮助我们优化渲染性能,让组件更加流畅。 useDeferredValue的作用是将一个值延迟更新。这个值可以是状态、属性或其他变量…...
lodash常用方法
cloneDeep 克隆 import { cloneDeep,reduce } from lodash; const b {c:1} const a cloneDeep(b)debounce 防抖 import { debounce } from lodash; debounce(() > {}, 300, { trailing: true })()omit方法删除指定属性,返回一个新的对象 import …...
QByteArray与结构体之间相互转换
Qt项目会碰到自定义结构体和字符数组之间的转换问题,不妨假设结构体名字为custom_struct, 字符数组名字为array_data QByteArray转换为自定义结构体 custom_struct *struct_data reinterpret_cast<custom_struct *>(array_data.data());自定义结构体转换为…...
npm如何安装淘宝镜像
通过命令配置 这种方法是通过修改npm的全局配置文件,将默认的镜像源改为淘宝镜像。具体步骤如下: 打开终端,输入以下命令,设置淘宝镜像源:(windowr) npm config set registry https://registr…...

从项目中突显技能:在面试中讲述你的编程故事
🌷🍁 博主猫头虎 带您 Go to New World.✨🍁 🦄 博客首页——猫头虎的博客🎐 🐳《面试题大全专栏》 文章图文并茂🦕生动形象🦖简单易学!欢迎大家来踩踩~🌺 &a…...

python的观察者模式案例
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言二、具体代码写在结尾 前言 最近写安卓的代码比较多,了解了java代码的注册回调机制,也就是观察者模式,搜索了一下python也有…...

C语言——类型转换
数据有不同的类型,不同类型数据之间进行混合运算时涉及到类型的转换问题。 转换的方法有两种: 自动转换(隐式转换):遵循一定的规则,由编译系统自动完成强制类型转换:把表达式的运算结果强制转换成所需的数据类型 语法格…...

jmeter性能测试入门完整版
1. Jmeter简介 Apache JMeter是一款纯java编写负载功能测试和性能测试开源工具软件。相比Loadrunner而言,JMeter小巧轻便且免费,逐渐成为了主流的性能测试工具,是每个测试人员都必须要掌握的工具之一。 本文为JMeter性能测试完整入门篇&…...

报错sql_mode=only_full_group_by
首发博客地址 https://blog.zysicyj.top/ 报错内容 ### The error may exist in file[D:\code\cppCode20221025\leader-system\target\classes\mapper\system\TJsonDataMapper.xml] ### The error may involve defaultParameterMap ### The error occurred while…...
伪造 IP 地址的原理和防范措施
在数字化时代,网络安全是至关重要的话题。其中,伪造 IP 地址是一种可能导致网络攻击和欺诈的技术手段。这里将深入探讨伪造 IP 地址的原理以及如何采取措施来防范这种风险。 一.伪造 IP 地址的原理 伪造 IP 地址是一种操纵网络通信的方式,它…...

Linux通过libudev获取挂载路径、监控U盘热拔插事件、U盘文件系统类型
文章目录 获取挂载路径监控U盘热拔插事件libusb 文件系统类型通过挂载点获取挂载路径添libudev加库 获取挂载路径 #include <stdio.h> #include <libudev.h> #include <string.h>int main() {struct udev *udev;struct udev_enumerate *enumerate;struct ud…...

【会议征稿】2023智能通信与网络国际学术会议(ICN 2023)
2023智能通信与网络国际学术会议(ICN 2023) 2023 International Conference on Intelligent Communication and Networking (ICN2023) 2023智能通信与网络国际学术会议(ICN 2023)将于2023年11月10-12日在中国常州召开。ICN 2023…...

Android投屏总结
#android手机投屏 ####导语 至于手机投屏的实现方法可谓五花八门,今天小袁就说下以开发人员的角度来说下当今手机的主流投屏方法。目前这种将终端信号经由WiFi传输到电视、电视盒的技术有三种:DLNA、AirPlay、Miracast、Google Cast。 ##手机投屏智能电…...

vue2 组件组成部分,组件通信,进阶语法
一、学习目标 1.组件的三大组成部分(结构/样式/逻辑) scoped解决样式冲突/data是一个函数 2.组件通信 组件通信语法父传子子传父非父子通信(扩展) 4.进阶语法 v-model原理v-model应用于组件sync修饰符ref和$refs$nextTic…...

信看课堂笔记—LDO和DC-DC电路打PK
LDO(low dropout voltage regulator,低压差线性稳压器)和DC-DC(Direct current-Direct current converter,直流电压转直流电压转换器)电源是非常常见的电源电路,LDO 出来的比较早,像老戏骨一样,…...
conda相比python好处
Conda 作为 Python 的环境和包管理工具,相比原生 Python 生态(如 pip 虚拟环境)有许多独特优势,尤其在多项目管理、依赖处理和跨平台兼容性等方面表现更优。以下是 Conda 的核心好处: 一、一站式环境管理:…...

高频面试之3Zookeeper
高频面试之3Zookeeper 文章目录 高频面试之3Zookeeper3.1 常用命令3.2 选举机制3.3 Zookeeper符合法则中哪两个?3.4 Zookeeper脑裂3.5 Zookeeper用来干嘛了 3.1 常用命令 ls、get、create、delete、deleteall3.2 选举机制 半数机制(过半机制࿰…...
大语言模型如何处理长文本?常用文本分割技术详解
为什么需要文本分割? 引言:为什么需要文本分割?一、基础文本分割方法1. 按段落分割(Paragraph Splitting)2. 按句子分割(Sentence Splitting)二、高级文本分割策略3. 重叠分割(Sliding Window)4. 递归分割(Recursive Splitting)三、生产级工具推荐5. 使用LangChain的…...

【项目实战】通过多模态+LangGraph实现PPT生成助手
PPT自动生成系统 基于LangGraph的PPT自动生成系统,可以将Markdown文档自动转换为PPT演示文稿。 功能特点 Markdown解析:自动解析Markdown文档结构PPT模板分析:分析PPT模板的布局和风格智能布局决策:匹配内容与合适的PPT布局自动…...

srs linux
下载编译运行 git clone https:///ossrs/srs.git ./configure --h265on make 编译完成后即可启动SRS # 启动 ./objs/srs -c conf/srs.conf # 查看日志 tail -n 30 -f ./objs/srs.log 开放端口 默认RTMP接收推流端口是1935,SRS管理页面端口是8080,可…...

新能源汽车智慧充电桩管理方案:新能源充电桩散热问题及消防安全监管方案
随着新能源汽车的快速普及,充电桩作为核心配套设施,其安全性与可靠性备受关注。然而,在高温、高负荷运行环境下,充电桩的散热问题与消防安全隐患日益凸显,成为制约行业发展的关键瓶颈。 如何通过智慧化管理手段优化散…...

04-初识css
一、css样式引入 1.1.内部样式 <div style"width: 100px;"></div>1.2.外部样式 1.2.1.外部样式1 <style>.aa {width: 100px;} </style> <div class"aa"></div>1.2.2.外部样式2 <!-- rel内表面引入的是style样…...

vue3+vite项目中使用.env文件环境变量方法
vue3vite项目中使用.env文件环境变量方法 .env文件作用命名规则常用的配置项示例使用方法注意事项在vite.config.js文件中读取环境变量方法 .env文件作用 .env 文件用于定义环境变量,这些变量可以在项目中通过 import.meta.env 进行访问。Vite 会自动加载这些环境变…...

Unsafe Fileupload篇补充-木马的详细教程与木马分享(中国蚁剑方式)
在之前的皮卡丘靶场第九期Unsafe Fileupload篇中我们学习了木马的原理并且学了一个简单的木马文件 本期内容是为了更好的为大家解释木马(服务器方面的)的原理,连接,以及各种木马及连接工具的分享 文件木马:https://w…...

Netty从入门到进阶(二)
二、Netty入门 1. 概述 1.1 Netty是什么 Netty is an asynchronous event-driven network application framework for rapid development of maintainable high performance protocol servers & clients. Netty是一个异步的、基于事件驱动的网络应用框架,用于…...