首页 > 其他分享 >缓存一致性

缓存一致性

时间:2023-05-14 22:22:31浏览次数:33  
标签:缓存 cache 总线 主存 Invalid 处理器 一致性

通信模式

共享存储

统一的地址空间,每一个处理器都可以访问。但是需要注意并发控制。

使用线程。

消息传递

使用单独的地址

 

共享存储系统

因为性能原因,使用多个私有缓存

当一个chip读取一个值时,必须读取到最近写入的值。

缓存一致性(Cache Coherence):执行一个读操作,应该返回哪一个值。

存储一致性(Memory Consistency):如何让一个写操作让所有人都看到。

 

缓存一致性(Cache Coherence)

cache1中是2,但是之后cache3中写入了值3。

处理器核3若读取到2,那么读到了一个旧值,应当读到most recent值3.

一致性协议

写传播:保证一个写最终让所有处理器看到。

写序列:一堆写操作应当能够序列化。

如何保证写传播

写无效协议:在执行一个写操作时,将其他所有的副本无效。

写更新协议:在执行写操作后,更新所有副本

如何观测共享状态并序列化请求

基于侦听:所有cache通过共享总线观察其他cache的动作。

基于目录:多处理器维持一个目录,目录会跟踪所有私有缓存内容,然后进行排序。

基于侦听

由总线确保序列化。

        1. 广播模式,确保所有有序。
        2. 每一个缓存控制器侦听所有总线事务。
        3. 控制器更新缓存的状态。
        4. 使用写传播策略。

基于侦听序列化请求——VI协议(Valid/Invalid)

VI协议四种动作

处理器读:处理器自己的缓存中load一个值。

处理器写:处理器会写入一个值到cache。(会触发总线写,写入主存,同时让其他cache都无效)

总线读:触发总线读的处理器,从主存load一个值到自己的cache

总线写:发出总线写的处理器,将自己的cache写入到主存。其他处理器收到总线写消息,将自己的cache设置为Invalid

VI协议两种状态

Valid:缓存数据有效,可以直接读。

Invalid:缓存数据无效,只能从主存读,触发总线读,加载数据到cache。

 

VI协议的缺陷

每一次写都要更新主存。(因为处理器写会触发总线写)

每次写都需要广播。

状态变换图

Valid -> Valid :  处理器读(读一个valid的cache),处理器写,总线写。

Valid -> Invalid:响应总线上的总线写。

Invalid -> Valid: 处理器读,总线读

Invalid-> Invalid:处理器写,总线写

实线是响应处理器的动作,虚线是响应总线的动作。

core0 load一个值0xA,但是缓存中没有,触发总线读,从主存load一个值到cache.

core0 store值3到缓存,触发总线写,,将cache更新到主存,同时使得其他core的cache变为Invalid。

core1 load缓存中的值时,发现缓存中的值为Invalid,于是触发总线读,将主存的值load到cache中

 

特点

读取

if cache.state=='Invalid' :

   总线读,从主存读,且从load一个值到cache。

else :

        直接读取缓存。

写入

总线写,将自己cache值写入到主存。

让其他core的cache变为无效

 

基于侦听序列化请求——MSI协议

  三种状态

Modified:当前Cache已修改,缓存中数据与主存数据不一致(会触发总线排他读,其他cache变为无效,有效且修改过)

Shared:表示当前的处理器已经从另一个被Modified的处理器中获取到了数据。(有效且是最新的)

Invalid:当前Cache块失效,需要从其他状态为“S”或“M”的CPU出拿数据。

每一个Cache修改了一个数据后,其他Cache会被标记为无效。

 

五种动作

处理器读:处理器自己的缓存中load一个值。

处理器写:处理器会写入一个值到cache。(会触发总线写,写入主存,同时让其他cache都无效)

总线读:触发总线读的处理器,从主存load一个值到自己的cache

总线写:发出总线写的处理器,将自己的cache写入到主存。其他处理器收到总线写消息,将自己的cache设置为Invalid

总写排他读:触发总线读的处理器,将其他的cache状态变为Invalid,自己状态变为Modify

     

缺点

收到其他core发出的总线排他读,自己cache变为Invalid,其他某个core的cache中是最新的,但是没写入到主存。

若这时候读取cache,会触发总线读,直接从主存中读取一个值,只存中的值是旧的。

状态变化

 Shared -> Modified :向自己的缓存中写入一个值,但是没写入主存,状态变为Modified。

    Shared -> Invalid:其它Core将最新的值写入其缓存,触发总线排他读,收到总线排他读表示自己是旧的无法使用,状态变为Invalid。

    Invalid -> Modified:向自己的Core写入一个值。

 

    Invalid -> Shared:读取的时候自己是Invalid,于是状态为Modified的cache会将值写会主存,然后自己总线读一个值,这个值就是最新的。

    Modified -> Shared:其他cache为Invalid时被读取,自己将cache写入主存以便其他core读取,于是自己的变为最新的,状态为Shared。

后两条的前提读取Invalid时触发的cache miss 能够被识别,否则会导致读取旧的数据。

案例

Core0 load一个值,发现cache中没有数据,于是触发总线读,从主存读取一个值到自己的cache。

Core1 load一个值,发现cache中没有数据,于是触发总线读,从主存读取一个值到自己的cache。

Core0 store一个值10到自己的cache,自己的状态变为Modify,触发总线排他读,其他Core的Cache变为无效。(表示自己是最新的)

core1 store一个值10到自己的cache,自己状态变为Modify,触发总线排他读。其他core的状态变为Invalid。(表示自己的最新的)

core0 load一个值,发现自己的cache状态为Invalid,那么Core1会使用总线写将自己的cache写入主存,然后Core0从主存load一个值到自己cache。(主存中值可能是旧的值,这也是缺点)

特点

写入cache时,仅仅是变为Modify,不写入主存,然后发出总线排他读,并使得其它CPU的cache无效。

但是cache状态为Invalid时若读取,则会读取主存的数据,但是主存中数据可能是旧的。

解决方法

增加一个Exclusive状态:如果没有其他的share,也就是没有最新的未写入到主存的值,一个读取应该变成E状态,且不触发总线读。(用E表示从主存读到最新的)

增加Owner状态:负责写回,相当于S状态+负责写回。

当从M状态到S状态时,其他处于M状态的变成O状态而不是S

切分事务

打破了总线事务的原子性。

可以支持同时多事务执行。

优点 

拥有更高的吞吐率。

缺点

但是响应不一定是顺序

基于目录

特点

通过目录路由所有一致事务

非广播,乱序网络

缓存一致性——假共享

产生的原因:缓存一致性是块级别而不是word级别,但是一个块可以有多个word。

P1写wordi,P2写wordk,两个word由相同的块地址。

可能导致冲突,P1写完使得P2写的无效,P2写了后导致P1写的值无效。(Ping-Pong效果。)

 

缓存一致性——总线占用

一个原子操作read-modify-write需要两个内存操作。而不用其他处理器介入内存操作。

在多处理器环境下,总线在原子读或写操作整个期间被锁住

LR/SC指令

产生原因

总线事务的总数没必要减少,可以将原子指令切分为LR和SC指令。

Load Reserve

指令格式:lr.{w/d}.{aqrl} rd,(rs1)

作用:读取保留,将rs1中内容加载到rd寄存器,在rs1对应地址上设置保留标记

Store Conditional

指令格式:sc.{w/d}.{aqrl} rd,rs2,(rs1)。

作用:条件存储,根据条件将值将rs2写入到rs1内,不满足条件则不读。

切分为LR和SC指令的好处:

增加总线利用率。

避免了缓存ping-pong效应。(因为进程只要尝试获取互斥锁,得到了互斥锁才写,而不用每次尝试执行store操作)

 

 

 

 

 

 

 

标签:缓存,cache,总线,主存,Invalid,处理器,一致性
From: https://www.cnblogs.com/RedNoseBo/p/17308589.html

相关文章

  • 一致性hash算法(consistent hashing)
    consistenthashing 算法早在 1997 年就在论文 Consistenthashingandrandomtrees 中被提出,目前在 cache 系统中应用越来越广泛;1比如你有 N 个 cache 服务器(后面简称 cache ),那么如何将一个对象 object 映射到 N 个 cache 上呢,你很可能会采用类似下面的通用方......
  • 前端项目更新的缓存问题
    问题描述:微信公众号前端项目更新总会遇到不会加载最新代码问题,需要进行多次刷新或手动清空微信缓存。问题分析:1、前端项目本身是否存在缓存配置;2、nginx是否存在缓存配置。解决方案:在前端项目配置做过动态hash处理的前提下,更新后构建输出的cssjs图片等文件会被重新请......
  • 使用 jQuery Mobile 与 HTML5 开发 Web App (十七) —— HTML5 离线缓存
    本文要介绍的,是HTML5离线网络应用程序的特性,离线网络应用程序在W3C中的实际名称是"OfflineWebapplications",也称离线缓存。当用户打开浏览器时,浏览器会将一个列表中指定的资源都下载并储存在本地。下次当用户再访问这个网络程序时,浏览器会自动引用本地缓存中相应的文件,而......
  • 详解缓存更新策略及如何选择
    概述缓存更新是指在数据发生变化时,保持缓存和数据库的数据一致性的问题。如果缓存和数据库的数据不一致,会导致用户看到过期或者错误的数据,影响业务逻辑和用户体验。为了实现缓存更新,我们可以采用以下四种方式其中的一种:CacheAside策略:应用程序直接与数据库和缓存交互,并负责......
  • 一致性哈希(哈希环)解决数据分布问题
    哈希算法是程序开发过程中最广泛接触到的的算法之一,典型的应用有安全加密、数据校验、唯一标识、散列函数、负载均衡、数据分片、分布式存储。前些天遇到用一致性哈希(哈希环)的场景,不过我细想一下,对这个知识点好像了解过,但是又没太深印象,说不出具体是什么原理,怎么用,有哪些注意的地......
  • 泛微代码刷新缓存
    工具类:weaver.monitor.cache.CacheFactory;相关方法:ResultMapgetRecordCache(Stringvar1,Object...var2)refreshCache(Stringvar1,Objectvar2,ResultMapvar3)removeCacheForSql(Stringsql,Object...var2) ......
  • 更新缓存操作
    需求分析:问题描述:并发操作redis,发现redis连接数增长异常(呈直线上升)原因分析:发现redis更新时,没有处理好之前的连接缓存,而是直接替换,导致旧的缓存没有及时删除。修改方案:1.更新时,先关闭之前的连接,再替换2.只更新redis配置修改的连接update:之前的连接:比较(ip,pass......
  • redis缓存
    引入依赖<!--redis--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><!--spring2.X集成redis所需common-pool2--><dependency>......
  • springcache + redis 配置支持缓存ttl失效
    packagetst;importcom.fasterxml.jackson.annotation.JsonAutoDetect;importcom.fasterxml.jackson.annotation.JsonTypeInfo;importcom.fasterxml.jackson.annotation.PropertyAccessor;importcom.fasterxml.jackson.databind.DeserializationFeature;importcom.......
  • 项目Redis缓存设计心得体会
    1,列表类缓存比如一些列表类的缓存,如果列表是跟用户无关的,可以直接对查询的列表进行缓存,比如省份列表、菜单列表等。但是如果列表里面有跟用户相关的属性,比如文档的卡片列表里有用户是否下载过,设计缓存需要注意,可以将用户无关的卡片列表组装后进行缓存,上面的【已下载】【......