深入理解缓存之缓存和数据库的一致性

深入理解MyBatis的一级缓存和二级缓存机制 在现代Java企业级应用开发中,MyBatis作为一款优秀的持久层框架,因其灵活性和高性能而广受欢迎。缓存作为提升数据库访问性能的关键技术,在MyBatis中有着精妙的实现。本文将全面剖析MyBatis的一级缓存和二级缓存机制,从基础概念到高级应用,帮助开发者深入理解并合理运用MyBatis缓存来优化应用性能。 阅读详情

GitHub:https://github.com/JDawnF

产生原因

主要有两种情况,会导致缓存和 DB 的一致性问题:

  1. 并发的场景下,导致读取老的 DB 数据,更新到缓存中。

  2. 缓存和 DB 的操作,不在一个事务中,可能只有一个操作成功,而另一个操作失败,导致不一致。

当然,有一点我们要注意,缓存和 DB 的一致性,我们指的更多的是最终一致性。我们使用缓存只要是提高读操作的性能,真正在写操作的业务逻辑,还是以数据库为准。例如说,我们可能缓存用户钱包的余额在缓存中,在前端查询钱包余额时,读取缓存,在使用钱包余额时,读取数据库。

更新缓存的设计模式

1.Cache Aside Pattern(旁路缓存)

这是最常用最常用的pattern了。其具体逻辑如下:

  • 失效:应用程序先从cache取数据,没有得到,则从数据库中取数据,成功后,放到缓存中。

  • 命中:应用程序从cache中取数据,取到后返回。

  • 更新:先把数据存到数据库中,成功后,再让缓存失效。

一个是查询操作,一个是更新操作的并发,首先,没有了删除cache数据的操作了,而是先更新了数据库中的数据,此时,缓存依然有效,所以,并发的查询操作拿的是没有更新的数据,但是,更新操作马上让缓存的失效了,后续的查询操作再把数据从数据库中拉出来。而不会像文章开头的那个逻辑产生的问题,后续的查询操作一直都在取老的数据。

要么通过2PC或是Paxos协议保证一致性,要么就是拼命的降低并发时脏数据的概率,而Facebook使用了这个降低概率的玩法,因为2PC太慢,而Paxos太复杂。当然,最好还是为缓存设置上过期时间。

2.Read/Write Through Pattern

在上面的Cache Aside套路中,我们的应用代码需要维护两个数据存储,一个是缓存(Cache),一个是数据库(Repository)。所以,应用程序比较啰嗦。而Read/Write Through套路是把更新数据库(Repository)的操作由缓存自己代理了,所以,对于应用层来说,就简单很多了。可以理解为,应用认为后端就是一个单一的存储,而存储自己维护自己的Cache。

Read Through

Read Through 套路就是在查询操作中更新缓存,也就是说,当缓存失效的时候(过期或LRU换出),Cache Aside是由调用方负责把数据加载入缓存,而Read Through则用缓存服务自己来加载,从而对应用方是透明的。

Write Through

Write Through 套路和Read Through相仿,不过是在更新数据时发生。当有数据更新的时候,如果没有命中缓存,直接更新数据库,然后返回。如果命中了缓存,则更新缓存,然后再由Cache自己更新数据库(这是一个同步操作)

下图自来Wikipedia的Cache词条。其中的Memory你可以理解为就是我们例子里的数据库。

3.Write Behind Caching Pattern

Write Behind 又叫 Write Back。write back就是Linux文件系统的Page Cache的算法。

Write Back套路,一句说就是,在更新数据的时候,只更新缓存,不更新数据库,而我们的缓存会异步地批量更新数据库。

这个设计的好处就是让数据的I/O操作飞快无比(因为直接操作内存嘛 ),因为异步,write backg还可以合并对同一个数据的多次操作,所以性能的提高是相当可观的。

但是,其带来的问题是,数据不是强一致性的,而且可能会丢失(我们知道Unix/Linux非正常关机会导致数据丢失,就是因为这个事)。在软件设计上,我们基本上不可能做出一个没有缺陷的设计,就像算法设计中的时间换空间,空间换时间一个道理,有时候,强一致性和高性能,高可用和高性性是有冲突的。软件设计从来都是取舍Trade-Off。

另外,Write Back实现逻辑比较复杂,因为他需要track有哪数据是被更新了的,需要刷到持久层上。操作系统的write back会在仅当这个cache需要失效的时候,才会被真正持久起来,比如,内存不够了,或是进程退出了等情况,这又叫lazy write。

在wikipedia上有一张write back的流程图,基本逻辑如下:

参照:左耳朵耗子《缓存更新的套路》

缓存架构设计:

1.更新缓存 VS 淘汰缓存

更新缓存:数据不但写入数据库,还会写入缓存;优点:缓存不会增加一次miss,命中率高

淘汰缓存:数据只会写入数据库,不会写入缓存,只会把数据淘汰掉;优点:简单

这两者的选择主要取决于“更新缓存的复杂度”。

例如,上述场景,只是简单的把余额money设置成一个值,那么:

(1)淘汰缓存的操作为deleteCache(uid)

(2)更新缓存的操作为setCache(uid, money)

更新缓存的代价很小,此时我们应该更倾向于更新缓存,以保证更高的缓存命中率

如果余额是通过很复杂的数据计算得出来的,例如业务上除了账户表account,还有商品表product,折扣表discount

account(uid, money)

product(pid, type, price, pinfo)

discount(type, zhekou)

业务场景是用户买了一个商品product,这个商品的价格是price,这个商品从属于type类商品,type类商品在做促销活动要打折扣zhekou,购买了商品过后,这个余额的计算就复杂了,需要:

(1)先把商品的品类,价格取出来:SELECT type, price FROM product WHERE pid=XXX

(2)再把这个品类的折扣取出来:SELECT zhekou FROM discount WHERE type=XXX

(3)再把原有余额从缓存中查询出来money = getCache(uid)

(4)再把新的余额写入到缓存中去setCache(uid, money-price*zhekou)

更新缓存的代价很大,此时我们应该更倾向于淘汰缓存。

总之,淘汰缓存操作简单,并且带来的副作用只是增加了一次cache miss,建议作为通用的处理方式。

2.先操作数据库 vs 先操作缓存

当写操作发生时,假设淘汰缓存作为对缓存通用的处理方式,又面临两种抉择:

(1)先写数据库,再淘汰缓存

(2)先淘汰缓存,再写数据库

对于一个不能保证事务性的操作,一定涉及“哪个任务先做,哪个任务后做”的问题,解决这个问题的方向是:如果出现不一致,谁先做对业务的影响较小,就谁先执行。

由于写数据库与淘汰缓存不能保证原子性,谁先谁后同样要遵循上述原则。

假设先写数据库,再淘汰缓存:第一步写数据库操作成功,第二步淘汰缓存失败,则会出现DB中是新数据,Cache中是旧数据,数据不一致。

假设先淘汰缓存,再写数据库:第一步淘汰缓存成功,第二步写数据库失败,则只会引发一次Cache miss。

结论:数据和缓存的操作时序:先淘汰缓存,再写数据库。

3.缓存架构优化

上述缓存架构有一个缺点:业务方需要同时关注缓存与DB,主要有两种优化方案:

一种方案是服务化:加入一个服务层,向上游提供帅气的数据访问接口,向上游屏蔽底层数据存储的细节,这样业务线不需要关注数据是来自于cache还是DB。

另一种方案是异步缓存更新:业务线所有的写操作都走数据库,所有的读操作都总缓存,由一个异步的工具来做数据库与缓存之间数据的同步,具体细节是:

(1)要有一个init cache的过程,将需要缓存的数据全量写入cache

(2)如果DB有写操作,异步更新程序读取binlog,更新cache

在(1)和(2)的合作下,cache中有全部的数据,这样:

(a)业务线读cache,一定能够hit(很短的时间内,可能有脏数据),无需关注数据库

(b)业务线写DB,cache中能得到异步更新,无需关注缓存

这样将大大简化业务线的调用逻辑,存在的缺点是,如果缓存的数据业务逻辑比较复杂,async-update异步更新的逻辑可能也会比较复杂。

4.结论:

(1)淘汰缓存是一种通用的缓存处理方式

(2)先淘汰缓存,再写数据库

(3)服务化是向业务方屏蔽底层数据库与缓存复杂性的一种通用方式

参照:沈剑《缓存架构设计细节二三事》

缓存和DB一致性的解决方案

1)先淘汰缓存,再写数据库

因为先淘汰缓存,所以数据的最终一致性是可以得到有效的保证的。因为先淘汰缓存,即使写数据库发生异常,也就是下次缓存读取时,多读取一次数据库。

但是,这种方案会存在缓存和 DB 的数据会不一致的情况,参照《缓存与数据库一致性优化》 所说。

我们需要解决缓存并行写,实现串行写。比较简单的方式,引入分布式锁。

  • 在写请求时,先淘汰缓存之前,获取该分布式锁。

  • 在读请求时,发现缓存不存在时,先获取分布式锁。

这样,缓存的并行写就成功的变成串行写落。写请求时,是否主动更新缓存,根据自己业务的需要,是否有,都没问题。

2)先写数据库,再更新缓存

按照“先写数据库,再更新缓存”,我们要保证 DB 和缓存的操作,能够在“同一个事务”中,从而实现最终一致性。

基于定时任务来实现

  • 首先,写入数据库。

  • 然后,在写入数据库所在的事务中,插入一条记录到任务表。该记录会存储需要更新的缓存 KEY 和 VALUE 。

  • 【异步】最后,定时任务每秒扫描任务表,更新到缓存中,之后删除该记录。

基于消息队列来实现

  • 首先,写入数据库。

  • 然后,发送带有缓存 KEY 和 VALUE 的事务消息。此时,需要有支持事务消息特性的消息队列,或者我们自己封装消息队列,支持事务消息。

  • 【异步】最后,消费者消费该消息,更新到缓存中。

这两种方式,可以进一步优化,可以先尝试更新缓存,如果失败,则插入任务表,或者事务消息。

另外,极端情况下,如果并发写执行时,先更新成功 DB 的,结果后更新缓存:

 

  • 理论来说,希望的更新缓存顺序是,线程 1 快于线程 2 ,但是实际线程1 晚于线程 2 ,导致数据不一致。

  • 图中一直是基于定时任务或消息队列来实现异步更新缓存,如果网络抖动,导致【插入任务表,或者事务消息】的顺序不一致。

  • 那么怎么解决呢?需要做如下三件事情:

    • 1、在缓存值中,拼接上数据版本号或者时间戳。例如说:value = {value: 原值, version: xxx} 。

    • 2、在任务表的记录,或者事务消息中,增加上数据版本号或者时间戳的字段。

    • 3、在定时任务或消息队列执行更新缓存时,先读取缓存,对比版本号或时间戳,大于才进行更新。 当然,此处也会有并发问题,所以还是得引入分布式锁或 CAS 操作。

3) 基于数据库的 binlog 日志

1、重客户端

写入缓存:

  • 应用同时更新数据库和缓存

  • 如果数据库更新成功,则开始更新缓存,否则如果数据库更新失败,则整个更新过程失败。

  • 判断更新缓存是否成功,如果成功则返回

  • 如果缓存没有更新成功,则将数据发到MQ中

  • 应用监控MQ通道,收到消息后继续更新Redis。

问题点:如果更新Redis失败,同时在将数据发到MQ之前的时间,应用重启了,这时候MQ就没有需要更新的数据,如果Redis对所有数据没有设置过期时间,同时在读多写少的场景下,只能通过人工介入来更新缓存。

读缓存:

如何来解决这个问题?那么在写入Redis数据的时候,在数据中增加一个时间戳插入到Redis中。在从Redis中读取数据的时候,首先要判断一下当前时间有没有过期,如果没有则从缓存中读取,如果过期了则从数据库中读取最新数据覆盖当前Redis数据并更新时间戳。具体过程如下图所示:

2、客户端数据库与缓存解耦

上述方案对于应用的研发人员来讲比较重,需要研发人员同时考虑数据库和Redis是否成功来做不同方案,如何让研发人员只关注数据库层面,而不用关心缓存层呢?请看下图:

  • 应用直接写数据到数据库中。

  • 数据库更新binlog日志。

  • 利用Canal中间件读取binlog日志。

  • Canal借助于限流组件按频率将数据发到MQ中。

  • 应用监控MQ通道,将MQ的数据更新到Redis缓存中。

可以看到这种方案对研发人员来说比较轻量,不用关心缓存层面,而且这个方案虽然比较重,但是却容易形成统一的解决方案。

参照: 《技术专题讨论第五期:论系统架构设计中缓存的重要性》

PS:下面这两种比较实用

  • “先淘汰缓存,再写数据库”的方案,并且无需引入分布式锁。

  • “先写数据库,再更新缓存”的方案,并且无需引入定时任务或者消息队列。

使用缓存过程中,经常会遇到缓存数据的不一致性和脏读现象。一般情况下,采取缓存双淘汰机制,在更新数据库的前淘汰缓存。此外,设定超时时间,例如三十分钟。

极端场景下,即使有脏数据进入缓存,这个脏数据也最存在一段时间后自动销毁。

另外,在 DB 主从架构下,方案会更加复杂。详细可以看看 《主从 DB 与 cache 一致性优化》 。

 

 

 

 

 

 

 

 

 

 

【Redis】深入理解缓存——从概念到实战,解决缓存穿透、雪崩与击穿问题 本文全面介绍了缓存的概念、作用及使用方法。首先解释了缓存即数据交换的缓冲区,通过示例展示了不同类型的缓存实现,如 Java 中的本地缓存。阐述了使用缓存的原因在于其速度快能降低服务器读写压力,但也会增加代码复杂度和运营成本。接着详细介绍了多级缓存的构成,包括浏览器缓存、应用层缓存、数据库缓存和 CPU 缓存等。 阅读详情

相关推荐

深入理解分布式技术 - 先更新数据库,还是先更新缓存

文章目录Pre数据不一致更新缓存的方式先更新数据库,再更新缓存先删缓存,再更新数据库先更新数据库,再删缓存 Pre 深入理解分布式技术 - 探究缓存穿透、缓存击穿、缓存雪崩解决方案 缓存穿透、缓存击穿和缓存雪崩,这几个问题聚焦的是缓存本身的稳定性,包括缓存集群和缓存的数据,除了这些,缓存应用中,缓存和上下游系统的数据同步也很重要。 本文我们来学习缓存应用中的另一个高频问题:应用缓存以后,缓存和数据库何时同步。 数据不一致 众所周知, 除了少部分配置信息类缓存,比如业务中的黑白名单信息、页面展示配置等

小工匠 2万+

一文搞懂缓存和数据库的一致性问题(全面总结)

缓存是我们经常用到的,而如何解决缓存和数据库的一致性也是一个挺让人头疼的问题。

lans_g的博客 8930

安卓db数据库查看工具——快速管理与分析SQLite数据库

SQLite 是 Android 内置的轻量级关系型数据库管理系统,为 Android 应用提供了一种高效、便捷的数据持久化方案。与传统的关系型数据库不同,SQLite 将数据库存储在文件系统中的单一文件内,从而简化了数据库的部署和管理。SQLite 支持标准的 SQL 语言,允许在没有服务器进程的情况下进行数据库操作,这使得它非常适合于资源有限的移动设备环境。在 Android 应用开发中,SQLite 数据库常用于本地数据存储、用户个性化设置记录以及应用内缓存。

weixin_32869687的博客 1940

数据库与缓存的一致性

数据库与缓存的一致性

@BXuan 968

深入理解小型数据库db-4.6.21的编程实践

Berkeley DB是一款开源的嵌入式数据库管理系统,提供灵活的数据存储解决方案。db-4.6.21作为其版本中的一个代表,包含了数据库核心功能,以及一系列对数据操作的优化。字典数据库,通常被称为键值存储数据库,是数据存储模型中最简单的一种,它与传统的基于表的关系数据库有所不同。字典数据库中的数据以键值对的形式存储。在这里,每个键都是唯一的,用来标识数据项,而值则是实际存储的数据。

weixin_30978239的博客 1233

《童虎学习笔记》5分钟用Keepalived搭建MySQL高可用实现虚ip自动漂移

1

tonghu_note的博客 5617

8种方案,保证缓存和数据库的最终一致性

​我们通常使用缓存机制来提升系统的性能,缓存系统下的读写操作,一般都需要操作数据库与缓存。 对于读操作,一般是先查询缓存,查询不到再查询数据库,最后回写进缓存。 而对于写操作,究竟是先删除(更新)缓存,再更新数据库,还是先更新数据库,再删除(更新)缓存呢? 由于对数据库以及缓存的整体操作,并不是原子性的,再加上读写并发,究竟什么样的方案可以保证数据库与缓存的一致性呢? 下面介绍8种方案,配合读写时序图,希望你能从其中了解到保证一致性的设计要点。

阳阳的博客 1万+

cartographer错误终结者 ordered_multi_queue.cc:155 Queue waiting for data

错误描述 错误提示的感应器数据可能是: Queue waiting for data:(0, points2) Queue waiting for data:(0, odom) 说明在提供给cartographter的传感器数据出现了问题,没有被成功解析。 原因分析 小编是使用自己编写的odom话题发布时,cartographer爆出了该错误。 于是设想传感器数据相关的tf或lua配置或数据本身存在错误。 于是逐个排查,最终发现了错误原因。 排查可能原因:tf错误 小编之前已处理过tf与lua配置的问题 参

人工智能机器人 4156

如何保证缓存与数据库的数据一致性

推荐这种,更新完数据库后删除缓存的速度是非常快的,所以在这个间隔内插入其他事务概率会比较低。缓存更新成功后,数据库更新失败,则会造成数据不一致性,而且也有并发问题,不推荐。更新数据库成功了,但是在删除缓存的阶段没有成功,则之后读取的缓存都是错误的。并发更新数据库场景下,会将脏数据刷新到缓存,不推荐。改进方法:先删缓存,再更新数据库,再删缓存。先更新数据库,再更新缓存(有bug)先更新缓存,再更新数据库(有bug)先删除缓存,在更新数据库(有bug)先更新数据库,再删除缓存(有bug)

qq_21238011的博客 838

数据产品需求文档(PRD)怎么写?阿里P8分享的模板+5个避坑点

作用:记录文档的版本、作者、评审信息,避免“文档混乱”。填写规范字段说明示例文档名称清晰反映产品名称,如“用户行为分析平台PRD”用户行为分析平台PRD_V1.0文档版本用“版本号+日期”,如V1.0_20240301编写人数据产品经理姓名+联系方式张三(138-XXXX-XXXX)评审人员业务负责人、开发经理、数据分析师、运维负责人李四(业务)、王五(开发)、赵六(数据)、周七(运维)评审时间评审日期2024-03-05评审意见。

架构师的AI之路,分享AI应用开发架构的学习与实践。 1570

华为OD 面试手撕代码真题【岛屿的周长】

0代表水,1代表陆地,岛由陆地组成且岛内不允许有湖,让你求岛的周长。

MISAYAONE的博客 8412

老司机带你玩转面试(6):Redis 分布式锁、并发竞争、双写一致

前文回顾 建议前面文章没看过的同学先看下前面的文章: 「老司机带你玩转面试(1):缓存中间件 Redis 基础知识以及数据持久化」 「老司机带你玩转面试(2):Redis 过期策略以及缓存雪崩、击穿、穿透」 「老司机带你玩转面试(3):Redis 高可用之主从模式」 「老司机带你玩转面试(4):Redis 高可用之哨兵模式」 「老司机带你玩转面试(5):Redis 集群模式 Redis Cluster」 并发竞争 这个问题产生的根源是并发写,本身 Redis 是不会产生并发问题的,看过前面文章的同学应该知.

极客挖掘机 629

Multica 自托管部署与使用入门:从上线到让 AI Agent 真正干活

Multica是一个将AI Agent作为团队成员的任务协作平台,支持自托管部署。本文介绍了完整的单机部署流程: 核心架构包括前端界面、后端服务、PostgreSQL数据库和Runtime执行机器 推荐使用Docker Compose部署,需配置数据持久化目录 提供详细的docker-compose.yml和.env配置文件说明 重点注意事项:数据库密码和JWT密钥必须修改,生产环境配置必须设为production 需正确配置前端访问地址和WebSocket连接 部署完成后,用户可创建AI Agent并将其

q742971636的博客 1693

MySQL 与 Redis 缓存的同步方案

点击上方“Java基基”,选择“设为星标”做积极的人,而不是积极废人!每天14:00更新文章,每天掉亿点点头发...源码精品专栏原创 | Java 2021超神之路,很肝~中文详细注释的开源项目RPC 框架 Dubbo 源码解析网络应用框架 Netty 源码解析消息中间件 RocketMQ 源码解析数据库中间件 Sharding-JDBC 和 MyCAT 源码解析作业调度中间件 Elast...

weixin_44421461的博客 1185

6-2 GPU GART 绑定机制与 TLB 失效

本文详细解析了AMD GPU的GART(Graphics Address Remapping Table)绑定机制实现。主要内容包括: 绑定流程:从ttm_tt_bind()到硬件PTE更新的完整调用链,重点分析amdgpu_gart_bind()函数实现。 关键函数: amdgpu_gart_bind():执行安全检查、记录映射关系、更新页表等操作 amdgpu_gart_map():将CPU页映射为多个GPU页并填充PTE amdgpu_gmc_set_pte_pde():处理硬件特定的PTE格式 内存

图形/计算GPU的驱动与虚拟化技术分享园地 2644

【嵌入式DIY实例-ESP32篇】-热成像仪

在本文中,我们将使用 MLX90640 热像仪和 1.8 英寸 ST7735 TFT 显示屏,构建一款基于 ESP32 的高性能紧凑型热像仪。本项目旨在打造一款便携、响应迅速的热像仪,具有增强的图像质量、优化的帧率和精准的温度读数。

视觉与物联智能 877

深入理解Oracle DB的锁和闩

本文深入介绍Oracle DB的锁和闩。

qq_45732829的博客 2017

【社招算法经验贴】算法社招记录

总的来说,也是收获了七七八八的offer,给的涨幅40~100%,职级有的可以对标到 p7(但阿里p7是真难a,a不动)。面了一圈下来,感觉大模型也在收缩hc。尤其是多模态相关hc。凭着上学期间做过相关视觉的work和paper,社招虽然能进面试,但是hc少得可怜,多模态已死慎入。还有大模型应用算法给的涨幅,跟搜广推的涨幅差别不大。真正能几百万往上的是基座pretrain/后训练/infra,但是全靠social和conn,hc极少。

Danger的博客 976

Redis - CAP原则 => 缓存与数据库的一致性

这里的数据库是指Mysql等存放在磁盘的数据库,缓存是指Redis等在内存的数据库 实时同步 实时同步:缓存或DB修改,另一方同步修改 强一致性要求比较高,可采用实时同步:查询时先查询缓存,查询不到再查询数据库,并保持到缓存;更新缓存时先更新数据库,再将缓存设置为过期,更新数据(建议不要更新缓存内容,而是设置缓存过期) 非实时同步 非实时同步:缓存或数据库修改,另一方不需要同步修改 非实时同步: 定时任务:设置一定时间间隔更新数据 异步队列: 并发程度高,可以采用异步队列,可此案有kafka等消息中.

key_768的博客 2162

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

深入理解缓存穿透、缓存击穿和缓存雪崩

本文详细探讨了缓存系统中的三大常见问题:缓存穿透、缓存击穿和缓存雪崩。缓存穿透是由于缓存和数据库中都不存在的数据被频繁请求,解决方案包括布隆过滤器和缓存空结果。缓存击穿是热点数据在缓存过期瞬间被大量请求,解决方案包括互斥锁和提前更新缓存。缓存雪崩是大量缓存同时失效导致数据库压力骤增,解决方案包括分散缓存过期时间、双缓存策略和限流降级。通过合理应用这些技术手段,可以有效提升系统的稳定性和性能。

欢迎来到【技术拾光者】,在这里,我们专注分享编程教程、技术趋势、实战案例和优质资源。不定期举办技术问答、专家访谈和职业指导。加入我们,共同探索技术世界,提升技能,拓展职业道路! 1749

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

【转】深入理解缓存穿透、缓存击穿和缓存雪崩

缓存穿透、缓存击穿和缓存雪崩是缓存系统中常见的三种问题,它们各自具有不同的特点、影响以及解决方案。以下是对这三种问题的深入理解以及相应的案例分析。

1821

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

图文深入理解Oracle DB实例管理

本来这篇打算承接上篇,接着介绍Oracle数据库表的管理的,但考虑到需要实操,在这之前先深入介绍下Oracle DB实例的基本管理,包括一些常用的管理工具和数据库启动过程的各个阶段和几种带选项的关闭方式的会有什么影响。学习知识就得循序渐进,每个知识点揉碎了再彻底消化。

qq_45732829的博客 2154

缓存和数据库的一致性学习

深入理解缓存之缓存和数据库的一致性 https://blog.youkuaiyun.com/striveb/article/details/95110502

zmm0420的专栏 105

CodeIgniter 数据库查询缓存(Database Caching Class)完全指南:原理、配置与实战

> 本文基于 CodeIgniter 3.x 官方文档《Database Caching Class》编写,结合本仓库 [system/database/DB_cache.php](https://link.gitcode.com/i/df67dac330608edbdca56f5ff122521d) 与 [system/database/DB_driver.php](https://link.g

gitblog_00466的博客 380
上一篇: 深入理解缓存之缓存存在的问题及应对措施
下一篇: 深入理解缓存之缓存预热与淘汰策略
striveb
博客等级 码龄10年 242粉丝 117原创
评论 18
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值