MySQL InnoDB Memcached Plugin在Oray公司的实践
1、應(yīng)用背景介紹
我所在職的Oray是一家提供各種互聯(lián)網(wǎng)服務(wù)且具有海量用戶的企業(yè),我們也一直在實踐各種新技術(shù)新架構(gòu);緩存方面,我們從memcached、ttserver、redis等都有較多應(yīng)用,其中redis在我們的dns體系中有著很深度的集成使用;MySQL InnoDB memcached plugin出來有挺長時間了,網(wǎng)上還沒見到國內(nèi)有把它用到生產(chǎn)環(huán)境的實例,我今天就給大家說下小白鼠體驗。
創(chuàng)始產(chǎn)品花生殼是個簡單的動態(tài)域名產(chǎn)品,用戶可以用它發(fā)布自己的各類服務(wù),從網(wǎng)站到各類專用數(shù)據(jù)連接;就算在中國互聯(lián)網(wǎng)環(huán)境如此殘酷同時IPv4資源在不斷萎縮的今天,這個產(chǎn)品還在不斷的發(fā)展壯大。雖然表面看起來是個簡單的工具軟件,但它為中國一代代的互聯(lián)網(wǎng)人解決了很多基礎(chǔ)的連接問題!
但很大一部分用戶使用我們的花生殼也就是為了遠(yuǎn)程操作電腦,所以2010年,在我們埋頭苦干了1年多后推出了向日葵遠(yuǎn)程控制產(chǎn)品,這個產(chǎn)品的基本功能就是讓用戶不需要關(guān)心IP端口等技術(shù)知識就可以遠(yuǎn)程管理控制他的所有電腦,這個產(chǎn)品主要依賴以下技術(shù):
1、通過關(guān)系型數(shù)據(jù)庫管理用戶主機(jī)清單;
2、使用長連接維持被控在線狀態(tài);
3、P2P通信技術(shù)傳輸控制信號以及圖像信號;
4、優(yōu)化的算法盡可能的降低用戶帶寬占用以及提高圖像質(zhì)量;
5、其他周邊技術(shù),如HTML5免插件遠(yuǎn)程控制、遠(yuǎn)程開機(jī)等。
客戶端、操作系統(tǒng)以及相關(guān)遠(yuǎn)控技術(shù)問題我們今天先不探討,向日葵也不是一個簡單的C/S結(jié)構(gòu)軟件,我們需要像聊天服務(wù)器那樣與客戶端進(jìn)行實時交互,而客戶端在線量一直在兇猛的增長中,我們的系統(tǒng)以及運(yùn)維和開發(fā)團(tuán)隊也就不停的迭代并成長。
2、向日葵遠(yuǎn)程控制技術(shù)的數(shù)據(jù)需求
上面提到,向日葵使用關(guān)系型數(shù)據(jù)庫存貯某一個用戶擁有哪些主機(jī),以及這些主機(jī)的具體相關(guān)信息;在此同時,我們也需要臨時存儲一些關(guān)鍵的實時數(shù)據(jù):
1、 主機(jī)鑒權(quán)信息?
2、 主機(jī)在線狀態(tài)?
3、 如何連接主機(jī)
從這些數(shù)據(jù)內(nèi)容可以看出它們是實時產(chǎn)生且需要多方可以直接訪問的,向日葵的被控端可能登陸在全國各地任意一臺長連接服務(wù)器上,而試圖過來訪問這個被控的主控端則需要通過API服務(wù)實時讀取被控的狀態(tài)信息,以及讀取這個被控通過哪個長連接服務(wù)能被訪問到;整個向日葵有多少臺主機(jī),這個實時數(shù)據(jù)就有多少條;每條數(shù)據(jù)大概也就幾百個字節(jié),目前每組服務(wù)數(shù)百萬條記錄。這些數(shù)據(jù)的更新頻繁度也非常高,因為那么大量的被控端總是在不停的上下線,目前峰值的時候QPS可以達(dá)到萬次。
其實剛發(fā)布向日葵的幾個月我們是把它們同時放在關(guān)系數(shù)據(jù)庫里的,那個時候主要考慮的也不是服務(wù)端的性能問題,而是整個系統(tǒng)跑通,只是我們的數(shù)據(jù)庫后來吃不消了,很快我們就走上了漫長緩存優(yōu)化之路。
3、緩存優(yōu)化史
既然存在關(guān)系數(shù)據(jù)庫中不合適,我們就開始用各種緩存技術(shù)來存儲這種實時數(shù)據(jù)。
3.1 從memcached到ttserver
3.1.1 memcached
第一代的主機(jī)狀態(tài)數(shù)據(jù)緩存化,我們把它放在了memcached,整個客戶端的登陸過程是這樣的(里頭略去了各種錯誤處理及異常以及各種附屬架構(gòu),比如負(fù)載均衡或者備份等):
把狀態(tài)等需要頻繁訪問的數(shù)據(jù)放到緩存后,這個大框架到現(xiàn)在也還基本上是這樣,API負(fù)責(zé)所有跟持久化DB的交互操作,長連接只負(fù)責(zé)跟memcached的通信,這樣也避免了我們的DB有過多角色參與讀寫;另外這個時候我們只有一臺memcached服務(wù)器,因為我們算過16G內(nèi)存大約可以放上億的主機(jī)信息。
但這些數(shù)據(jù)跑memcached真的合適嗎?
memcached剛剛上線的很長一段時間內(nèi)系統(tǒng)運(yùn)行還是很完美的,速度也完全夠用,因為數(shù)據(jù)量以及QPS對memcached來說也還不太大,但后來我們的向日葵用戶量發(fā)展迅速,主機(jī)和在線量都在急劇的上漲;而由于memcached并沒有主從同步之類的機(jī)制,任一個主機(jī)的緩存信息只能存在一個memcached中,而一個memcached其實也就是一個進(jìn)程,我們沒法保證這個進(jìn)程永遠(yuǎn)活著,它會崩潰,機(jī)器也會死掉,網(wǎng)絡(luò)也會死掉。
在經(jīng)歷了兩次memcached崩潰后我們也崩潰了,memcached的數(shù)據(jù)是完全放在內(nèi)存里的,崩潰后存在其中的所有主機(jī)全部會變成不在線且只能通過重啟所有服務(wù)器解決,而重啟所有服務(wù)器意味著所有原先在線客戶端都得全部重新登陸一次,這個過程會極其漫長,以小時計的。
3.1.2 ttserver
我們要改進(jìn)了,順其自然的,我們想到了ttserver,ttserver可以在崩潰重啟后恢復(fù)數(shù)據(jù)且具備主備同步功能,而丟失那部分?jǐn)?shù)據(jù)我們可以在客戶端登陸時從DB里自動恢復(fù)出來;
由于ttserver跟memcached通信協(xié)議上完全兼容,但為了避免全局性的災(zāi)難,我們在完成多cache服務(wù)優(yōu)化后,新系統(tǒng)很快就上線了。
新緩存體系的結(jié)構(gòu)長這樣的:
完全堆疊式的設(shè)計,理論上也是可以無限擴(kuò)容的,但我們沒意識到ttserver幾個大問題:
ttserver不支持key過期的,需要開啟table database模式,并通過lua腳本的方式來實現(xiàn),但該模式ttserver的運(yùn)行性能相當(dāng)差,并且在數(shù)據(jù)很大的時候出現(xiàn)不穩(wěn)定的現(xiàn)象。
這個不穩(wěn)定現(xiàn)象我們不湊巧也遇到了:由于它會自動把不頻繁讀寫的數(shù)據(jù)swap到磁盤,它倒不會像memcached那樣容易崩潰,但它會偶爾神經(jīng)質(zhì)似的卡;卡到什么程度呢:手工上去敲個get,大概要幾百ms才會得到結(jié)果;而我們對ttserver做了很多優(yōu)化依舊于事無補(bǔ)。前兩次卡死,重啟能解決,但后來,我們不得不把它保存的文件徹底刪除才能恢復(fù)性能,這不又回到了memcached時代嗎?怎么辦?
3.2 MySQL InnoDB memcached plugin
在我們出現(xiàn)ttserver危機(jī)的時候,已經(jīng)沒有什么能讓我更絞盡腦汁的事情了,天天到各社區(qū)調(diào)研,某個偶然的機(jī)會,我看到了MySQL居然支持memcached插件,這真是個神奇的組合:
傳統(tǒng)關(guān)系型數(shù)據(jù)庫在大數(shù)據(jù)時代的性能與擴(kuò)展,離不開內(nèi)存與分布式這兩大主題。
在傳統(tǒng)的關(guān)系型數(shù)據(jù)庫中,Oracle的Timesten,SQL Server的Hekaton,都是選擇與內(nèi)存數(shù)據(jù)庫相集合,但實際上卻少有突出的應(yīng)用場景。而MySQL嵌入nosql ,在性能與管理、分析上達(dá)到互補(bǔ),則是更為有意義的結(jié)合。
MySQL5.6.6后開始內(nèi)嵌 memcached 的支持,在MySQL 5.7較新的版本性能大幅提升,有測試表明在48核只讀環(huán)境下QPS可以達(dá)到百萬以上。
借用下MySQL官方的結(jié)構(gòu)圖:
我們先來看一下memcached plugin的安裝:?
下載mysql5.7.17 源碼包:
因為是一個插件,開啟memcached plugin功能,需要在編譯安裝時添加:
-DWITH_INNODB_MEMCACHED=ONcmake . \ -DCMAKE_INSTALL_PREFIX=/usr/local/mysql5.7/ \-DMYSQL_DATADIR=/data1/ \-DWITH_INNOBASE_STORAGE_ENGINE=1 \-DWITH_PARTITION_STORAGE_ENGINE=1 \-DWITH_INNODB_MEMCACHED=ON \-DENABLED_LOCAL_INFILE=1 \-DWITH_READLINE=1 \-DMYSQL_UNIX_ADDR=/tmp/mysql5.7.sock \-DMYSQL_TCP_PORT=3306 \-DEXTRA_CHARSETS=all \-DWITH_EMBEDDED_SERVER=1 \-DWITH_DEBUG=1 \-DWITH_BOOST=../boost_1_59_0安裝啟動后執(zhí)行配置:
mysql> source /usr/local/mysql5.7/share/innodb_memcached_config.sql 啟動memcached插件: mysql> install plugin daemon_memcached soname "libmemcached.so"; 關(guān)閉memcached插件: mysql> uninstall plugin daemon_memcached;memcached plugin相關(guān)配置表:
innodb_memcache.config_options ? ? ?--配置分割符、引用符innodb_memcache.from cache_policies ? ? --根據(jù)需要設(shè)置緩存策略innodb_memcache.containers ? ? ?--設(shè)置表結(jié)構(gòu):key、value大小,過期時間等在mysql的配置文件my.cnf中通常需要設(shè)置以下參數(shù)(注意在啟動插件后配置,否則mysqld啟動報錯),主要是配置分配給memcached 的內(nèi)存大小以及開啟寫binlog,如果需要指定其他端口,如11212 在loose-daemon_memcached_option參數(shù)添加 ’ -p11212’?
而daemon_memcached_r_batch_size、daemon_memcached_w_batch_size 默認(rèn)為1,這里也建議設(shè)置為1:
MySQL memcached plugin 特點:
1.數(shù)據(jù)直接讀寫請求innodb存儲引擎,不需要經(jīng)過SQL層,不需要進(jìn)行解析編譯。
2.由MySQL buffer pool 管理內(nèi)存緩存數(shù)據(jù)。
3.可以把數(shù)據(jù)存入多個表,可進(jìn)行多列數(shù)據(jù)合并為一個value。
4.可以通過SQL對數(shù)據(jù)進(jìn)行查詢、分析、維護(hù)。(在過期時間字段添加索引,通過mysql job進(jìn)行過期數(shù)據(jù)刪除)
5.可以利用MySQL靈活的主從架構(gòu)。
性能測試對比:
我們采用4核進(jìn)行測試對比,MySQL memcached plugin 與 ttserver (hash模式)性能相當(dāng),QPS可以達(dá)到7萬/秒。比 ttserver (btree模式)高出3倍以上。
memaslap的測試存在一些缺陷,這里僅供大致參考:
實際上,在網(wǎng)絡(luò)延遲上,QPS性能將大打折扣,所以要將應(yīng)用部署在同個內(nèi)網(wǎng)以降低網(wǎng)絡(luò)延遲瓶頸,輕松應(yīng)對每天上億次的QPS請求,在接近1萬/s的QPS并發(fā)訪問下依舊表現(xiàn)穩(wěn)定。
以下是其中一個MySQL Memcahced 運(yùn)行情況:
在我們DBA的設(shè)計和操控下,新架構(gòu)上線還是比較順利的:
圖中的magent:
在這次架構(gòu)優(yōu)化中,我們在應(yīng)用和MySQL memcached中間加了一層magent,這東西大家百度下到處都有介紹,但原版其實是有不少bug的,比如buffer大小問題;加上這東西的好處:
1、通過對magent的改造,實現(xiàn)HA,當(dāng)ma后端cache某一臺down掉后ma可以自動切換;系統(tǒng)管理員晚上終于可以安心的睡覺了。
2、MySQL memcached plugin 不支持multi get/set (在未來的版本中會支持)。通過magent解決。
3、由于mysql memcached plugin 存在一些bug,5.7.18做了一些修復(fù),但不夠完善。借助magent便于控制和維護(hù)。
此架構(gòu)優(yōu)勢:
擴(kuò)展性強(qiáng)。逐步提升應(yīng)對高并發(fā),采取多主架構(gòu),配合magent實現(xiàn)高可用。
我們做的優(yōu)化:
MySQL 5.7.17 前的版本,不建議設(shè)置 daemon_memcached_r_batch_size 大于1,容易遭遇 bug 導(dǎo)致 MySQL Crashed。同時建議innodb_api_bk_commit_interval設(shè)置為稍大一點的值。默認(rèn)為5。存在get會話的情況下,對 daemon_memcached 插件進(jìn)行重啟,也會導(dǎo)致MySQL Crashed,重啟插件時要確保沒有其他會話。
禁止flush_all權(quán)限操作:
update cache_policies set flush_policy=’disabled’;
總結(jié)
其實上面說了那么多細(xì)節(jié)抑或還不夠細(xì)節(jié)的東西,都是圍繞著緩存架構(gòu)的優(yōu)化。在這么多年從事軟硬開發(fā)與架構(gòu)設(shè)計的實際工作中,我深刻的體會到架構(gòu)的重要性,不管代碼、算法、硬件多好,系統(tǒng)架構(gòu)不好的話,你的運(yùn)行結(jié)果一樣糟糕。這里的架構(gòu)不僅僅包含服務(wù)器層面以及系統(tǒng)運(yùn)維上的,架構(gòu)無處不在,從軟件架構(gòu)到硬件架構(gòu),從網(wǎng)站架構(gòu)到數(shù)據(jù)庫架構(gòu),從通信架構(gòu)到服務(wù)整體架構(gòu),包括本文提到的緩存架構(gòu),甚至細(xì)化到C++開發(fā)層的class封裝與相互調(diào)用,都有著架構(gòu)及其優(yōu)化的存在。做任何一件部署與實際的開發(fā)前,我們都要有做好架構(gòu)這個潛在意識,去考慮一個好的架構(gòu)再動手構(gòu)建,當(dāng)然我們都不可避免的會踩到坑,不要害怕,持續(xù)改進(jìn)就好。
正是這樣的態(tài)度下,我們又相繼推出以物理性遠(yuǎn)程的“向日葵控控”這樣創(chuàng)新性的硬件產(chǎn)品。有了這一路走來的經(jīng)驗,不管產(chǎn)品從軟件延伸硬件,我們也有自己的一套優(yōu)化方案,有機(jī)會我們繼續(xù)分享。
作者簡介:張小峰,Oray技術(shù)總監(jiān),專注于高性能網(wǎng)絡(luò)服務(wù)架構(gòu),15年C++網(wǎng)絡(luò)應(yīng)用開發(fā)和團(tuán)隊管理經(jīng)驗;在DNS架構(gòu)、C++網(wǎng)絡(luò)通信技術(shù)、各操作系統(tǒng)API交互、圖像處理、加密算法等領(lǐng)域都有著深入的研究;在Oray技術(shù)團(tuán)隊中負(fù)責(zé)所有產(chǎn)品的網(wǎng)絡(luò)服務(wù)及圖像底層架構(gòu)設(shè)計與開發(fā);帶領(lǐng)團(tuán)隊先后研發(fā)了多款如花生殼、向日葵遠(yuǎn)程控制軟件等多款千萬量級的產(chǎn)品,從事其中的結(jié)構(gòu)設(shè)計與關(guān)鍵技術(shù)攻關(guān),是Oray技術(shù)團(tuán)隊的領(lǐng)頭羊與靈魂人物。
全天候聚焦IaaS/PaaS/SaaS最新技術(shù)動態(tài),深度挖掘技術(shù)大咖第一手實踐,及時推送云行業(yè)重大新聞,一鍵關(guān)注,總覽國內(nèi)外云計算大勢!?
總結(jié)
以上是生活随笔為你收集整理的MySQL InnoDB Memcached Plugin在Oray公司的实践的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 你我贷一般是晚上八点放款吗 晚上时间人工
- 下一篇: 杭州热电上演天地板 涨停到跌停令人心惊