首页 > 数据库 >redis 数据库一致性策略

redis 数据库一致性策略

时间:2024-03-27 11:36:35浏览次数:23  
标签:缓存 策略 数据库 redis 更新 一致性 数据 请求

参考

常见的缓存更新策略共有3种:

  • Cache Aside(旁路缓存)策略;
  • Read/Write Through(读穿 / 写穿)策略;
  • Write Back(写回)策略;

Cache Aside(旁路缓存)策略

Cache Aside(旁路缓存)策略是最常用的,应用程序直接与「数据库、缓存」交互,并负责对缓存的维护,该策略又可以细分为「读策略」和「写策略」。
image

写策略的步骤:

先更新数据库中的数据,再删除缓存中的数据。

读策略的步骤:

如果读取的数据命中了缓存,则直接返回数据;
如果读取的数据没有命中缓存,则从数据库中读取数据,然后将数据写入到缓存,并且返回给用户。
注意,写策略的步骤的顺序不能倒过来,即不能先删除缓存再更新数据库,原因是在「读+写」并发的时候,会出现缓存和数据库的数据不一致性的问题。

举个例子,假设某个用户的年龄是 20,请求 A 要更新用户年龄为 21,所以它会删除缓存中的内容。这时,另一个请求 B 要读取这个用户的年龄,它查询缓存发现未命中后,会从数据库中读取到年龄为 20,并且写入到缓存中,然后请求 A 继续更改数据库,将用户的年龄更新为 21。

image

最终,该用户年龄在缓存中是 20(旧值),在数据库中是 21(新值),缓存和数据库的数据不一致。

为什么「先更新数据库再删除缓存」不会有数据不一致的问题?

继续用「读 + 写」请求的并发的场景来分析。

假如某个用户数据在缓存中不存在,请求 A 读取数据时从数据库中查询到年龄为 20,在未写入缓存中时另一个请求 B 更新数据。它更新数据库中的年龄为 21,并且清空缓存。这时请求 A 把从数据库中读到的年龄为 20 的数据写入到缓存中。

image

最终,该用户年龄在缓存中是 20(旧值),在数据库中是 21(新值),缓存和数据库数据不一致。 从上面的理论上分析,先更新数据库,再删除缓存也是会出现数据不一致性的问题,但是在实际中,这个问题出现的概率并不高。

因为缓存的写入通常要远远快于数据库的写入,所以在实际中很难出现请求 B 已经更新了数据库并且删除了缓存,请求 A 才更新完缓存的情况。而一旦请求 A 早于请求 B 删除缓存之前更新了缓存,那么接下来的请求就会因为缓存不命中而从数据库中重新读取数据,所以不会出现这种不一致的情况。

Cache Aside 策略适合读多写少的场景,不适合写多的场景,因为当写入比较频繁时,缓存中的数据会被频繁地清理,这样会对缓存的命中率有一些影响。如果业务对缓存命中率有严格的要求,那么可以考虑两种解决方案:

一种做法是在更新数据时也更新缓存,只是在更新缓存前先加一个分布式锁,因为这样在同一时间只允许一个线程更新缓存,就不会产生并发问题了。当然这么做对于写入的性能会有一些影响;
另一种做法同样也是在更新数据时更新缓存,只是给缓存加一个较短的过期时间,这样即使出现缓存不一致的情况,缓存的数据也会很快过期,对业务的影响也是可以接受。

实践

标签:缓存,策略,数据库,redis,更新,一致性,数据,请求
From: https://www.cnblogs.com/kelvinxiong/p/18098567

相关文章

  • 非关系型数据库和关系型数据库--一起学习吧之数据库
    非关系型数据库和关系型数据库是两种不同类型的数据库管理系统,它们在设计、数据存储、数据结构和应用场景等方面有着显著的区别。一、概念区别关系型数据库是建立在关系数据库模型基础上的数据库,通过外键关联来建立表与表之间的关系。它使用二维表的形式来存储数据,具有固定的......
  • GeoLite2 geoip数据库下载和使用
            GeoLite2数据库是免费的IP地理定位数据库,与MaxMind的GeoIP2数据库相当,但准确度较低。GeoLite2国家、城市和ASN数据库每周更新两次,即每周二和周五。GeoLite2数据还可作为GeoLite2Country和GeoLite2CityWeb服务中的Web服务提供。GeoLite2......
  • php:页面链接数据库(封装),其他页面引入方法
    数据库连接get_db_conn.php//创建连接$conn=mysqli_connect($servername,$username,$password,$dbname);<?php//数据库连接参数define('DB_SERVER','localhost');//数据库服务器的地址define('DB_USERNAME','root');//数据库账户define(......
  • MySQL数据库索引失效的常见情况
    MySQL数据库索引失效的常见情况01索引失效负面后果在MySQL数据库中,当索引失效时,可能会导致以下后果:全表扫描:如果索引失效,MySQL可能会选择执行全表扫描来检索数据,这将导致性能下降,特别是对于大型数据表而言。低效的查询计划:索引失效可能导致MySQL优化器选择不合适......
  • 如何在 Laravel 代码中正确地使用数据库事务
    如何在Laravel代码中正确地使用数据库事务22594英文原文 /  翻译 /  1852 /  4 / 创建于 2年前 /  1个改进 引言在web开发中,数据的完整性和准确性非常重要。因此,必须确保我们编写的代码能够以安全的方式存储、更新和删除数据库中的数据。在本文......
  • 面试题:在百万keys的Redis里面,如何模糊查找某个key.
    面试题:在百万keys的Redis里面,如何模糊查找某个key.在百万级别的Redis数据库中,进行模糊查找某个key时,需要注意查询效率和对Redis服务器性能的影响。以下是一些建议和方法:1.使用SCAN命令代替KEYS由于KEYS命令在大规模数据集上执行时会阻塞Redis服务器,并可能导致严重......
  • ctgu 2024春数据库3.1-3.4
    3.1任务13.1任务23.1任务33.2任务13.2任务23.2任务33.3任务13.3任务23.3任务33.4任务13.4任务23.4任务3爱门......
  • C#ASP.Net Core 5.0 使用StackExchange.Redis
    一、前言日常开发中,我们常需要操作redis,本章节介绍ASP.NetCore使用StackExchange.RedisDocs:https://stackexchange.github.io/StackExchange.Redis/二、介绍StackExchange.Redis是适用于.NET语言(C#等)的高性能通用Redis客户端。它是BookSleeve的逻辑继承者,是由StackEx......
  • Redis发布订阅模式解决Guava Cache本地缓存刷新问题
    为什么要用本地缓存可以加快资源访问速度,减少第三方IO延迟,也避免了网络调用的开销,将数据存储在本地jvm内存中可以减少外部系统的压力,可以将频繁访问、且更新场景较少的数据缓存起来,降低对远程服务或者数据库的请求次数,降低外部系统负载,提供系统整体的稳定性缺点:但是同时也得......
  • GBase8c 分布式数据库安装步骤
    GBase8c分布式数据库安装步骤GBase8c技术支持分布式安装数据库简介  GBase8c多模多态企业级分布式数据库具备高性能、高可用、弹性伸缩、高安全性等特性,可以部署在物理机、虚拟机、容器、私有云和公有云,为关键行业核心系统、互联网业务系统和政企业务系统提供安全、稳定、......