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

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 主动更新机制(胜&#xff…...

重磅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">选择方式&#xff1a;</view><u--form labelPosition"left" :mod…...

漏洞挖掘-利用

一、文章简介 整合一些web漏洞&#xff0c;以及对漏洞的理解。 二、Web漏洞 1.SQL注入 &#xff08;1&#xff09;定义 开发者程序编写过程中&#xff0c;对传入用户数据过滤不严格&#xff0c;将可能存在的攻击载荷拼接到SQL查询语句当中&#xff0c;再将这些查询语句传递到…...

React钩子函数之useDeferredValue的基本使用

在React中&#xff0c;使用钩子函数可以方便地管理组件的状态和副作用。useDeferredValue是React 18中新引入的钩子函数之一&#xff0c;它可以帮助我们优化渲染性能&#xff0c;让组件更加流畅。 useDeferredValue的作用是将一个值延迟更新。这个值可以是状态、属性或其他变量…...

lodash常用方法

cloneDeep 克隆 import { cloneDeep&#xff0c;reduce } from lodash; const b {c:1} const a cloneDeep(b)debounce 防抖 import { debounce } from lodash; debounce(() > {}, 300, { trailing: true })()omit方法删除指定属性&#xff0c;返回一个新的对象 import …...

QByteArray与结构体之间相互转换

Qt项目会碰到自定义结构体和字符数组之间的转换问题&#xff0c;不妨假设结构体名字为custom_struct, 字符数组名字为array_data QByteArray转换为自定义结构体 custom_struct *struct_data reinterpret_cast<custom_struct *>(array_data.data());自定义结构体转换为…...

npm如何安装淘宝镜像

通过命令配置 这种方法是通过修改npm的全局配置文件&#xff0c;将默认的镜像源改为淘宝镜像。具体步骤如下&#xff1a; 打开终端&#xff0c;输入以下命令&#xff0c;设置淘宝镜像源&#xff1a;&#xff08;windowr&#xff09; npm config set registry https://registr…...

从项目中突显技能:在面试中讲述你的编程故事

&#x1f337;&#x1f341; 博主猫头虎 带您 Go to New World.✨&#x1f341; &#x1f984; 博客首页——猫头虎的博客&#x1f390; &#x1f433;《面试题大全专栏》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33a; &a…...

python的观察者模式案例

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

C语言——类型转换

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

jmeter性能测试入门完整版

1. Jmeter简介 Apache JMeter是一款纯java编写负载功能测试和性能测试开源工具软件。相比Loadrunner而言&#xff0c;JMeter小巧轻便且免费&#xff0c;逐渐成为了主流的性能测试工具&#xff0c;是每个测试人员都必须要掌握的工具之一。 本文为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 地址的原理和防范措施

在数字化时代&#xff0c;网络安全是至关重要的话题。其中&#xff0c;伪造 IP 地址是一种可能导致网络攻击和欺诈的技术手段。这里将深入探讨伪造 IP 地址的原理以及如何采取措施来防范这种风险。 一.伪造 IP 地址的原理 伪造 IP 地址是一种操纵网络通信的方式&#xff0c;它…...

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智能通信与网络国际学术会议&#xff08;ICN 2023&#xff09; 2023 International Conference on Intelligent Communication and Networking (ICN2023) 2023智能通信与网络国际学术会议&#xff08;ICN 2023&#xff09;将于2023年11月10-12日在中国常州召开。ICN 2023…...

Android投屏总结

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

vue2 组件组成部分,组件通信,进阶语法

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

信看课堂笔记—LDO和DC-DC电路打PK

LDO&#xff08;low dropout voltage regulator&#xff0c;低压差线性稳压器&#xff09;和DC-DC(Direct current-Direct current converter&#xff0c;直流电压转直流电压转换器)电源是非常常见的电源电路&#xff0c;LDO 出来的比较早&#xff0c;像老戏骨一样&#xff0c;…...

springboot 百货中心供应链管理系统小程序

一、前言 随着我国经济迅速发展&#xff0c;人们对手机的需求越来越大&#xff0c;各种手机软件也都在被广泛应用&#xff0c;但是对于手机进行数据信息管理&#xff0c;对于手机的各种软件也是备受用户的喜爱&#xff0c;百货中心供应链管理系统被用户普遍使用&#xff0c;为方…...

相机Camera日志实例分析之二:相机Camx【专业模式开启直方图拍照】单帧流程日志详解

【关注我&#xff0c;后续持续新增专题博文&#xff0c;谢谢&#xff01;&#xff01;&#xff01;】 上一篇我们讲了&#xff1a; 这一篇我们开始讲&#xff1a; 目录 一、场景操作步骤 二、日志基础关键字分级如下 三、场景日志如下&#xff1a; 一、场景操作步骤 操作步…...

Mac软件卸载指南,简单易懂!

刚和Adobe分手&#xff0c;它却总在Library里给你写"回忆录"&#xff1f;卸载的Final Cut Pro像电子幽灵般阴魂不散&#xff1f;总是会有残留文件&#xff0c;别慌&#xff01;这份Mac软件卸载指南&#xff0c;将用最硬核的方式教你"数字分手术"&#xff0…...

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样…...

智能仓储的未来:自动化、AI与数据分析如何重塑物流中心

当仓库学会“思考”&#xff0c;物流的终极形态正在诞生 想象这样的场景&#xff1a; 凌晨3点&#xff0c;某物流中心灯火通明却空无一人。AGV机器人集群根据实时订单动态规划路径&#xff1b;AI视觉系统在0.1秒内扫描包裹信息&#xff1b;数字孪生平台正模拟次日峰值流量压力…...

算法岗面试经验分享-大模型篇

文章目录 A 基础语言模型A.1 TransformerA.2 Bert B 大语言模型结构B.1 GPTB.2 LLamaB.3 ChatGLMB.4 Qwen C 大语言模型微调C.1 Fine-tuningC.2 Adapter-tuningC.3 Prefix-tuningC.4 P-tuningC.5 LoRA A 基础语言模型 A.1 Transformer &#xff08;1&#xff09;资源 论文&a…...

毫米波雷达基础理论(3D+4D)

3D、4D毫米波雷达基础知识及厂商选型 PreView : https://mp.weixin.qq.com/s/bQkju4r6med7I3TBGJI_bQ 1. FMCW毫米波雷达基础知识 主要参考博文&#xff1a; 一文入门汽车毫米波雷达基本原理 &#xff1a;https://mp.weixin.qq.com/s/_EN7A5lKcz2Eh8dLnjE19w 毫米波雷达基础…...

论文阅读笔记——Muffin: Testing Deep Learning Libraries via Neural Architecture Fuzzing

Muffin 论文 现有方法 CRADLE 和 LEMON&#xff0c;依赖模型推理阶段输出进行差分测试&#xff0c;但在训练阶段是不可行的&#xff0c;因为训练阶段直到最后才有固定输出&#xff0c;中间过程是不断变化的。API 库覆盖低&#xff0c;因为各个 API 都是在各种具体场景下使用。…...

Spring AOP代理对象生成原理

代理对象生成的关键类是【AnnotationAwareAspectJAutoProxyCreator】&#xff0c;这个类继承了【BeanPostProcessor】是一个后置处理器 在bean对象生命周期中初始化时执行【org.springframework.beans.factory.config.BeanPostProcessor#postProcessAfterInitialization】方法时…...

【笔记】AI Agent 项目 SUNA 部署 之 Docker 构建记录

#工作记录 构建过程记录 Microsoft Windows [Version 10.0.27871.1000] (c) Microsoft Corporation. All rights reserved.(suna-py3.12) F:\PythonProjects\suna>python setup.py --admin███████╗██╗ ██╗███╗ ██╗ █████╗ ██╔════╝…...