淘寶商品庫MySQL優化實踐的學習
淘寶商品庫是淘寶網最核心的數據庫之一,采用MySQL主備集群的架構,特點是數據量大且增長速度快,讀多寫少,對安全性要求高,并發請求高。由于 MySQL最初的設計不是用來存儲大規模數據的,但淘寶的數據量非常驚人,所以在I/O方面,尤其是CPU I/O層面會有很大瓶頸,因此淘寶的主要目標也是解決IO方面的瓶頸問題。
以下內容整理自淘寶的演講,演講內容包括淘寶商品庫硬件的選型決策,安全性和性能的平衡,特別是創新引入PCI-E Flash卡和Flashcache作為Cache提高IO性能,在保證安全性的前提下就包括MySQL、InnoDB引擎、文件系統、系統Page Cache、 IO調度算法、DM層(Flashcache)、Raid卡、設備驅動在內的整條IO路徑的Cache進行優化,進一步挖掘了系統IO的潛能,重點介紹優化過程中的一些經驗教訓、測量手段和工具。
一、商品庫項目背景介紹以及約束
淘寶的產品線很多,以淘寶的商品庫為例,商品庫是賣家賣的所有的商品信息數據庫。我們都知道淘寶商品是非常多的,有可能是十億級別的,而且淘寶每年的數據都會翻番,在淘寶上,由于賣家是非常活躍的,所以每天的交易數也是非常多的,而且每天的訪問量也是相當大的。更比如在一些高峰期,比如節假日,像光棍節促銷,當時一天的訪問量可就是平常的好幾倍,幾十倍的樣子。
商品庫(單機,測試)情況
-
無復雜查詢,離散度高
-
記錄數:1億條鍵值對
-
記錄大小:100字節
-
數據文件:170G
-
訪問熱點情況:20%的鍵占用55%的訪問量
-
鍵讀寫比例: 10:1
硬件選擇
- 主機: Dell; PowerEdge C2100;
- 處理器: physical = 2, cores = 12, virtual = 24
- 內存: 96 G
- RAID卡:LSI MegaSAS 9260/512MB Memory
- PCI-E Flash卡: Fusion-io ioDrive 320GB/MLC
- 硬盤: SEAGATE ST3300657SS 300G x 12
軟件選擇
- 發行版: Red Hat Enterprise Linux Server release 5.4
- 內核: Kernel | 2.6.18-164.el5
- 文件系統:Ext3
- Flashcache: FB內部版本
- MySQL 版本: 5.1.48-log Source
二、技術要求和方案
1、商品庫技術要求:
- 高可用,安全第一。因為淘寶賣家的商品都存在上面,一大堆數據,商品沒了,淘寶會非常的難受;
- 高性能,性能平穩,性價比高。因為數據量大,而且未來增長的速度會非常快,以前系統是跑在Oracle的小機上面,它的成本是非常高的。現在改用高性能的PC服務器,性價比較高,而且Oracle數據庫的能力不足以維持淘寶的更新速度;
- 控制運維風險。Oracle是有一套完整的工具,利用它們我們可隨時查看相關的狀態和預測它的一些變化。MySQL作為開源產品,這部分的功能稍顯欠缺,因此就需要根據運維團隊和DBA的需求去開發一些工具。
2、調優指導思想
- 杜絕拍腦袋,理論(源碼)指導+精確測量+效果驗證
- 內存為王
- 數據訪問規律導向,隨機數據和順序數據盡量分離
- 盡量提高IO的利用率,減少無謂的IO能力浪費
- 在安全性的前提下,盡可能的利用好系統各個層次cache
3、技術方案
-
MySQL數據庫集群,數據水平切割,主從備份
-
采用高性價比PC服務器,大內存,強勁CPU,可靠性高
-
采用高性能PCI-E Flash卡作為cache, 提高系統的IO性能
-
充分利用系統各部件的cache, 大膽采用新技術
-
充分考慮容災,在各個層面考慮數據的安全性
4、調優工具
-
源碼+emacs+大腦
-
必備工具:systemtap、oprofile、latencytop 、blktrace/btt/seekwatcher、aspersa、tcprstat、sar、gdb
-
自制工具:bash腳本、gnuplot腳本
三、系統資源規劃
內存分配:
- MySQL
- InnoDB buffer pool
- OS pagecache
- 驅動程序
IO能力分配:
- 讀能力,零散讀,提高IOPS
- 寫能力,集中寫,提高吞吐量
Cache分配:
- MySQL內部cache
- 匿名頁面/文件頁面
- Flashcache 混合存儲
- Raid卡內部cache
1、MySQL數據庫
考慮因素:
- 主從備份帶來的性能影響
- 復雜數據查詢操作是否需要預留內存以及上限
- 數據備份dump對系統的影響,避免系統swap
- 開啟binlog帶來的性能開銷
- 限制最大鏈接數
#############################
-
max_binlog_cache_size=2G
-
max_binlog_size = 500M
-
max_connections = 1020
-
max_user_connections=1000
-
query_cache_size = 30M
2、InnoDB引擎
考慮因素:
- 盡可能大的BP(buffer pool)
- 日志和數據分設備存儲
- 離散數據走direct-IO,順序日志走buffered-IO
- 減少臟頁的同步,提高命中率
- 減少鎖對多核CPU性能的影響
- 提高底層存儲默認的IO能力
#############################
-
innodb_buffer_pool_size = 72G
-
innodb_flush_method = O_DIRECT
-
innodb_sync_spin_loops=0
-
innodb_log_group_home_dir = /u02/
-
innodb_io_capacity=2000
-
innodb_thread_concurrency = 64
3、高速頁緩存
考慮因素:
- page資源傾斜給數據庫, 盡量不浪費,兼顧臨時內存申請
- 避免NUMA架構帶來的zone內存分配不均而導致的swap現象
- cache大部分由InnoDB日志產生,適時清除,限制page數量
#############################
-
# numactl –interleave=all mysqld
-
# sysctl vm.drop_caches = 1
-
vm.swappiness = 0
-
vm.dirty_ratio = ?
-
vm.dirty_background_ratio =?
-
vm.pagecache = ?
4、文件系統
考慮因素(選擇):
- Ext3/4
- Xfs
考慮因素(配置):
- 減少元數據變化產生的IO
- 對混合存儲系統友好
- 關閉barrier
#############################
-
/dev/mapper/cachedev (rw,noatime,nodiratime,barrier=0) /u01
-
/dev/sda12 (rw,barrier=0) /u02
5、IO調度
考慮因素:
- 調度算法對減少磁頭移動的效果
- 關閉預讀
- 設備隊列長度
#############################
-
sda | [deadline] 128
-
sdb | [deadline] 128
6、混合存儲(Flashcache)
考慮因素
- 結合磁盤的大容量,PCI-E Flash卡的高隨機讀寫性能優點
- 數據盡可能多停留在PCI-E Flash卡上,提高讀寫命中率
- 減少同步次數,保留磁盤的IO能力
- 適時同步數據,減少安全風險
#############################
-
dev.flashcache.dirty_thresh_pct = 90
-
dev.flashcache.cache_all = 0
-
dev.flashcache.fast_remove = 1
-
dev.flashcache.reclaim_policy = 1
7、Raid卡
考慮因素:
- 邏輯分卷
- Cache使用寫優先,讀少分配(數據無相關性效果不好)
- 數據安全和raid level
- 少預讀
#############################
-
Controller | LSI Logic / Symbios Logic LSI MegaSAS 9260 (rev 03)
-
Model | LSI MegaRAID SAS 9260-8i, PCIE interface, 8 ports
-
Cache | 512MB Memory, BBU Present
-
BBU | 95% Charged, Temperature 28C, isSOHGood=
-
VirtualDev Size RAID Level Disks SpnDpth Stripe Status Cache
-
0(no name) 278.875 GB 1 (1-0-0) 2 1-1 64 Optimal WB, RA
-
1(no name) 1.361 TB 1 (1-0-0) 2 5-5 64 Optimal WB, RA
8、存儲設備驅動
考慮因素:
- 減少IO的抖動,提高IOPS
- 提高壽命
- 關閉或減少預讀
#############################
PCI-E Flash卡驅動:
$cat /etc/modprobe.d/iomemory-vsl.conf
-
options iomemory-vsl use_workqueue=0
-
options iomemory-vsl disable-msi=0
-
options iomemory-vsl use_large_pcie_rx_buffer=1
四、具體優化內容
1、安全保證
- Raid卡帶Flash,掉電保護,raid level10防止磁盤損害
- PCI-E卡自身有日志系統,恢復時間最差10分鐘
- Ext3文件系統帶日志保護
- Flashcache上的cache數據最多24小時都會同步到SAS盤
- 數據庫Innodb引擎本身有redo日志,數據安全校驗,高級別日志同步
- MySQL主從備份
- 商品庫應用方有事務日志
2、性能保證
解決IO瓶頸:
- 高速PCI-E Flash卡做Cache,讀寫速度可達800/500M
- 10 x SAS 300G 存放離散度高數據文件
- 2 x SAS 300G 存放順序binlog和trx日志
- 控制數據庫臟頁面的刷新頻率和強度
- 優化操作系統的pagecache,資源傾斜, 杜絕swap發生
- 優化文件系統減少meta數據的產生,以及寫入延遲
- 優化IO調度器和預讀
- 開啟raid卡的讀寫cache
- 優化設備驅動,適應高強度的讀寫請求,減少jitter
解決CPU瓶頸:
- 業務上優化掉復雜查詢
- 優化自旋鎖
3、運維保證
數據預熱:
- 支持熱點數據每秒150M從磁盤直接加載到混合存儲
- 數據庫重新啟動,無需重新預熱
數據庫DDL 操作:
- 控制數據表的大小,讓DDL時間可接受
- 減少DDL對性能的沖擊
混合存儲cache:
- 通過設置白名單,減少諸如備份操作對cache的干擾
- 混合存儲cache可管理
五、優化成果
經過優化從機器的運算能力上來看的話,比原來要高很多,從設備的總體的價格來看的話,相比原來小機的價格,現在的價格相當于原來的幾分之一。具體細節為:
- 充足的容量規劃,可對抗突增業務,滿足未來幾年業務增長
- 系統總體運行平穩,系統負載CPU util <50%,磁盤 util <10%,PCI-E Flash卡 util < 20%
- QPS/36000,其中讀/32800,寫/3200
- 請求平均延時時間:260微秒(包括網絡時間)
- 掉電和操作系統失效的情況下,數據無丟失
- 第一次預熱時間半個小時以內,之后只需幾分鐘
六、一些重要討論問題的分享
1、優化MySQL的過程中有沒有涉及到水平分片,或者垂直分片,大概的策略是什么?
這塊因為之前的MySQL從業務的角度上我們已經優化過了。涉及到業務上的復雜SQL查詢,基本上都把它當成Key- Value來處理。所以說在水平切割上就變得非常簡單,只需要根據用戶的這些ID把它平均地分割到集群的各個機器上去即可,所以說這塊會做得非常簡單,也不會有那些非常復雜的SQL。
2、淘寶在去Oracle化過程中,最終選擇了MySQL。是怎樣的原因使你沒有去選擇NoSQL或是其它技術來作為提高性能優化方面的考慮呢?
主要考慮到以下這幾個方面,第一是因為MySQL已經是非常成熟的產品,而且也是經過大規模系統考驗的,所以它的穩定性,開發的便捷性還是比較有優勢的。從另外一個角度上來講,也能最大限度的保障歷史系統的遷移,這是第一個方面。此外,之所以沒有采用NoSQL主要基于以下幾個方面的考慮,第一由于市面上流行的NoSQL方案相對來說都比較年輕。然而對于淘寶商品庫來講,它是作為淘寶非常重要的庫,是不允許我們有絲毫閃失的,不能出現任何問題。第二點,現在流行的NoSQL方案,從程序的架構上來講,就是對傳統數據庫的過程進行了精簡。但是它的存儲、內存等問題其實還是存在的。只是解決問題的思路變得輕量。但是這些問題依舊在的。現在我們在數據庫層面,因為平常都是從引擎層面去開發,在原碼級別去做優化,甚至包括操作系統級的優化。所以我們可以很清楚的知道問題在哪里,應該解決什么問題,最終能達到什么樣的效果。那這樣做的好處就是我們既能解決問題,又能充分利用傳統數據庫的方便性以及穩定性。
3、優化過程中具體還做了哪些工作?
優化聽起來好像沒什么內容,但實際上我們做了很多的工作。首先要有明確的目標,我們的目標是什么,是為了提高性能還是提高安全性,還是提高其他的什么指標,這個目標要清晰和完整。第二點是測量,你不能說,我拍腦袋看到某某某,他怎么優化的,然后我也上去這樣照著優化,這不是我們做事的風格。我們要測量現在的瓶頸在哪里?我們的系統遇到了什么問題,這點我們會借助一些工具來實現。比如說測量CPU的使用,我們會非常精確的去測量I/O的使用,比如說在設備層面,I/O是怎么使用的,在軟件系統層面I/O是怎么使用的,在數據庫引擎層面I/O是怎么使用的。通過非常精細的測量,我們就能找出,對I/O使用不恰當的地方,然后就是要去解決這種問題,為什么會比設想的要多呢,或者為什么要比設想的要慢呢,我們會針對此類問題做理論上的分析,甚至會去翻翻源碼它到底是怎么實現的,這樣我們就可以比較有針對性將問題解決。
4、優化過程中有哪些創新和亮點?
這次有一個創新,用高速的SSD盤去做2級Cache,因為傳統的MySQL數據庫都是引擎里面發揮pool的功能,然后直接在軟件系統存儲。就是引擎里邊吐出來東西到那邊去,命不中東西從磁盤讀進去,由于是傳統的磁盤,所以它的尋道時間是非常長的。那它的I/O其實是不高的,但是吞吐量大。為了解決問題,我們采用一種叫PCI-E的Flash卡。這個卡的特點是,它是電子盤,所以它沒有尋道時間,隨機特性非常好,同時它的讀寫吞吐量非常高,讀能大概到1G,寫能達到幾百兆。采用其作為二級cache,數據從InnoDB引擎這邊出來,不到磁盤去,而是先寫到高速卡中。由于高速卡很快,它完成的I/O PS是微秒級的,幾十微秒就寫完了,然后傳統磁盤卻是十個毫秒級的。所以從數據庫引擎的角度來看,只需寫入幾十微妙就解決了。寫入數據開始是隨機的,隨機累計起來以后它就不是隨機的,我們通過把它排序,就可以使其變為順序的。然后我們再把這順序的數據利用磁盤的高吞吐量特點,由于數據庫半夜時候它可能會比較輕松。那這時候,把它導到磁盤中去,這樣就大大的提高整個系統的IO能力。這是比較大的一個創新點。