簡介: 針對寫少讀多的業務可以考慮通過添加資料庫節點來使其達到提升性能的目的,但添加節點,往往涉及到資料的搬遷,擴容周期比較長,很難應對徒增的業務流量,這個時候可以考慮采用讀寫分離的方式,将讀寫流量做分流,減輕主執行個體的壓力,同時利用隻讀庫橫向的擴充能力,快速提升讀性能。
作者 | 希明
在資料庫使用過程中經常會遇到一些場景:
- 業務寫流量一直相對比較穩定,但随着時間,資料不斷增加,資料庫的壓力也會越來越大,寫操作會影響到讀請求的性能,做任何優化可能都達不到最終的效果;
- 在應用的使用者通路量比較低的時候,一個資料庫的讀寫能力是完全能夠勝任的。但是在使用者通路量增大的時候,資料庫很快會成為瓶頸;
針對這種寫少讀多的業務可以考慮通過添加資料庫節點來使其達到提升性能的目的,但添加節點,往往涉及到資料的搬遷,擴容周期比較長,很難應對徒增的業務流量。這個時候可以考慮采用讀寫分離的方式,将讀寫流量做分流,減輕主執行個體的壓力,同時利用隻讀庫橫向的擴充能力,快速提升讀性能。
其基本原理是讓主資料庫處理事務性查詢,而從資料庫處理select查詢。當業務量非常大時,一台伺服器的性能無法滿足需求,就可以讀寫分離方式分攤負載,避免因負載太高而造成無法及時響應請求。目前業界實作讀寫分離的方案主要有兩種:
基于程式代碼内部實作
在代碼中根據select,insert進行路由分類,這類方法也是目前生産環境應用最廣泛的,優點是性能好,因為在程式代碼中已經将讀寫的資料源拆分至兩個,是以不需要額外的MySQL proxy解析SQL封包,在進行路由至不同資料庫節點。缺點是通常該架構較複雜,運維成本相對較高。
基于中間Proxy(odp/mycat等)實作
Proxy一般位于用戶端和伺服器之間,代理伺服器接到用戶端請求後通過解析SQL文本再将SQL路由至可用的資料庫節點中。優點是程式不需要改造可以實作無縫遷移,可移植性較好。缺點是性能相對前者略微遜色一些,并且并不是所有的讀操作都能夠被路由至從節點中。
上述方案都不能算是透明的,要不需要對業務代碼進行改造,要不需要業務系統依然第三方元件;除此之外,業界主流的讀寫方案都無法做到一緻性讀,應用在使用弱一緻性讀時,要充分考慮主備副本的資料同步延時,并根據具體業務場景考慮延時的業務影響(髒讀)是否能夠接受。讀寫分離業務都還需要做額外的改造,以應對隻讀庫異常或者延遲過大的時候下,對業務做降級處理。
為此,PolarDB-X核心側提出一種提供了透明的強一緻的讀寫分離能力,支援多種讀寫分離政策滿足各類業務需求。
PolarDB-X Native 讀寫分離
PolarDB-X配置了多種讀寫政策,提供了透明的強一緻的讀寫分離能力。簡單的說其特點有:
- 無論什麼狀況都不用擔心誤寫了“備副本或隻讀副本”,因為它不支援寫,寫操作會被路由到主副本;
- 無論什麼時候不用擔心“備副本或隻讀副本”故障,因為它會自動路由給其他正常的副本或者切回主副本;
- 無論什麼場景不用擔心 “備副本或隻讀副本”讀不到最新的資料,因為它提供的是強一緻的讀寫能力;
- 大查詢不用擔心打爆“主副本”,因為它支援将大查詢路由給”備副本或隻讀副本“,避免對主副本造成壓力。
其整體的方案設計如下:
PolarDB-X存儲節點基于X-Paxos複制協定,整合了binary log,實作了統一的consensus log。consensus log不僅扮演了binary log的角色,同時還維護了LogIndex(全局一緻性日志位點)。LogIndex中記錄了主庫了最新修改consensus log位點資訊,當隻讀庫做一緻性複制的時候,也會不斷更新自身的LogIndex資訊。通過LogIndex我們可以確定在隻讀庫上讀到最新的資料,結合TSO可以確定讀到已送出的一緻性資料。路由到隻讀節點的強一緻性讀查詢過程如下:
- 用戶端把請求發送到CN;
- CN識别到請求會發送給隻讀執行個體,首先會從主執行個體DN節點擷取目前最大LogIndex;
- CN把LogIndex +TSO 請求一起發送給隻讀節點;
- 隻讀節點根據接收到的LogIndex判斷是否等到隻讀節點事務狀态回放到相應位點;根據TSO判斷資料可見性,給CN傳回結果。
同時為了降低每次一次隻讀查詢都會分别與主庫互動擷取LogIndex,我們為此做了異步Grouping Fetch Logindex優化,在高并發下盡可能将多次Fetch Logindex整合成一次請求,大大降低對主庫的壓力。
讀寫分離的操作管理
業務上不需要做任何改造,在需要的時候購買隻讀執行個體,預設情況下主執行個體就具備了讀寫分離的能力。如果要開啟,需要在阿裡控制台點選主執行個體上的叢集位址-》配置管理。
會進入下隻讀分離的配置管理頁面
操作 | 解釋 |
資源配置 | 選擇購買的隻讀執行個體加入到讀寫分離叢集,隻有在讀寫分離叢集的執行個體才可以分擔主執行個體的流量 |
智能讀寫分離 | 基于統計資訊做代價估算,将偏AP的複雜查詢路由給隻讀執行個體做MPP加速。非混合負載場景,可以選擇關閉 |
隻讀流量占比 | 将隻讀流量設定按一定的比例路由給隻讀執行個體 |
資料一緻性 | 強一緻性: 路由到隻讀執行個體的請求可以讀到已送出最新鮮的資料,但如果隻讀執行個體延遲大的話,路由到隻讀執行個體 弱一緻性: 路由到隻讀執行個體的請求隻是讀到執行個體上可見的最新資料。 |
隻讀執行個體延遲閥值 | 隻讀執行個體延遲超過門檻值,那麼流量會打到其他延遲正常的隻讀執行個體上或者切回主執行個體。 |
隻讀可用性 | 當隻讀執行個體延遲超過門檻值或者隻讀執行個體 HA時,則認為目前隻讀執行個體處于不可用的狀态,流量自動切回主執行個體或者其他正常的隻讀執行個體上去。 |
使用者真正在使用的時候,業務上完全不需要改造任何代碼,一般隻需要調整隻讀流量占比,調整為0意味着流量全部路由給主庫;調整成>0,隻讀流量将按照設定的比例自動分流給隻讀執行個體。在這個基礎上結合隻讀執行個體延遲閥值和隻讀可用性,可以做到在隻讀執行個體異常狀态下,流量自動切回主執行個體或者其他正常的隻讀執行個體上去。除了資料庫級别的配置,PolarDB-X也支援session級别和query級别的讀寫配置,可靈活控制某個session下隻讀查詢或者某個具體query的路由分發。
讀寫分離的可用性測試
為了衡量PolarDB-X 讀寫分離能力的可用性,我們利用sysbench 從正确性 性能角度設計了三種實驗場景來驗證。
測試環境
- 測試所用執行個體規格
主執行個體規格2*16C128G (CN)+2*4C32G(DN), 2個隻讀執行個體規格 2*4C32G(CN) + 2*4C 32G(DN)
- 測試所用壓力機規格
ecs.g7ne.8xlarge(24 vCPU,48 GB記憶體)
測試參數配置
- 修改參數ENABLE_COROUTINE的值為true,XPROTO_MAX_DN_CONCURRENT的值為4000,詳細操作步驟請參見參數設定。
- 通過指令行連接配接到PolarDB-X執行個體,在同一會話内執行如下SQL語句,關閉日志記錄與CPU采樣統計:
set ENABLE_SET_GLOBAL = true;
set global RECORD_SQL = false;
set global MPP_METRIC_LEVEL = 0;
set global ENABLE_CPU_PROFILE = false;
測試資料準備
nohup sysbench --config-file='sysb.conf' --create-table-options='partition by key(id)' --tables='16' --threads='16' --table-size='10000000' oltp_point_select prepare &
實驗一:一緻性讀的正确性
從附件中下載下傳這次測試的oltp_insert_read_verify.lua腳本,該腳本邏輯比較簡單,就是在主執行個體插入一條資料,測試在不同并發下在一緻性讀開啟和關閉條件下,是否可以正确讀到。一次實驗的執行流程如下:
#準備表
sysbench --config-file='sysb.conf' --db-ps-mode='disable' --skip-trx='on' --mysql-ignore-errors='all' --tables='8' --threads={并發度} --time=60 oltp_insert_read_verify prepare
#運作
sysbench --config-file='sysb.conf' --db-ps-mode='disable' --skip-trx='on' --mysql-ignore-errors='all' --tables='8' --threads={并發度} --time=60 oltp_insert_read_verify run
#清理
sysbench --config-file='sysb.conf' --db-ps-mode='disable' --skip-trx='on' --mysql-ignore-errors='all' --tables='8' --threads={并發度} --time=60 oltp_insert_read_verify cleanup
測試結果
并發 | 不一緻性次數(弱一緻性讀) | 不一緻性次數(強一緻性讀) |
4 | 2 | |
8 | 5 | |
16 | 16 | |
32 | 33 | |
64 | 57 |
從測試結果看,強一緻性讀下,可以保證路由到隻讀執行個體的流量讀到最新的資料;而非強一緻性讀下,無法保證。
實驗二:高并發下吞吐表現
我們分别利用oltp_point_select和oltp_read_only兩個腳本,測試了下在目前規格下高并發下的性能資料。
- 點查場景
sysbench --config-file='sysb.conf' --db-ps-mode='disable' --skip-trx='on' --mysql-ignore-errors='all' --tables='16' --table-size='10000000' --threads=512 oltp_point_select run
測試了在不同隻讀執行個體個數,不同配置下的性能資料,其QPS表現如下
隻讀執行個體查詢占比 | 主執行個體+一個隻讀執行個體(強一緻性) | 主執行個體+一個隻讀執行個體(弱一緻性) | 主執行個體+兩個隻讀執行個體(強一緻性) | 主執行個體+兩個隻讀執行個體(弱一緻性) |
0% | 88201.17 | 88201.17 | 88201.17 | 88201.17 |
50% | 124269.63 | 171935.56 | 171783.84 | 208648.34 |
100% | 62891.86 | 89213.13 | 117133.83 | 169352.07 |
- oltp_read場景
sysbench --config-file='sysb.conf' --db-ps-mode='disable' --skip-trx='on' --mysql-ignore-errors='all' --tables='16' --table-size='10000000' --range-size=5 --threads=512 oltp_read_only run
測試了在不同隻讀執行個體個數,不同配置下的性能資料,其QPS表現如下
隻讀執行個體查詢占比 | 主執行個體+一個隻讀執行個體(強一緻) | 主執行個體+一個隻讀執行個體(弱一緻) | 主執行個體+兩個隻讀執行個體(強一緻) | 主執行個體+兩個隻讀執行個體(弱一緻) |
0% | 29145.43 | 29145.43 | 29145.43 | 29145.43 |
50% | 44084.40 | 55399.80 | 61698.85 | 73161.11 |
100% | 23115.23 | 29235.73 | 42160.54 | 56393.54 |
從測試結果看:
1. 在強一緻性讀下,在TP讀場景下流量從主執行個體切換到隻讀執行個體上吞吐的性能衰減20~30%,但是通過添加隻讀執行個體個數,性能可以做到一定的線性增加;
2.在弱一緻性讀下,在TP讀場景下流量從主執行個體切換到隻讀執行個體上吞吐的性能未衰減,且通過添加隻讀執行個體的個數,性能可以做到線性增加;
實驗三:低并發下RT表現
同樣的我們分别利用oltp_point_select和oltp_read_only兩個腳本,測試了下在(一個主執行個體+隻讀執行個體)下在強一緻性讀條件下,不同并發的RT表現。
- 點查場景(ms)
并發 | 隻讀查詢比例0% | 隻讀查詢比例100% | 隻讀查詢比例50% |
4 | 0.61 | 0.89 | 0.87 |
8 | 0.62 | 0.91 | 0.89 |
16 | 0.64 | 0.94 | 0.90 |
32 | 0.71 | 1.04 | 0.99 |
64 | 1.18 | 1.27 | 1.27 |
- oltp_read場景(ms)
并發 | 隻讀查詢比例0% | 隻讀查詢比例100% | 隻讀查詢比例50% |
4 | 11.65 | 21.89 | 17.63 |
8 | 12.21 | 22.69 | 17.29 |
16 | 14.21 | 23.95 | 18.23 |
32 | 20 | 27.17 | 21.50 |
64 | 40.5 | 50.7 | 31.37 |
從測試結果看:
- 低并發場景下,隻讀執行個體和主執行個體壓力都不大,流量從主執行個體切換到隻讀執行個體上,RT衰減近30%~40%, 但都是在業務可以接受的RT範圍内抖動;
- 随着并發增加,流量從主執行個體切換到隻讀執行個體上RT衰減會變得不明顯,主執行個體的資源會成為影響RT的主要因素。
本文的讀寫分離路由的是非事務下的隻讀流量,這裡給大家提一個問題:事務下的讀查詢是否可以做讀寫分離?
點選檢視原文,擷取更多福利!
https://developer.aliyun.com/article/1064901?utm_content=g_1000367011
版權聲明:本文内容由阿裡雲實名注冊使用者自發貢獻,版權歸原作者所有,阿裡雲開發者社群不擁有其著作權,亦不承擔相應法律責任。具體規則請檢視《阿裡雲開發者社群使用者服務協定》和《阿裡雲開發者社群知識産權保護指引》。如果您發現本社群中有涉嫌抄襲的内容,填寫侵權投訴表單進行舉報,一經查實,本社群将立刻删除涉嫌侵權内容。