近期關於緩存設計的一些思考


我們先來看看我們常說的緩存有哪些

  1. CPU 的 L1, L2, L3 緩存
  2. 操作系統內存(相對於CPU來說也是緩存)
  3. 操作系統 page cache 高速頁緩存(緩存磁盤中的數據)
  4. Redis 用作 MySQL的緩存
  5. MySQL buffer pool 的數據頁緩存
  6. Java HashMap 實現的堆內緩存

通過上面的例子我們可以知道緩存的實現不一定都是DRAM內存,但他們的作用都一樣,解決兩個系統或層次的讀寫能力差距

操作系統的緩存

在極客時間《Java並發編程實戰》這樣寫道

這些年,我們的 CPU、內存、I/O 設備都在不斷迭代,不斷朝着更快的方向努力。但是,在這個快速發展的過程中,有一個核心矛盾一直存在,就是這三者的速度差異。
CPU 和內存的速度差異可以形象地描述為:CPU 是天上一天,內存是地上一年(假設 CPU 執行一條普通指令需要一天,那么 CPU 讀寫內存得等待一年的時間)。內存和 I/O 設備的速度差異就更大了,內存是天上一天,I/O 設備是地上十年。

程序里大部分語句都要訪問內存,有些還要訪問 I/O,根據木桶理論(一只水桶能裝多少水取決於它最短的那塊木板),程序整體的性能取決於最慢的操作——讀寫 I/O 設備,也就是說單方面提高 CPU 性能是無效的。

為了合理利用 CPU 的高性能,平衡這三者的速度差異,計算機體系結構、操作系統、編譯程序都做出了貢獻,主要體現為:
1. CPU 增加了緩存,以均衡與內存的速度差異;
2. 操作系統增加了進程、線程,以分時復用 CPU,進而均衡 CPU 與 I/O 設備的速度差異;
3. 編譯程序優化指令執行次序,使得緩存能夠得到更加合理地利用。

同時作者也說了緩存帶來的問題:可見性,這也是並發編程Bug的源頭之一

一個線程對共享變量的修改,另外一個線程能夠立刻看到,我們稱為可見性。
在單核時代,所有的線程都是在一顆 CPU 上執行,CPU 緩存與內存的數據一致性容易解決。因為所有線程都是操作同一個 CPU 的緩存,一個線程對緩存的寫,對另外一個線程來說一定是可見的。
多核時代,每顆 CPU 都有自己的緩存,這時 CPU 緩存與內存的數據一致性就沒那么容易解決了,當多個線程在不同的 CPU 上執行時,這些線程操作的是不同的 CPU 緩存。

Redis 用作緩存

下面我們在看看 Redis 用作緩存的場景

在極客時間《Redis核心技術與實戰》中作者寫道:

一個系統中的不同層之間的訪問速度不一樣,所以我們才需要緩存

所以,計算機系統中,默認有兩種緩存:
1. CPU 里面的末級緩存,即 LLC,用來緩存內存中的數據,避免每次從內存中存取數據;
2. 內存中的高速頁緩存,即 page cache,用來緩存磁盤中的數據,避免每次從磁盤中存取數據。

還有一點非常重要,文中也提到了

緩存系統的容量大小總是小於后端慢速系統的,我們不可能把所有數據都放在緩存系統中。

這其實取決於硬件的限制成本,讀寫越快的存儲越貴,容量越大的存儲越貴,並且兩者不是線性增長的關系。

另外這個限制也說明緩存系統是要有數據淘汰機制的,比如redis就有多種數據淘汰策略

同時還要關注緩存命中率的問題,有限的資源當然要給訪問更頻繁的數據。

那么Redis用作磁盤DB的緩存又會帶來什么問題呢?

就是我們常說的緩存不一致問題,這里不展開討論了

MySQL中的緩存設計

我們都知道MySQL的數據是存儲在磁盤上的,但是在購買MySQL實例時,往往能看到8核32g,64g這樣的配置,為什么磁盤數據庫還需要這么大的內存呢,如果你查看的內存使用量,發現也是不低的

這是因為MySQL也有自己的數據頁內存,和操作系統類似,操作系統對磁盤有page cachemysql也有 buffer pool

另外,MySQL作為一個復雜的數據庫系統,在磁盤IO上做了大量的緩存設計,比如寫 binlogbinlog cache,寫 redo logredo log cache

同時 MySQL 也利用了操作系統的高速頁緩存(page cache)來提高讀寫性能,比如組提交機制

MySQL 涉及到的緩存很多,這里不細講了,極客上面的課有對上面的內容作解釋,MySQL 官方文檔也都有對應的描述

總結

  1. 一個系統中的不同層之間的訪問速度不一樣,所以我們才需要緩存
  2. 緩存會帶來數據一致性問題,可見性問題
  3. 緩存往往容量是小於被緩存數據的,所以任何緩存系統都要關注緩存命中率和數據淘汰的問題

這里就不展開說如何解決緩存帶來的問題了,每個系統都有自己的解決方案

簡單聊聊,最近的一些收獲,歡迎指正討論


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM