mysql和redis双写一致性策略分析

news2024/9/21 4:23:22

mysql和redis双写一致性策略分析

一.什么是双写一致性
当我们更新了mysql中的数据后也可以同时保证redis中的数据同步更新;
数据读取的流程:
1.读取redis,如果value!=null,直接返回;
2.如果redis中value=null,读取mysql中数据对应的value,将key-value保存在redis中;
双写一致性策略:
策略1:先更新缓存,再更新数据库;
策略2:先更新数据库,再更新缓存;
策略3:先删除缓存,再更新数据库;
策略4:先更新数据库,再删除缓存;

二.四种策略存在的问题和优势
1.先更新缓存,再更新数据库
在这里插入图片描述

问题:这种策略如果redis更新成功,mysql更新失败,这时造成redis脏数据问题,这种策略是绝对不能使用的;

2.先更新数据库,再更新缓存
在这里插入图片描述
问题:这种策略的主要问题就是发生在并发场景下,当线程ThreadA更新mysql后由于某种原因并没有立刻更新redis缓存,这时线程ThreadB立即将数据库和缓存都更新成功,最后ThreadA将redis中的数据进行更新,这时就会造成ThreadB对缓存的更新丢失,这是一个很严重的问题;

3.先删除缓存,再更新数据库
在这里插入图片描述

问题:这种策略的主要问题也是发生在并发场景下,当ThreadA更新数据库之前先将redis中的数据进行删除,在更新数据库;但是在并发场景下回有一个问题,在ThreadA还没有更新完数据库时ThreadB读取了数据库将旧数据又重新写会redis中,这样同样造成数据库和缓存数据不一致问题;
解决办法:采用双删策略,在ThreadA准备写入数据库之前将缓存删除,当ThreadA数据库中数据更新完成后再进行一次缓存删除,这样就可以解决数据不一致问题,但是要注意第二次删除一定要保证时间上晚于数据库更新成功时间;值得注意的是延迟删除的时间间隔硬顶要大于操作的时间周期;

4.先更新数据库,再删除缓存
在这里插入图片描述
问题:这种策略的主要问题同样是发生在并发场景下,当ThreadA首先进行读数据库,准备将数据写入缓存,这时ThreadB更新数据库并且立刻执行了缓存删除,最后ThreadA才将旧数据同步到redis缓存中,同样会造成数据库和缓存数据不一致问题;
一般来说这种情况出现的概率很低,因为写操作时间大概率要比读操作时间长很多;
解决办法:解决上述问题的办法还是使用延迟双删策略,但要注意在ThreadB的第二次删除时间间隔一定要大于ThreadA的读取数据的时间周期;

三.扩展
1.采用延迟双删策略时如果删除失败了如何进行处理?
消息队列
2.如何使用Canal保证数据库与缓存数据的实时一致性?

四.关于单机redis中的16个数据库的分析
对于使用过redis的小伙伴们对一台redis服务器下有16个物理数据库并不陌生,它的命名格式是db0-db15,并且我们不能自定义的去更改这个命名;
在这里插入图片描述
1.关于16个物理数据库的使用介绍

Redis默认支持16个数据库,可以通过调整Redis的配置文件redis/redis.conf中的databases来修改这一个值,设置完毕后重启Redis便完成配置。
聊聊关于Redis中16个默认数据库的知识
Redis是一个字典结构的存储服务器,一个Redis实例提供了多个用来存储数据的字典,客户端可以指定将数据存储在哪个字典中。
Redis默认支持16个数据库,可以通过调整Redis的配置文件redis/redis.conf中的databases来修改这一个值,设置完毕后重启Redis便完成配置。
客户端与Redis建立连接后会默认选择0号数据库,不过可以随时使用SELECT命令更换数据库。
切库redis> SELECT 1 # 默认0号db,切换为1号dbOKredis [1] > GET username # 从1号库中获取 username (nil)
在实际项目中则可以通过以Redis配置文件的形式指定数据库,如下图所示
在这里插入图片描述
2、正确理解单机Redis的“数据库”概念

由于Redis不支持自定义数据库的名字,所以每个数据库都以编号命名。开发者则需要自己记录存储的数据与数据库的对应关系。另外Redis也不支持为每个数据库设置不同的访问密码,所以一个客户端要么可以访问全部数据库,要么全部数据库都没有权限访问。但是,要正确地理解Redis的“数据库”概念这里不得不提到一个命令:
清空一个Redis实例中所有数据库中的数据redis 127.0.0.1:6379> FLUSHALL
该命令可以清空实例下的所有数据库数据,这与我们所熟知的关系型数据库所不同。关系型数据库多个库常用于存储不同应用程序的数据 ,且没有方式可以同时清空实例下的所有库数据。所以对于Redis来说这些db更像是一种命名空间,且不适宜存储不同应用程序的数据。比如可以使用0号数据库存储某个应用生产环境中的数据,使用1号数据库存储测试环境中的数据,但不适宜使用0号数据库存储A应用的数据而使用1号数据库B应用的数据,不同的应用应该使用不同的Redis实例存储数据。Redis非常轻量级,一个空Redis实例占用的内在只有1M左右,所以不用担心多个Redis实例会额外占用很多内存。

3、在redis集群环境下不支持一个实例多个数据库的形式
在resis的集群环境下只支持db0,所以在redis的集群环境下不能使用select +number进行redis物理数据库的切换;
要注意以上所说的都是基于单体Redis的情况。而在集群的情况下不支持使用select命令来切换db,因为Redis集群模式下只有一个db0。再扩展一些集群与单机Reids的区别,感兴趣的朋友可以去查阅相关的资料深入理解,这里就不做讨论了。

key批量操作支持有限:例如mget、mset必须在一个slot

Key事务和Lua支持有限:操作的key必须在一个节点

key是数据分区的最小粒度:不支持bigkey分区

不支持多个数据库:集群模式下只有一个db0

复制只支持一层:不支持树形复制结构

五、总结

Redis实例默认建立了16个db,由于不支持自主进行数据库命名所以以dbX的方式命名。默认数据库数量可以修改配置文件的database值来设定。对于db正确的理解应为“命名空间”,多个应用程序不应使用同一个Redis不同库,而应一个应用程序对应一个Redis实例,不同的数据库可用于存储不同环境的数据。最后要注意,Redis集群下只有db0,不支持多db。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1481815.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

P2040 打开所有的灯

题目传送门:P2040 打开所有的灯 用深度优先搜索实现的一个填色题。 题目步骤: 1..dfs 首先dfs要判断是否符合题意,如果符合题意就更新最短路; 如果不符合题意就枚举 如果是关的就把周围四个包括 给标记上和原来相反的&#xf…

AI大预言模型——ChatGPT与AI绘图及论文高效写作

原文链接:AI大预言模型——ChatGPT与AI绘图及论文高效写作 2023年随着OpenAI开发者大会的召开,最重磅更新当属GPTs,多模态API,未来自定义专属的GPT。微软创始人比尔盖茨称ChatGPT的出现有着重大历史意义,不亚于互联网…

python语言1

一、pytho中的注释 1.1注释的理解 程序员在代码中对代码功能解释说明的标注性文字可以提高代码的可读性注释的内容将被python解释器忽略,不被计算机执行 1.2注释的分类 注释分为:单行注释、多行注释、中文声明注释 (1)单行注…

计算机网络-网络互连和互联网(五)

1.路由器技术NAT: 网络地址翻译,解决IP短缺,路由器内部和外部地址进行转换。静态地址转换:静态NAT(一对一) 静态NAT,内外一对一转换,用于web服务器,ftp服务器等固定IP的…

大模型的智慧之源:图技术的崛起

自2023年以来,大语言模型(Large Language Models,LLMs)的兴起已经改变了科技行业的面貌。 科创公司如果不涉足这一领域,似乎就不好意思称自己是科技企业。 然而,随着大语言模型的普及,它固有的…

Linux高级编程:进程(三),线程(一)

进程的一生: execute: exec族 用fork创建子进程后执行的是和父进程相同的程序(但有可能执行不同的代码分支), 子进程往往要调用一种exec函数以执行另一个程序。当进程调用一种exec函数时,该进程的 用户空间…

Python复合型数据避坑指南

目录 前言 列表(Lists) 1. 修改可变对象 2. 浅拷贝和深拷贝 元组(Tuples) 集合(Sets) 字典(Dictionaries) 1. 键值唯一性 2. 键的类型 实际应用场景 1. 数据分析与清洗 2. 网络…

微信小程序云开发教程——墨刀原型工具入门(安装以及基础使用教程)

引言 作为一个小白,小北要怎么在短时间内快速学会微信小程序原型设计? “时间紧,任务重”,这意味着学习时必须把握微信小程序原型设计中的重点、难点,而非面面俱到。 要在短时间内理解、掌握一个工具的使用&#xf…

Hgame题解(第二星期)

Hgame题解(第二星期) Web Select More Courses 打开靶机发现是一个登陆页面,根据题目提示下载弱密码字典,通过BP爆破获得用户密码为qwert123 登陆后进入下一个页面,由于学分已满无法选课,所以需要先进行…

仿牛客网项目---显示评论和添加评论功能的实现

这篇文章,我来介绍一下我的项目中的另外一个功能:显示评论和添加评论。 其实这两个功能都不怎么重要,我感觉最重要的应该是用户注册登录功能,这个也了解一下,知道这么一回事儿就好。 首先设计DAO层。 Mapper public …

【刷题】Leetcode 1609.奇偶树

Leetcode 1609.奇偶树 题目描述广度优先搜索(BFS)深度优先算法(DFS) 思路一(BFS)思路二(DFS)Thanks♪(・ω・)ノ谢谢阅读!!&a…

配置之道:深入研究Netty中的Option选项

欢迎来到我的博客,代码的世界里,每一行都是一个故事 配置之道:深入研究Netty中的Option选项 前言Option的基础概念ChannelOption与Bootstrap Option常见的ChannelOption类型ChannelConfig的使用Option的生命周期不同传输协议的Option 前言 在…

【MySQL】MySQL复合查询--多表查询自连接子查询 - 副本

文章目录 1.基本查询回顾2.多表查询3.自连接4.子查询 4.1单行子查询4.2多行子查询4.3多列子查询4.4在from子句中使用子查询4.5合并查询 4.5.1 union4.5.2 union all 1.基本查询回顾 表的内容如下: mysql> select * from emp; ----------------------------…

Java——建造者模式(Builder)

建造者模式(Builder) 1、建造者模式的定义 将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。 Builder模式是一步一步创建一个复杂对象的创建型模式,它允许使用者在不知道内部建造细节的情况下&…

vue3的router

需求 路由组件一般放在&#xff0c;pages或views文件夹, 一般组件通常放在component文件夹 路由的2中写法 子路由 其实就是在News组件里面&#xff0c;再定义一个router-view组件 他的子组件&#xff0c;机会渲染在router-view区域 路由传参 <RouterLink :to"/news…

Charles抓包 - 安装、激活、证书配置

最近刚好又遇到了抓包的需求&#xff0c;之前一直使用 Fiddler 抓包&#xff0c;这几年一直听大家都在用 Charles 抓包&#xff0c;正好一起了解下&#xff08;一般建议掌握一种抓包方式即可&#xff0c;都可以解决同种需求场景&#xff09; 抓包 Fiddler抓包 Charles 下载、安…

Day08:基础入门-算法分析传输加密数据格式密文存储代码混淆逆向保护

目录 传输数据-编码型&加密型等 传输格式-常规&JSON&XML等 密码存储-Web&系统&三方应用 代码混淆-源代码加密&逆向保护 思维导图 章节知识点&#xff1a; 应用架构&#xff1a;Web/APP/云应用/三方服务/负载均衡等 安全产品&#xff1a;CDN/WAF/I…

HotFix原理学习

原文链接&#xff1a;Unity 游戏用XLua的HotFix实现热更原理揭秘-CSDN博客 本文通过对XLua的HoxFix使用原理的研究揭示出来这样的一套方法。这个方法的 第一步&#xff1a;通过对C#的类与函数设置Hotfix标签。来标识需要支持热更的类和函数。第二步&#xff1a;生成函数连接器…

94. 递归实现排列型枚举 刷题笔记

思路 依次枚举 每个位置用哪个数字 要求按照字典序最小来输出 而每次搜索下一层时i都是从1开始 也就是说 如果有小的数可以填上 那么该方案会填上这个数字 例如 当n等于3 第一次搜索 1 2 3输出后返回 返回后此时i3 第二个位置填3 1 3 2 输出后返回 此时返回到第一层…

tkinterFrame框架+标签框架LabelFrame+Toplevel窗口的使用

1.在tkinter中&#xff0c;Frame是一个容器小部件用于组织和管理其他小部件。它可以作为一个独立的可见区域&#xff0c;也可以作为其他小部件的父容器。 import tkinter as tk import tkinter.ttk as ttk import tkinter.messagebox as mbm tk.Tk() m.title("tkinter L…