前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >高速缓存和主内存之间如何保持数据一致性

高速缓存和主内存之间如何保持数据一致性

作者头像
大忽悠爱学习
发布2023-03-06 08:47:19
4760
发布2023-03-06 08:47:19
举报
文章被收录于专栏:c++与qt学习

这里写自定义目录标题


转载

来自深入浅出计算机组成原理


引言

现在的CPU都是多核的CPU,每个CPU内核都有着自己的L1、L2级缓存,多个CPU内核共享L3级缓存和计算机的组主内存。CPU在加载数据的时候,首先会尽可能的从 Cache 中取加载,并不是一开始就从主内存中取加载数据。当 Cache 中没有数据的时候,才会从内存中去加载数据。

但是对于CPU处理的数据来说,肯定也会有数据的写入操作,Cache 的速度比内存快很多,那应该是直接写入 Cache 中还是内存中呢?如果直接写入内存中,Cache中的内存是否会失效?(与redis作为数据库缓存类似,当发送数据更新写入缓存还是直接写入库)。


单核CPU两种缓存更新策略

两种写入策略

写直达

写直达是最简单直接的一种策略,在写入之前先判断 Cache 中是否已经存在这个数据(通过地址映射关系判断这个地址的数据是否在 Cache 上),如果存在则直接更新 Cache 在写入到主内存中,如果不存在 Cache 就只更新主内存。

这个策略存在一个很明显的问题,就是不管缓存命中与否,都要写入到主内存中。

写回(Write-Back)

写回这个策略的想法是:既然CPU加载数据首先会从 Cache 中查找,那么是否可以直接将数据写入 Cache,而不把所有的数据同步到主内存呢?这样当缓存命中率高的时候可以减少很多I/O操作。

所以写回这个策略不再需要每次都同步数据到主内存中,而只是写到 Cache中,只有当 Cache 中的数据要被替换(应该是由于缓存淘汰策略)的时候才同步到主内存中。

过程是这样子的:当有要写入的数据的时候,直接更新 Cache 中的数据(如果存在),同时这个这个数据所在的块(cpu是按块加载数据)会被标记成脏的,就是这个块中的数据和主内存中的是不一致的。如果要写入的块存放着别的内存地址的数据(这个时候这个 Cache 中的数据要被淘汰),再查看这个块是否标记了脏块,如果标记了就先把这个 Cache 块的数据同步到主内存中,如果没有标记成脏块,就直接更新 Cache 块,再把这个块标记成脏块!

由于有了一个脏块标记,在从内存中加载数据写入到 Cache 中也需要多加一个同步操作,如果缓存到的 Cache 块是脏块的话,就需要先将块中的数据同步到主内存之后再进行缓存操作,让后把脏标记去掉。

写直达和写回都是针对单个CPU核心数为前提的,如果是多个CPU核心同时工作多线程的前提下,如果保证各个核心的高速缓存一致性呢?(数据还没有同步到主内存)

如果有这样一种传播机制,可以在cpu的一个核心更新完 Cache 之后,主动传播到其他的核心上。这样就可以解决同步的问题,但是仅仅是这个还是不够的,如果有四个cpu核心,内核1对缓存做了更改,内核2也对缓存做了更改,如果内核3和内核4接收到的更改顺序不一样,那也是不行的,所有也需要有一种串行化的机制。


多核CPU: 总线嗅探机制和 MESI 协议

总线嗅探

就是前面说的那种传播机制,本质上就是把所有的读写请求都通过总线(Bus)广播给所有的 CPU 核心,然后让各个核心去“嗅探”这些请求,再根据本地的情况进行响应。

MESI 协议

MESI表示对 Cache Line(CPU高速缓存块)的四种标记:

  • M:代表已修改(Modified)
  • E:代表独占(Exclusive)
  • S:代表共享(Shared)
  • I:代表已失效(Invalidated)

它是一种写失效的协议,在写失效协议里面,只有一个CPU核心是负责写入数据(关键,解决串行的问题),其他核心只是同步读取到这个写入,但是不做任何操作。在负责写入数据的核心操作完之后,发送一个"失效"请求到其他的CPU核心(那个块失效了),其他的核心只通过这个请求判断自己是否有这个失效的块,有的话就标记为失效。

MESI协议的核心是E和S,在共享(s)状态下,因为同样的数据在多个 CPU 核心的 Cache 里都有。所以,当我们想要更新 Cache 里面的数据的时候,不能直接修改,而是要先向所有的其他 CPU 核心广播一个请求,要求先把其他 cpu 核心里面的 Cache,都变成无效的状态,然后再更新当前 Cache 里面的数据。

在独占(e)状态下,对 Cache 块的更新操作就只能在这个核心下操作,其他的核心是没有操作权限的,相当于加了一把写锁,任何数据操作都只会在这个核心下进行。在独占状态下的数据,如果收到了一个来自于总线的读取对应缓存的请求,它就会变成共享状态。这个共享状态是因为,这个时候,另外一个 CPU 核心,也把对应的 Cache Block,从内存里面加载到了自己的 Cache 里来。


思考

CPU,高速缓存,内存。在数据同步方面就像我们在编程过程中使用redis作为mysql的缓存层,同样也是需要面临和计算机组成一样的问题。以及多核cpu换从同步和应用程序的缓存集群同步问题。不管做什么都是一个发现问题,解决问题,优化解决问题的过程。站在巨人的肩膀看世界固然不错,但是也同样希望能有所突破。

数据库缓存一致性问题


本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023-03-05,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 这里写自定义目录标题
  • 转载
  • 引言
    • 单核CPU两种缓存更新策略
      • 多核CPU: 总线嗅探机制和 MESI 协议
        • 思考
        相关产品与服务
        数据库
        云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档