缓存一致性解决方案:MESI
我们知道,缓存如果不保证一致性,可能会导致程序发生预期之外的结果,正确性得不到保障,那如何保证缓存的一致性呢?
MESI协议就是用来解决缓存一致性问题的,下面来一步一步聊聊什么的MESI。
总线窥探
了解MESI之前,先了解一下什么是总线窥探。
![image](https://prod-files-secure.s3.us-west-2.amazonaws.com/371abca5-94fd-4d13-a43e-bbcb27be7c63/be025d36-6870-4cae-aced-8288ecff22cf/Untitled.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=ASIAZI2LB466UXKNN7WO%2F20250205%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Date=20250205T155229Z&X-Amz-Expires=3600&X-Amz-Security-Token=IQoJb3JpZ2luX2VjEC8aCXVzLXdlc3QtMiJIMEYCIQCi%2BCx3yCl4no48T%2Bp6C2BKmkl4JvRpJh9LhCCA2VlcVAIhAIDwbM%2Bymw2ViYBOch38bDL9FNlggpJAJnnokrdVzqkfKv8DCEgQABoMNjM3NDIzMTgzODA1IgwdKMI%2BHs7E%2B2g%2Fyfwq3AOPVzJab6tsn1%2FH7XEGmX6prMRPyKmf4fGkduN43Su%2BWQa0Un0euHURgzyAB42BPACvGKLnirvujioIIgM4byTLZzQ7emRobdWbwgNxvQyM8YTXsYbbo4%2BQpPfJu39WTvAwIfEEMLaVSLjxQRpPPQZMka1q3Ulr0oXTDr2vGFYDCKTzkbznPtleQ7oMHRh070z%2B0HuXMdgrdghq1BFaSDQpuOdygUifjwWCy32J29%2FtGmC72qE5A%2B9KITNpPYcvVYFVTnJRdljD0mfsmPEGwKKrXbuoVuEwdNxcFahvJu6%2Ff%2B5ernT0hYB80hxkHeNp4Rm2DbMQRHH%2B%2FVtZuGNKMG2462eYwIDf66O4OCXqbwGYx0EpqQIH2InryhhkrEXGZIONiGxXwyag9WMXI2JcfWvT7RhyWrPqTqlOMoiudwzWk%2BbyTZpPvNBRBKK3%2Bx830FqY33IrB0Yz%2FDpAnAIGRYTwVOB8UvgEz2Dg6F6QAdDkfWLKehgqDLAAogcLYfA3J3zQBn72k7q6ZTXeFZjmk8PgbSZgwbDvF7moxHy%2BDotcEYexbrM%2FfHjaJT0SaeMA5U%2BC%2BdSi1bz2iIlPmERO%2BTt2AFTamNlylGPFKd4gBu%2B8LNvH8Pe48G3Xu0u%2BLjC%2BgI69BjqkAbuEhg6W2X9vViC%2BR0naFeGbx%2BMMVZega%2BcjGo7T6xVrA8ib5dk%2BD596hUvqEZa8whcO%2Bhneoo%2BPwf9F14L6dRw1Uk7urTdlh1KWZrfGPjQOfRLndlIcpXYojYta3qwChFiWzh54xkdaZuRDpzrCe7XbrqpAMjPfGFWpmfLKU8sfk3ka8gS9Cj56im%2BBOxE4Pal0uhVxH3sERTtvPLcf2CpY6WJt&X-Amz-Signature=9744582f9502dd9802bf65a5b3d88847a0780dff4278f6bc9fc05027a094f282&X-Amz-SignedHeaders=host&x-id=GetObject)
一般我们的电脑和服务器都是基于总线的架构(Bus-based)。例如上图有3个cpu核心和一个共享的主存,每一个cpu通过同一个总线向主存读写数据。
总线窥探从通俗的话来讲,就是每一个cpu都可以监测到某一个内存地址的更新操作,因为所有cpu都是共用同一个bus,所以cpu可以关注自己的cache里有那些地址,并且关注这些地址的数据是否有更新。
窥探协议
那么是怎么实现这个窥探的呢?
有两种协议,写失效(Write Invalidate) 和 写更新(Write Update)
无论是Write Invalidate 还是 Write Update 操作,都需要通过总线仲裁来完成,总线仲裁就是同一时刻,只有一个cpu能够使用总线,类似给总线加了一把锁。
到底使用哪种协议呢?
写更新协议看上去最简单,但是存在性能问题,例如多次更新同一条数据,需要占用多次总线进行同步更新,而占用总线的成本是非常高的。
写失效协议虽然使用起来相对复杂,但是是最节省总线资源的方案,因为写失效协议不需要每次更新其他cpu缓存,仅仅是发送缓存失效消息。
如果你再多思考一下, 你会发现写失效不一定总是性能上强于写更新的,例如当一个cpu核心更新了一条数据之后,其他的cpu核心马上需要读取数据, 那总线资源一样会占用的非常大,但是实际情况不会这么极端。从经验上来看,写失效在性能上是好于写更新,但是不是绝对的。
MESI
在了解什么是写失效(Write Invalidate)之后,来看看什么是MESI。
MESI相当于是Write Invalidate的一个拓展,MESI试图让使用Write Invalidate协议的过程中,尽可能的节省总线资源。
MESI协议定义了所有的缓存行都有一个状态,状态分为4种:
从上面的名字可以看出来,MESI其实就是这4种操作的首字母
MESI还对缓存行的操作,进行了抽象,所有的操作都可以抽象成4种:
用一张图来展示这4种操作对应的状态变化:
![image](https://prod-files-secure.s3.us-west-2.amazonaws.com/371abca5-94fd-4d13-a43e-bbcb27be7c63/7b8f8ae4-b204-4a04-8011-2b6eaaba18e1/Untitled.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=ASIAZI2LB466UXKNN7WO%2F20250205%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Date=20250205T155229Z&X-Amz-Expires=3600&X-Amz-Security-Token=IQoJb3JpZ2luX2VjEC8aCXVzLXdlc3QtMiJIMEYCIQCi%2BCx3yCl4no48T%2Bp6C2BKmkl4JvRpJh9LhCCA2VlcVAIhAIDwbM%2Bymw2ViYBOch38bDL9FNlggpJAJnnokrdVzqkfKv8DCEgQABoMNjM3NDIzMTgzODA1IgwdKMI%2BHs7E%2B2g%2Fyfwq3AOPVzJab6tsn1%2FH7XEGmX6prMRPyKmf4fGkduN43Su%2BWQa0Un0euHURgzyAB42BPACvGKLnirvujioIIgM4byTLZzQ7emRobdWbwgNxvQyM8YTXsYbbo4%2BQpPfJu39WTvAwIfEEMLaVSLjxQRpPPQZMka1q3Ulr0oXTDr2vGFYDCKTzkbznPtleQ7oMHRh070z%2B0HuXMdgrdghq1BFaSDQpuOdygUifjwWCy32J29%2FtGmC72qE5A%2B9KITNpPYcvVYFVTnJRdljD0mfsmPEGwKKrXbuoVuEwdNxcFahvJu6%2Ff%2B5ernT0hYB80hxkHeNp4Rm2DbMQRHH%2B%2FVtZuGNKMG2462eYwIDf66O4OCXqbwGYx0EpqQIH2InryhhkrEXGZIONiGxXwyag9WMXI2JcfWvT7RhyWrPqTqlOMoiudwzWk%2BbyTZpPvNBRBKK3%2Bx830FqY33IrB0Yz%2FDpAnAIGRYTwVOB8UvgEz2Dg6F6QAdDkfWLKehgqDLAAogcLYfA3J3zQBn72k7q6ZTXeFZjmk8PgbSZgwbDvF7moxHy%2BDotcEYexbrM%2FfHjaJT0SaeMA5U%2BC%2BdSi1bz2iIlPmERO%2BTt2AFTamNlylGPFKd4gBu%2B8LNvH8Pe48G3Xu0u%2BLjC%2BgI69BjqkAbuEhg6W2X9vViC%2BR0naFeGbx%2BMMVZega%2BcjGo7T6xVrA8ib5dk%2BD596hUvqEZa8whcO%2Bhneoo%2BPwf9F14L6dRw1Uk7urTdlh1KWZrfGPjQOfRLndlIcpXYojYta3qwChFiWzh54xkdaZuRDpzrCe7XbrqpAMjPfGFWpmfLKU8sfk3ka8gS9Cj56im%2BBOxE4Pal0uhVxH3sERTtvPLcf2CpY6WJt&X-Amz-Signature=ac3f45c17e846c965d5b13667bd41cc3f7ed01c0a12aae693a9e8d4a0e0f64e6&X-Amz-SignedHeaders=host&x-id=GetObject)