挨踢部落直播課堂第三期:國內首例談MySQL InnoDB memcached plugin實踐
原創【51CTO.com原創稿件】遠程控制技術背后有哪些數據需求?如何用緩存技術存儲實時數據?新緩存體系不穩定怎么辦?MySQL InnoDB memcached plugin出來挺久的了,網上還沒見到國內有把它用到生產環境的實例,我們特此邀請到向日葵技術總監張小峰老師做直播分享。
直播間:QQ群370892523、②群312724475、③群542270018、④群627843829
內容簡介:應用背景介紹、向日葵遠程控制技術的數據需求、緩存優化史、從memcached到ttserver、memcached、Ttserver、MySQL InnoDB memcached plugin等。
昨天看到群里有人說運維就是把程序員的代碼copy到服務器上,我覺得完全不是這樣的,至少在我們這里不是;只會上程序的運維是不合格的,他要能在現有程序上優化系統結構,能對開發提出當前的不足以及優化方案和為運維服務的開發需求。
(一)應用背景介紹
作為提供各種互聯網服務且具有海量用戶的的Oray,我們也一直在實踐各種新技術新架構;緩存方面我們從memcached、ttserver、redis等都有較多應用,其中redis我們的dns體系中有著很深度的集成使用;MySQL InnoDB memcached plugin出來挺久的了,網上還沒見到國內有把它用到生產環境的實例,我今天就給大家說下小白鼠體驗。
但很大一部分用戶使用我們的花生殼也就是為了遠程操作電腦,所以2010年,在我們埋頭苦干了1年多后推出了向日葵遠程控制產品,這個產品的基本功能就是讓用戶不需要關心IP端口等技術知識就可以遠程管理控制他的所有電腦,這個產品主要依賴以下技術:
通過關系型數據庫管理用戶主機清單;
使用長連接維持被控在線狀態;
P2P通信技術傳輸控制信號以及圖像信號;
優化的算法盡可能的降低用戶帶寬占用以及提高圖像質量;
其他周邊技術,如HTML5免插件遠程控制、遠程開機等。
客戶端、操作系統以及相關遠控技術問題我們今天先不探討,向日葵也不是一個簡單的C/S結構軟件,我們需要像聊天服務器那樣與客戶端進行實時交互,而客戶端在線量一直在兇猛的增長中,我們的系統以及運維和開發團隊也就不停的迭代并成長。
(二)向日葵遠程控制技術的數據需求
上面提到,向日葵使用關系型數據庫存貯某一個用戶擁有哪些主機,以及這些主機的具體相關信息;在此同時,我們也需要臨時存儲一些關鍵的實時數據:
主機鑒權信息
主機在線狀態
如何連接主機
其實剛發布向日葵的幾個月我們是把它們同時放在關系數據庫里的,那個時候主要考慮的也不是服務端的性能問題,而是整個系統跑通,只是我們的數據庫后來吃不消了,這一段經歷不長,說真的也沒啥好講的。
(三)緩存優化史
既然存在關系數據庫中不合適,我們就開始用各種緩存技術來存儲這種實時數據。
(三.1)從memcached到ttserver
(三.1.1)memcached
***代的主機狀態數據緩存化,我們把它放在了memcached,整個客戶端的登陸過程是這樣的(里頭略去了各種錯誤處理及異常以及各種附屬架構,比如負載均衡或者備份等):
把狀態等需要頻繁訪問的數據放到緩存后,這個大框架到現在也還基本上是這樣,API負責所有跟持久化DB的交互操作,長連接只負責跟memcached的通信,這樣也避免了我們的DB有過多角色參與讀寫;另外這個時候我們只有一臺memcached服務器,因為我們算過16G內存大約可以放上億的主機信息。
在經歷了兩次memcached崩潰后我們也崩潰了,memcached的數據是完全放在內存里的,崩潰后所有主機全部會變成不在線且只能通過重啟所有服務器解決,而重啟所有服務器意味著所有原先在線客戶端都得全部重新登陸一次,這個過程會極其漫長,以小時計的。
(三.1.2)ttserver
我們要改進了,順其自然的,我們想到了ttserver,ttserver可以在崩潰重啟后恢復數據且具備主備同步功能,而丟失那部分數據我們可以在客戶端登陸時從DB里自動恢復出來;
由于ttserver跟memcached通信協議上完全兼容,但為了避免全局性的災難,我們在完成多cache服務優化后,新系統很快就上線了。
新緩存體系的結構長這樣的:
完全堆疊式的設計,理論上也是可以***擴容的,但我們沒意識到ttserver幾個大問題:
ttserver不支持key過期的,需要開啟table database模式,并通過lua腳本的方式來實現,但該模式ttserver的運行性能相當差,并且在數據很大的時候出現不穩定的現象。
這個不穩定現象我們不湊巧也遇到了:由于它會自動把不頻繁讀寫的數據swap到磁盤,它倒不會像memcached那樣容易崩潰,但它會偶爾神經質似的卡;卡到什么程度呢:手工上去敲個get,大概要幾百ms才會得到結果;而我們對ttserver做了很多優化依舊于事無補。前兩次卡死,重啟能解決,但后來,我們不得不把它保存的文件徹底刪除才能恢復性能,這不又回到了memcached時代嗎?怎么辦?
(三.2)MySQL InnoDB memcached plugin
在我們出現ttserver危機的時候,已經沒有什么能讓我更絞盡腦汁的事情了,天天到各社區調研,某個偶然的機會,我看到了MySQL居然支持memcached插件,這真是個神奇的組合:
傳統關系型數據庫在大數據時代的性能與擴展,離不開內存與分布式這兩大主題。
在傳統的關系型數據庫中,Oracle的Timesten,SQL Server的Hekaton,都是選擇與內存數據庫相集合,但實際上卻少有突出的應用場景。而MySQL嵌入nosql ,在性能與管理、分析上達到互補,則是更為有意義的結合。
MySQL5.6.6后開始內嵌 memcached 的支持,在MySQL 5.7較新的版本性能大幅提升,有測試表明在48核只讀環境下QPS可以達到百萬以上。
借用下MySQL官方的結構圖:
我們先來看一下memcached plugin的安裝:
下載mysql5.7.17 源碼包 wget http://cdn.mysql.com//Downloads/MySQL-5.7/mysql-community-5.7.17-1.el6.src.rpm
因為是一個插件,開啟memcached plugin功能,需要在編譯安裝時添加:
-DWITH_INNODB_MEMCACHED=ON
安裝啟動后執行配置:
memcached plugin相關配置表:
innodb_memcache.config_options --配置分割符、引用符
innodb_memcache.cache_policies --根據需要設置緩存策略
innodb_memcache.containers --設置表結構:key、value大小,過期時間等
在mysql的配置文件my.cnf中通常需要設置以下參數(注意在啟動插件后配置,否則mysqld啟動報錯),主要是配置分配給memcached 的內存大小以及開啟寫binlog,如果需要指定其他端口,如11212 在loose-daemon_memcached_option參數添加 ' -p11212'
而daemon_memcached_r_batch_size、daemon_memcached_w_batch_size 默認為1,這里也建議設置為1:
MySQL memcached plugin 特點:
1.數據直接讀寫請求innodb存儲引擎,不需要經過SQL層,不需要進行解析編譯。
2.由MySQL buffer pool 管理內存緩存數據。
3.可以把數據存入多個表,可進行多列數據合并為一個value。
4.可以通過SQL對數據進行查詢、分析、維護。(在過期時間字段添加索引,通過mysql job進行過期數據刪除)
5.可以利用MySQL靈活的主從架構。
性能測試對比:
我們采用4核進行測試對比,MySQL memcached plugin 與 ttserver (hash模式)性能相當,QPS可以達到7萬/秒。比 ttserver (btree模式)高出3倍以上。
memaslap的測試存在一些缺陷,這里僅供大致參考:
實際上,在網絡延遲上,QPS性能將大打折扣,所以要將應用部署在同個內網以降低網絡延遲瓶頸,輕松應對每天上億次的QPS請求,在接近1萬/s的QPS并發訪問下依舊表現穩定。
以下是其中一個MySQL Memcahced 運行情況:
在我們一個很NB的DBA的設計和操控下,新架構上線還是比較順利的:
大家注意到,圖中多了一個角色,magent,在這次架構優化中,我們在應用和MySQL memcached中間加了一層magent,這東西大家百度下到處都有介紹,但原版其實是有不少bug的,比如buffer大小問題;加上這東西的好處:
1、通過對magent的改造,實現HA,當ma后端cache某一臺down掉后ma可以自動切換;系統管理員晚上終于可以安心的睡覺了。
2、MySQL memcached plugin 不支持multi get/set (在未來的版本中會支持)。通過magent解決。
3、由于mysql memcached plugin 存在一些bug,5.7.18做了一些修復,但不夠完善。借助magent便于控制和維護。
此架構優勢:
擴展性強。逐步提升應對高并發,采取多主架構,配合magent實現高可用。
我們做的優化:
MySQL 5.7.17 前的版本,不建議設置 daemon_memcached_r_batch_size 大于1,容易遭遇 bug 導致 MySQL Crashed。同時建議innodb_api_bk_commit_interval設置為稍大一點的值。默認為5。存在get會話的情況下,對 daemon_memcached 插件進行重啟,也會導致MySQL Crashed,重啟插件時要確保沒有其他會話。
禁止flush_all權限操作:
update cache_policies set flush_policy='disabled';
尾聲
其實上面說了那么多細節抑或還不夠細節的東西,都是圍繞著緩存架構的優化。在這么多年從事軟硬開發與架構設計的實際工作中,我深刻的體會到架構的重要性,不管多NB的代碼和算法,多NB的硬件,系統架構不好的話你的運行結果一樣糟糕。這里的架構不僅僅包含服務器層面以及系統運維上的,架構無處不在,從軟件架構到硬件架構,從網站架構到數據庫架構,從通信架構到服務整體架構,包括本文提到的緩存架構,甚至細化到C++開發層的class封裝與相互調用,都有著架構及其優化的存在。做任何一件部署與實際的開發前,我們都要有做好架構這個潛在意識,去考慮一個好的架構再動手構建,當然我們都不可避免的會踩到坑,不要害怕,持續改進就好。
正是這樣的態度下,我們又相繼推出無網遠控的硬件“向日葵控控”這樣創新性的產品。有了這一路走來的經驗,不管產品從軟件延伸硬件,我們也有自己的一套優化方案,有機會我們繼續分享。
Q&A
1、Q:PHP-watson-廣州::
A:向日葵-技術總監-上海:
redis單線程設計機制只能利用一個核,CPU利用度有限,我認為在高并發上比不上memcached,并且對數據比較大的情況性能不是很好,內存使用率管理上也沒有memcached優秀,value在大于1k之后性能下降明顯。
Q:python運維開發_howhy:
A:向日葵-技術總監-上海:
Q:python運維開發_howhy:
A:向日葵-技術總監-上海:
Q:數據庫管理-矢神-廣州:
A:向日葵-技術總監-上海:
【51CTO原創稿件,合作站點轉載請注明原文作者和出處為51CTO.com】