本篇文章著眼于 Linux 頁面大小對數據庫性能的影響,以及如何優化數據庫 Kubernetes 節點。
大多數流行的數據庫都受益于 Linux 大頁面。
Kubernetes 最初旨在大規模編排容器的生命周期,用于輕量級、無狀態應用程序,如 Ngnix、Java 和 Node.js。對于這個用例,Linux 4K 頁面是正確的選擇。
最近,通過添加Statefulsets、Persistent Volumes和大頁面等功能,Kubernetes 得到了增強,以支持大型、有狀態、持久性數據庫。
下圖顯示了使用 Linux 大頁面對數據庫性能的影響有多大。
上圖顯示,對于相同的數據庫,相同的數據,相同的工作負載,使用Linux 2MB頁面而不是4K頁面時吞吐量可以提高8倍。該圖還顯示,隨著并發水平的提高,大頁面的好處也隨之增加。
文章的其余部分介紹了一些背景概念,并著眼于影響數據庫工作負載的 Linux 頁面大小的因素。
Linux 頁面大小
所有現代多用戶操作系統都使用虛擬內存來使不同的進程能夠使用內存而不必擔心底層細節。Linux x86 64 的系統使用分頁進行虛擬內存管理。
Linux x8664 支持以下頁面大小:
4K
2MB
1GB
頁大小是可用于虛擬內存管理的連續數據的最小單位。?
頁面的大小是一種權衡。4K 頁面最大限度地減少了小內存分配的內存浪費。對于大內存分配,使用 2MB 或 1GB 頁面總共需要更少的頁面,而且速度會明顯更快,因為將虛擬內存轉換為物理內存地址會產生相關成本。?
TLB 緩存命中和未命中
Linux 上任何進程的每次內存訪問(例如,無論是 Nginx、Node.js 還是 MySQL)都需要從虛擬內存轉換為物理內存。由于這是一個常規的操作,所有 CPU 都有某種形式的轉換后備緩沖區[TLB],它充當最近轉換的內存地址的緩存。
所有從虛擬內存到物理內存的轉換首先查看 TLB 中是否已經存在映射。如果映射已經存在,則稱為 TLB 緩存命中。TLB 緩存命中非常快,并且發生在硬件中。當 TLB 緩存中不存在從虛擬內存到物理內存的轉換時,稱為 TLB 緩存未命中。TLB 緩存未命中需要通過頁面遍歷在 Linux 內核頁表中的軟件中解決映射。盡管頁面遍歷是高效的 C 代碼,但它比通過 TLB 緩存在硬件中進行映射要慢得多。
為什么 TLB 緩存未命中對數據庫很重要
所有數據庫最終都需要訪問內存中的數據進行讀取或寫入。所有這些數據庫讀取或寫入都需要至少進行一次 TLB 查找。TLB 緩存未命中會顯著減慢數據庫的讀寫速度:
數據庫越大,訪問的不同頁面越多,需要的 TLB 查找就越多。這實際上是數據庫工作集大小。
并發越大,單位時間需要的 TLB 查找越多
如果您有具有可變長度數據類型(例如字符串、JSON、CLOB 或 BLOB)的行/記錄,那么這些行/記錄的寬度很容易超過 4KB。當 Linux 頁面大小為 4KB 時,訪問寬度為 20KB 的單行/記錄通常需要至少五次 TLB 查找。如果使用 2MB 或 1GB Linux 頁面,訪問相同的 20KB 行/記錄通常只需要一次 TLB 查找。所以一般來說,數據庫行(rows)/記錄(record)越寬,大頁面與 4K Linux 頁面的優勢就越大。
挑戰在于 CPU 具有少量 TLB 緩存條目:
4K 頁面的 L1 TLB 中64個條目,2MB 頁面的 32 個條目,1G 頁面的 8 個條目
4K + 2MB 頁面的 L2 TLB 中有1024個條目
4K + 1GB 頁面的 L2 TLB 中有1024個條目
AMD EPYC Zen 3
4K + 2MB 頁面 + 1GB 頁面的 L1 TLB 中的64 個條目
4K 和 2MB 頁面的 L2 TLB 中的512 個條目
由于 L1 CPU 緩存通常只有大約 64 個 TLB 4K 條目,而最新的 Intel 和 AMD CPU 上的 L2 緩存則有 512 到 1024 個 4K 條目,如果您的數據庫具有寬行/記錄并訪問許多不同的行/記錄,那么它幾乎總是會得到 TLB 緩存未命中。
如果您使用 2MB 頁面,那么您不太可能遇到 TLB 緩存未命中,因為您有效地使 TLB 緩存更大:
AMD EPYC Zen 3 CPU 比?L1 和 L2 CPU?緩存大?512 倍
英特爾 Ice Lake CPU 的 L1 CPU 緩存大 256 倍,L2 CPU 緩存大 512 倍
減少 TLB 緩存未命中的數量可以對數據庫性能產生顯著的積極影響。
基準
Linux 并不關心你的數據庫是 MySQL、PostgreSQL 還是 Oracle。Linux 并不關心您的應用程序是用 Node.js、Java、Go、Rust 還是 C 編寫的。Linux 性能取決于諸如工作負載每單位時間發生多少 TLB 緩存未命中等指標。
以下基準測試著眼于幾種配置:
窄行(Narrow)/記錄 [128 字節],訪問 1 億條不同的行/記錄的概率均勻
整個行/記錄應適合單個 4KB Linux 頁面
中等行(Medium)/記錄 [8 KB],平均訪問 1 億條不同的行/記錄的概率
行/記錄應至少適合兩個 4KB Linux 頁面
更寬的行(Wider)/記錄 [16 KB],甚至有可能訪問 1 億條不同的行/記錄
行/記錄應至少適合四個 4KB Linux 頁面
16 KB 不是很寬,但結果很顯著
要最小化變量的數量:
只執行數據庫讀取,數據庫中的所有 1 億行都可以輕松放入 DRAM 并且數據庫被“預熱”
數據庫客戶端使用 IPC 而不是 TCP 套接字來訪問數據庫
這種配置意味著沒有磁盤 IO 或網絡處理,因此工作負載會在 CPU 和/或內存訪問上出現瓶頸。
128 字節行/記錄的4K Linux 頁面
上圖顯示,在 AMD EPYC 7J1C3 @ 2.55 GHz 處理器上使用 4K Linux 頁面和 128 個數據庫連接,在單臺 Linux 機器上每秒可以執行超過 350 萬次數據庫讀取。
128 字節行/記錄的4K 與 2MB 頁面
上圖顯示,對于相同的硬件、相同的數據庫、相同的表、相同的數據、相同的查詢,2 MB 的大頁面可以實現比使用 4K Linux 頁面時多出 8 倍的吞吐量。
對于窄行/記錄,吞吐量提高 8 倍是一個顯著的結果。
8 KB行/記錄的4K 與 2MB 頁面
對于 8KB 寬的數據庫行/記錄,2MB 頁面可以提供比 4K 頁面多 8 倍的吞吐量。
對于中等寬度的行/記錄,吞吐量提高 8 倍是一個重要的結果。
16 KB行/記錄的4K 與 2MB 頁面
上圖顯示,對于相同的硬件、相同的數據庫、相同的表、相同的數據、相同的查詢,2 MB 的大頁面可以實現比使用 4K Linux 頁面時多出 5 倍的吞吐量。
對于更寬的行/記錄,吞吐量提高 5 倍是一個重要的結果。
2MB 和 1GB Linux 頁面怎么樣
很容易看出 2MB Linux 頁面與 4K 頁面的優勢,例如提高 8 倍。您是否還希望看到 2MB 和 1GB Linux 頁面之間的顯著差異?
由于所有測試的行寬都可以放入 2MB 頁面,唯一的變量是 2MB 與 1GB Linux 頁面的 TLB 緩存未命中率,用于 1 億不同的行/記錄。
對于所有經過測試的行寬 [128 字節、8KB 和 16KB],1GB Linux 頁面的吞吐量比 2MB Linux 頁面高 1% 到 21%。
雖然高達 21% 的吞吐量改進不如 8 倍令人印象深刻,但它仍然存在一些差異。
也許行/記錄寬于 2MB 的測試會顯示顯著差異?
Kubernetes 節點專業化
在 Kubernetes 的早期,工作負載往往用于小型、無狀態的“基于 Web”的應用程序,例如負載均衡器、Web 服務器、代理和各種應用程序服務器。對于這個用例,使用 Linux 4K 頁面是一個合適的選擇。
最近,更專業的工作負載正在 Kubernetes 集群中運行,這些集群具有不同的硬件和/或軟件要求。例如,機器學習工作負載可以在通用 x86 64位 CPU 上運行,但在具有 GPU 或 ASIC 的 Kubernetes 節點上運行速度往往要快得多。此外,某些 Kubernetes 節點可能專門用于具有快速本地存儲、更多 RAM 或可能運行 ARM 64 CPU。
因此,并非所有 Kubernetes 節點都具有完全相同的 CPU、RAM、存儲等,一些節點可以使用守護程序集或節點標簽來定義和公開這些節點的特定功能。使用POD 標簽[使用選擇器來匹配節點標簽],允許 Kubernetes 調度程序在最合適的節點上自動運行 POD。
上圖顯示了具有四種類型的專用節點的 Kubernetes 集群。
你可以做些什么來優化 Kubernetes 上的數據庫性能
通常不在您控制范圍內的事情:
數據庫行/記錄的寬度
您的數據庫中有多少行/記錄
您的數據庫工作集大小
數據庫中數據訪問的并發性和頻率
CPU 的 TLB 緩存大小
在范圍內可以控制你的Kubernetes集群的事情:
Linux 內核在 Linux x8664 Kubernetes 節點上使用 4KB、2MB 還是 1GB Linux 頁面
您配置了多少 Linux 大頁面 [2MB 或 1GB]
Kubernetes 應用程序的內存和大頁面資源?的請求和限制
數據庫被認為是 Kubernetes 中的一個應用程序
您可以選擇為要在其上運行數據庫工作負載的一組機器配置具有 2MB 或 1GB 大頁面的 Kubernetes 節點 [即 Linux 主機]。
在 Linux上配置大頁面的方式與Kubernetes 無關。您必須在 Linux 內核中配置大頁面,因為您無法在 Kubernetes 或容器級別執行此操作。通常你想關閉透明大頁面,因為它們通常不會提高數據庫性能,只會浪費內存。
在 Linux x8664 上配置 2MB 頁面對于任何 Linux 發行版都相當簡單,通常無需更改啟動時間參數即可完成。
配置 1GB Linux 頁面的步驟因發行版而略有不同,并且需要啟動時間參數。我能夠在最近的 Intel Xeon 和 AMD CPU 上配置 1 GB Linux 頁面,用于:
紅帽企業 Linux 7.9 和 8.4
Oracle Linux 7.9 和 8.4
CentOS 7 和 8
Ubuntu 18.04 和 20.04
SuSE 12 和 SuSE 15
您應該為 Kubernetes 上的數據庫配置多少大頁面
這個問題是特定于數據庫的。這取決于您的 Kubernetes 節點有多少 RAM、您希望在該節點上運行多少其他 [非數據庫] POD、這些 POD 需要多少 RAM,以及最終您的數據庫通過使用更多內存而受益多少。
總結
大多數流行的數據庫在 Linux x86 64 上看到了大頁面的性能優勢
Kubernetes 支持 4KB、2MB 和 1GB 的 Linux 頁面
由于歷史原因,大多數 Kubernetes 集群使用 4KB Linux 頁面
許多 Kubernetes 集群根據工作負載優化一些節點 [例如機器學習、快速本地存儲、通用無狀態 Web 應用程序等]
考慮添加另一類經過優化以提高數據庫性能的節點。
使用 2MB 或 1GB 頁面在某些 Kubernetes 節點上配置 Linux 內核以優化它們的數據庫性能
根據您的數據庫為這些機器選擇適當數量的大頁面和 4K Linux 頁面
編輯:黃飛
?
評論