首页 > 其他分享 >9、写传播和事务串行化的具体实现

9、写传播和事务串行化的具体实现

时间:2022-10-22 21:00:21浏览次数:55  
标签:状态 事务 核心 Cache 总线 传播 串行化 数据 CPU

1、总线嗅探

写传播的原则就是当某个 CPU 核心更新了 Cache 中的数据,要把该事件广播通知到其他核心。最常见实现的方式是总线嗅探(Bus Snooping

我还是以前面的 i 变量例子来说明总线嗅探的工作机制,当 A 号 CPU 核心修改了 L1 Cache 中 i 变量的值,通过总线把这个事件广播通知给其他所有的核心,然后每个 CPU 核心都会监听总线上的广播事件,并检查是否有相同的数据在自己的 L1 Cache 里面,如果 B 号 CPU 核心的 L1 Cache 中有该数据,那么也需要把该数据更新到自己的 L1 Cache。

可以发现,总线嗅探方法很简单, CPU 需要每时每刻监听总线上的一切活动,但是不管别的核心的 Cache 是否缓存相同的数据,都需要发出一个广播事件,这无疑会加重总线的负载。

另外,总线嗅探只是保证了某个 CPU 核心的 Cache 更新数据这个事件能被其他 CPU 核心知道,但是并不能保证事务串行化。

于是,有一个协议基于总线嗅探机制实现了事务串行化,也用状态机机制降低了总线带宽压力,这个协议就是 MESI 协议,这个协议就做到了 CPU 缓存一致性。

2、MESI协议

MESI 协议其实是 4 个状态单词的开头字母缩写,分别是:

  • Modified,已修改
  • Exclusive,独占
  • Shared,共享
  • Invalidated,已失效

这四个状态来标记 Cache Line 四个不同的状态。

「已修改」状态就是我们前面提到的脏标记,代表该 Cache Block 上的数据已经被更新过,但是还没有写到内存里。而「已失效」状态,表示的是这个 Cache Block 里的数据已经失效了,不可以读取该状态的数据。

「独占」和「共享」状态都代表 Cache Block 里的数据是干净的,也就是说,这个时候 Cache Block 里的数据和内存里面的数据是一致性的。

「独占」和「共享」的差别在于,独占状态的时候,数据只存储在一个 CPU 核心的 Cache 里,而其他 CPU 核心的 Cache 没有该数据。这个时候,如果要向独占的 Cache 写数据,就可以直接自由地写入,而不需要通知其他 CPU 核心,因为只有你这有这个数据,就不存在缓存一致性的问题了,于是就可以随便操作该数据。

另外,在「独占」状态下的数据,如果有其他核心从内存读取了相同的数据到各自的 Cache ,那么这个时候,独占状态下的数据就会变成共享状态。

那么,「共享」状态代表着相同的数据在多个 CPU 核心的 Cache 里都有,所以当我们要更新 Cache 里面的数据的时候,不能直接修改,而是要先向所有的其他 CPU 核心广播一个请求,要求先把其他核心的 Cache 中对应的 Cache Line 标记为「无效」状态,然后再更新当前 Cache 里面的数据。

我们举个具体的例子来看看这四个状态的转换:

  1. 当 A 号 CPU 核心从内存读取变量 i 的值,数据被缓存在 A 号 CPU 核心自己的 Cache 里面,此时其他 CPU 核心的 Cache 没有缓存该数据,于是标记 Cache Line 状态为「独占」,此时其 Cache 中的数据与内存是一致的;
  2. 然后 B 号 CPU 核心也从内存读取了变量 i 的值,此时会发送消息给其他 CPU 核心,由于 A 号 CPU 核心已经缓存了该数据,所以会把数据返回给 B 号 CPU 核心。在这个时候, A 和 B 核心缓存了相同的数据,Cache Line 的状态就会变成「共享」,并且其 Cache 中的数据与内存也是一致的;
  3. 当 A 号 CPU 核心要修改 Cache 中 i 变量的值,发现数据对应的 Cache Line 的状态是共享状态,则要向所有的其他 CPU 核心广播一个请求,要求先把其他核心的 Cache 中对应的 Cache Line 标记为「无效」状态,然后 A 号 CPU 核心才更新 Cache 里面的数据,同时标记 Cache Line 为「已修改」状态,此时 Cache 中的数据就与内存不一致了。
  4. 如果 A 号 CPU 核心「继续」修改 Cache 中 i 变量的值,由于此时的 Cache Line 是「已修改」状态,因此不需要给其他 CPU 核心发送消息,直接更新数据即可。
  5. 如果 A 号 CPU 核心的 Cache 里的 i 变量对应的 Cache Line 要被「替换」,发现 Cache Line 状态是「已修改」状态,就会在替换前先把数据同步到内存。

所以,可以发现当 Cache Line 状态是「已修改」或者「独占」状态时,修改更新其数据不需要发送广播给其他 CPU 核心,这在一定程度上减少了总线带宽压力。

事实上,整个 MESI 的状态可以用一个有限状态机来表示它的状态流转。还有一点,对于不同状态触发的事件操作,可能是来自本地 CPU 核心发出的广播事件,也可以是来自其他 CPU 核心通过总线发出的广播事件。下图即是 MESI 协议的状态图:

9、写传播和事务串行化的具体实现_数据

MESI 协议的四种状态之间的流转过程,我汇总成了下面的表格,你可以更详细的看到每个状态转换的原因:

9、写传播和事务串行化的具体实现_数据_02

标签:状态,事务,核心,Cache,总线,传播,串行化,数据,CPU
From: https://blog.51cto.com/u_10630401/5786124

相关文章

  • MYSQL数据库的事务的四大特性
    事务的特性原子性(Atomicity)事务是一个原子操作单元,其对数据的修改,要么全部执行,要么全部不执行一致性(Consistent)在事务开始和完成时,数据都必须保持一致状态。这意味着所有......
  • Hive创建事务表
    在Hive0.14版本后,ORC文件能够确保Hive在工作时的ACID性质被正确地得到使用,使得对数据进行更新操作成为可能,但Hive的事务仍被设计成每个事务适用于更新大批量的数据,而不建......
  • 【JavaScript】事件的冒泡,委派,绑定和传播
    文章目录​​冒泡事件​​​​特性:​​​​阻止冒泡事件的两种方法​​​​cancelBubble​​​​stopPropagation()​​​​委派事件​​​​特性​​​​获取点击的元素​......
  • JDBC管理事务_实现和数据库连接池_概述
    JDBC管理事务_实现:1.使用connection对象来管理事务开启事务:setAutoCommit(booleanautoCommit):调用该方法设置参数为false,即开后事务在执行sql之前开启事务提交事务:comm......
  • JDBC管理事务概述以及实现
    JDBC管理事务-概述JDBC控制事务:1.事务:一个包含多个步骤的业务操作,如果这个业务操作被事务管理,则这多个步骤要么同时成功,要么同时失败2.操作:1.开启事务......
  • 事务_事务隔离级别演示1与事务_事务隔离级别演示2
    事务_事务隔离级别演示1演示:SETGLOBALTRANSACTIONISOLATIONLEVELREADUNCOMMITTED;#开启事务......
  • Spring Cloud集成Seata分布式事务-TCC模式
    参考文章分布式事务实战方案汇总https://www.cnblogs.com/yizhiamumu/p/16625677.html分布式事务原理及解决方案案例 https://www.cnblogs.com/yizhiamumu/p/16662412.......
  • 分桶表+事务表+视图
    HiveBucketedTables分桶表分桶表也是桶表(bucket)是一种用于优化查询而设计的表类型分桶表把数据文件在底层分解若干个部分(被拆分某干个小文件)分桶要指定字......
  • 通俗易懂的MySQL事务及MVCC原理,我先收藏了!
    一、事务简介与四大特性事务指的是一组命令操作,在执行的过程中,要么全部成功,要么全部失败。由引擎层支持事务,MyISAM就不支持事务,而InnoDB是支持事务的。事务具有以下四大特性......
  • JDBC事务管理和JDBC管理事物_概述
    JDBC事务管理:1.Preparedstatement:执行sql的对象1.sQL注入问题∶在拼接sql时,有一些sql的特殊关键字参与字符串的拼接。会造成安全性问题1.输入用户随便,输入密码:a'or......