NoSQL小故事:?jiǎn)畏?wù)器如何應(yīng)付每秒75萬(wàn)次查詢
原創(chuàng)【51CTO經(jīng)典譯文】大多數(shù)大規(guī)模Web應(yīng)用程序都使用MySQL+Memcached架構(gòu),其中許多應(yīng)用也同時(shí)使用了NoSQL數(shù)據(jù)庫(kù),如TokyoCabinet/Tyrant,也有一些人全部放棄MySQL,轉(zhuǎn)投NoSQL的懷抱,曾經(jīng)有人將這稱為NoSQL運(yùn)動(dòng),因?yàn)镹oSQL數(shù)據(jù)庫(kù)在處理一些簡(jiǎn)單訪問模式,如主鍵查找時(shí),比MySQL的表現(xiàn)更好,大多數(shù)Web應(yīng)用程序的查詢都很簡(jiǎn)單,因此這看上去是一個(gè)很合理的決定。
和許多其它大規(guī)模網(wǎng)站一樣,我們的DeNA(我于2010年8月離開Oracle,加盟了日本最大的社交游戲平臺(tái)提供商DeNA)多年來(lái)都存在類似的問題,但我們得出了不同的結(jié)論,最終我們?nèi)渴褂昧薓ySQL,當(dāng)然一如既往地使用Memcached作為前端緩存(如預(yù)處理的HTML,計(jì)數(shù)/摘要信息),但我們沒有使用Memcached緩存數(shù)據(jù)行,我們也沒有使用NoSQL,因?yàn)槲覀儚腗ySQL獲得的性能比其它NoSQL產(chǎn)品更好,在我們的基準(zhǔn)測(cè)試中,我們?cè)谝慌_(tái)普通的MySQL/InnoDB 5.1服務(wù)器上獲得了750000+QPS的成績(jī),在生產(chǎn)環(huán)境中的性能更優(yōu)秀。(QPS每秒查詢率,每秒查詢率QPS是對(duì)一個(gè)特定的查詢服務(wù)器在規(guī)定時(shí)間內(nèi)所處理流量多少的衡量標(biāo)準(zhǔn),在因特網(wǎng)上,作為域名系統(tǒng)服務(wù)器的機(jī)器的性能經(jīng)常用每秒查詢率來(lái)衡量。)
也許你不相信這個(gè)成績(jī),但我說(shuō)的是真的,在這篇文章中,我將分享一下我們是如何做到的。
SQL主鍵查詢真得能很快嗎?
每秒你可以運(yùn)行多少次主鍵查詢?DeNA的應(yīng)用程序需要執(zhí)行大量的主鍵查詢,如通過(guò)用戶id獲取用戶信息,通過(guò)日記id獲取日志信息,Memcached和NoSQL都能很好地適應(yīng)這種需求,當(dāng)你運(yùn)行簡(jiǎn)單的多線程“memcached get”基準(zhǔn)測(cè)試時(shí),每秒大約可以執(zhí)行400000+次get操作,即使Memcached客戶端位于遠(yuǎn)程服務(wù)器上,當(dāng)我使用最新的libmemcached和memcached測(cè)試時(shí),在一臺(tái)2.5GHz 8核Nehalem處理器,四個(gè)Broadcom千兆以太網(wǎng)卡的服務(wù)器上,測(cè)試成績(jī)是每秒執(zhí)行420000次get操作。
MySQL執(zhí)行主鍵查詢需要多長(zhǎng)時(shí)間?通過(guò)基準(zhǔn)測(cè)試很容易找到答案,只需要從sysbench,super-smack和mysqlslap等運(yùn)行并行查詢即可。
- [matsunobu@host ~]$ mysqlslap --query="select user_name,..
- from test.user where user_id=1" \
- --number-of-queries=10000000 --concurrency=30 --host=xxx –uroot
你可以使用下面的命令檢查每秒讀取了多少InnoDB行:
- [matsunobu@host ~]$ mysqladmin extended-status -i 1 -r -uroot \
- | grep -e "Com_select"
- ...
- | Com_select | 107069 |
- | Com_select | 108873 |
- | Com_select | 108921 |
- | Com_select | 109511 |
- | Com_select | 108084 |
- | Com_select | 108483 |
- | Com_select | 108115 |
- ...
每秒有100000+次查詢似乎還不錯(cuò),但卻遠(yuǎn)遠(yuǎn)低于Memcached的結(jié)果,MySQL實(shí)際上做了些什么?從vmstat輸出可以看出,%user和%system都很高。
- [matsunobu@host ~]$ vmstat 1
- r b swpd free buff cache in cs us sy id wa st
- 23 0 0 963004 224216 29937708 58242 163470 59 28 12 0 0
- 24 0 0 963312 224216 29937708 57725 164855 59 28 13 0 0
- 19 0 0 963232 224216 29937708 58127 164196 60 28 12 0 0
- 16 0 0 963260 224216 29937708 58021 165275 60 28 12 0 0
- 20 0 0 963308 224216 29937708 57865 165041 60 28 12 0 0
Oprofile輸出顯示了更多關(guān)于CPU資源消耗的情況。
- samples % app name symbol name
- 259130 4.5199 mysqld MYSQLparse(void*)
- 196841 3.4334 mysqld my_pthread_fastmutex_lock
- 106439 1.8566 libc-2.5.so _int_malloc
- 94583 1.6498 bnx2 /bnx2
- 84550 1.4748 ha_innodb_plugin.so.0.0.0 ut_delay
- 67945 1.1851 mysqld _ZL20make_join_statistics
- P4JOINP10TABLE_LISTP4ItemP16st_dynamic_array
- 63435 1.1065 mysqld JOIN::optimize()
- 55825 0.9737 vmlinux wakeup_stack_begin
- 55054 0.9603 mysqld MYSQLlex(void*, void*)
- 50833 0.8867 libpthread-2.5.so pthread_mutex_trylock
- 49602 0.8652 ha_innodb_plugin.so.0.0.0 row_search_for_mysql
- 47518 0.8288 libc-2.5.so memcpy
- 46957 0.8190 vmlinux .text.elf_core_dump
- 46499 0.8111 libc-2.5.so malloc
在SQL解析階段調(diào)用了MYSQLparse()和MYSQLlex(),在查詢優(yōu)化階段調(diào)用了make_join_statistics()和JOIN::optimize(),這些都是SQL開銷,很明顯,性能下降主要是由SQL層,而不是InnoDB(存儲(chǔ))層造成的,MySQL做了很多Memcached/NoSQL不需要做的事情,如:
- 解析SQL語(yǔ)句
- 打開,鎖住表
- 創(chuàng)建SQL執(zhí)行計(jì)劃
- 解鎖
- 關(guān)閉表
MySQL也做了許多并發(fā)控制,例如,在發(fā)送/接收網(wǎng)絡(luò)數(shù)據(jù)包時(shí)多次調(diào)用了fcntl(),全局互斥,如LOCK_open,LOCK_thread_count很頻繁地創(chuàng)建/釋放,這就是為什么oprofile輸出中my_pthread_fastmutex_lock()排名第二,%system也不小的原因。
MySQL開發(fā)團(tuán)隊(duì)和外部社區(qū)都知道并發(fā)問題,有些問題在5.5中已經(jīng)得到解決,我很高興地看到,大量的修復(fù)工作已經(jīng)完成,但同樣重要的是%user也達(dá)到了60%,互斥競(jìng)爭(zhēng)導(dǎo)致%system上升,而不是%user上升。雖然MySQL中的所有互斥問題都得到了解決,但不要指望每秒超過(guò)30萬(wàn)次查詢。
你可能聽說(shuō)過(guò)HANDLER語(yǔ)句,遺憾的是,HANDLER語(yǔ)句對(duì)提高吞吐量并不會(huì)有太多幫助,因?yàn)椴樵兘馕觯蜷_/關(guān)閉表等操作仍然是需要的。
CPU效率對(duì)內(nèi)存中的工作負(fù)載非常重要
如果內(nèi)存中沒有合適的活動(dòng)數(shù)據(jù),SQL開銷相對(duì)來(lái)說(shuō)可以忽略不計(jì),很簡(jiǎn)單,因?yàn)榇疟PI/O成本是非常高的,在這種情況下,我們不需要太關(guān)心SQL成本。
但在我們的熱點(diǎn)MySQL服務(wù)器上,幾乎所有數(shù)據(jù)都裝入到內(nèi)存中了,它們完全變成CPU限制,分析結(jié)果和上面類似:SQL層消耗了大部分資源。我們需要執(zhí)行大量的主鍵查詢(如SELECT x FROM t WHERE id=?)或限制范圍的掃描,即使70-80%的查詢是對(duì)相同表的簡(jiǎn)單主鍵查詢(不同的只是Where子句中的值),每次MySQL都要解析/打開/鎖住/解鎖/關(guān)閉,這對(duì)我們來(lái)說(shuō)效率是很低的。
#p#
你聽說(shuō)過(guò)NDBAPI嗎?
在MySQL的SQL層有什么好的解決辦法可以減少CPU資源爭(zhēng)用嗎?如果你使用的是MySQL集群,NDBAPI可能是最好的解決方案,我在MySQL/Sun/Oracle擔(dān)任顧問時(shí),我看到許多客戶對(duì)SQL節(jié)點(diǎn)+NDB的性能表現(xiàn)很失望,當(dāng)使用NDBAPI客戶端性能提高N倍后,他們高興極了,你可以在MySQL集群中同時(shí)使用NDBAPI和SQL,建議頻繁訪問模式使用NDBAPI,即席查詢或非頻繁模式使用SQL+MySQL+NDB。
這正是我們想要的,我們希望更快速地訪問API,我們也希望對(duì)即席查詢或復(fù)雜查詢使用SQL,但DeNA使用的是InnoDB,和許多其它Web服務(wù)一樣,切換到NDB不是小事,嵌入式InnoDB不支持SQL也不沒有網(wǎng)絡(luò)接口,因此它不適合我們。
HandlerSocket插件,一個(gè)懂NoSQL網(wǎng)絡(luò)協(xié)議的MySQL插件
我們認(rèn)為最好的辦法是在MySQL內(nèi)部實(shí)現(xiàn)一個(gè)NoSQL網(wǎng)絡(luò)服務(wù)器,也就是說(shuō),寫一個(gè)網(wǎng)絡(luò)服務(wù)器作為MySQL插件(守護(hù)進(jìn)程插件)監(jiān)聽指定端口,接受NoSQL協(xié)議/API,然后使用MySQL內(nèi)部存儲(chǔ)引擎API直接訪問InnoDB。這個(gè)方法和NDBAPI類似,但它可以和InnoDB交互,這個(gè)概念最初是由Kazuho Oku去年在Cybozu實(shí)驗(yàn)室提出并創(chuàng)建了原型,他編寫了使用memcached協(xié)議的MyCached UDF,我的同事Akira Higuchi實(shí)現(xiàn)了另一個(gè)插件:HandlerSocket,下圖顯示了HandlerSocket可以做的事情。
Hanldersocket是一個(gè)MySQL守護(hù)進(jìn)程插件,它讓應(yīng)用程序可以將MySQL當(dāng)NoSQL使,Hanldersocket的主要目的是與存儲(chǔ)引擎,如InnoDB交互,而不需要SQL相關(guān)的開銷。訪問MySQL表時(shí),Hanldersocket仍然需要打開和關(guān)閉表,但不是每次訪問都要求打開和關(guān)閉,因此減少了互斥爭(zhēng)奪,極大地提高了系統(tǒng)性能,當(dāng)流量變小時(shí),Hanldersocket會(huì)關(guān)閉表,因此它永遠(yuǎn)不會(huì)阻止管理命令(DDL)。
它和使用MySQL+Memcached有什么不同?比較圖1和圖2,我想你會(huì)發(fā)現(xiàn)很多差異的,圖2顯示了典型的Memcached和MySQL用法,Memcached用于緩存數(shù)據(jù)庫(kù)記錄,這是因?yàn)镸emcached的get操作比MySQL的內(nèi)存中/磁盤上的主鍵查詢要快很多,如果HandlerSocket的查詢速度和Memcached一樣快,我們就不用Memcached緩存記錄了。
圖 2 MySQL+Memcached的常見架構(gòu)模式
使用HandlerSocket
舉一個(gè)例子,假設(shè)有一個(gè)“user”表,我們需要通過(guò)user_id獲取用戶信息。
- CREATE TABLE user (
- user_id INT UNSIGNED PRIMARY KEY,
- user_name VARCHAR(50),
- user_email VARCHAR(255),
- created DATETIME
- ) ENGINE=InnoDB;
在MySQL中,可以通過(guò)SELECT語(yǔ)句獲取用戶信息。
- mysql> SELECT user_name, user_email, created FROM user WHERE user_id=101;
- +---------------+-----------------------+---------------------+
- | user_name | user_email | created |
- +---------------+-----------------------+---------------------+
- | Yukari Takeba | yukari.takeba@dena.jp | 2010-02-03 11:22:33 |
- +---------------+-----------------------+---------------------+
- 1 row in set (0.00 sec)
下面我們來(lái)看看如何使用HandlerSocket完成同樣的事情。
首先需要安裝HandlerSocket,具體安裝步驟請(qǐng)參考這里,基本步驟如下:
1、從這里下載HandlerSocket;
2、生成HandlerSocket(客戶端和服務(wù)器端);
- ./configure --with-mysql-source=... --with-mysql-bindir=... ; make; make install
3、安裝HandlerSocket
- mysql> INSTALL PLUGIN 'HandlerSocket' soname 'HandlerSocket.so';
因?yàn)镠andlerSocket是MySQL插件,你可以象使用其它插件,如InnoDB、Q4M和Spider插件那樣使用它,也就是說(shuō),你不需要修改MySQL源代碼,MySQL最好是5.1或更高版本,生成HandlerSocket時(shí)需要MySQL源代碼和MySQL庫(kù)。
接下來(lái)需要編寫HandlerSocket客戶端代碼,我們提供了C++和Perl客戶端庫(kù),下面是一個(gè)簡(jiǎn)單的Perl代碼示例,它通過(guò)主鍵查詢獲取一行記錄。
- #!/usr/bin/perl
- use strict;
- use warnings;
- use Net::HandlerSocket;
- #1. establishing a connection
- my $args = { host => 'ip_to_remote_host', port => 9998 };
- my $hs = new Net::HandlerSocket($args);
- #2. initializing an index so that we can use in main logics.
- # MySQL tables will be opened here (if not opened)
- my $res = $hs->open_index(0, 'test', 'user', 'PRIMARY',
- 'user_name,user_email,created');
- die $hs->get_error() if $res != 0;
- #3. main logic
- #fetching rows by id
- #execute_single (index id, cond, cond value, max rows, offset)
- $res = $hs->execute_single(0, '=', [ '101' ], 1, 0);
- die $hs->get_error() if $res->[0] != 0;
- shift(@$res);
- for (my $row = 0; $row < 1; ++$row) {
- my $user_name= $res->[$row + 0];
- my $user_email= $res->[$row + 1];
- my $created= $res->[$row + 2];
- print "$user_name\t$user_email\t$created\n";
- }
- #4. closing the connection
- $hs->close();
上面的代碼從user表查詢user_name,user_email和created列,查詢條件是user_id=101,因此查詢結(jié)果和前面的SELECT語(yǔ)句一樣。
- [matsunobu@host ~]$ perl sample.pl
- Yukari Takeba yukari.takeba@dena.jp 2010-02-03 11:22:33
對(duì)于大多數(shù)Web應(yīng)用程序而言,保持輕量級(jí)的HandlerSocket連接是一個(gè)很好的做法(持續(xù)連接),讓大量的請(qǐng)求可以集中于主要邏輯(上面代碼中的#3部分)。
HandlerSocket協(xié)議是一個(gè)小尺寸的基于文本的協(xié)議,和Memcached文本協(xié)議類似,你可以使用telnet通過(guò)HandlerSocket獲取數(shù)據(jù)。
- [matsunobu@host ~]$ telnet 192.168.1.2 9998
- Trying 192.168.1.2...
- Connected to xxx.dena.jp (192.168.1.2).
- Escape character is '^]'.
- P 0 test user PRIMARY user_name,user_email,created
- 0 1
- 0 = 1 101
- 0 3 Yukari Takeba yukari.takeba@dena.jp 2010-02-03 11:22:33
綠色表示請(qǐng)求數(shù)據(jù)包,字段必須用Tab鍵分隔。
基準(zhǔn)測(cè)試
現(xiàn)在是時(shí)候展示我們的基準(zhǔn)測(cè)試結(jié)果了,我使用上面的user表,從多線程遠(yuǎn)程客戶端測(cè)試了執(zhí)行主鍵查詢操作的次數(shù),所有用戶數(shù)據(jù)都裝入到內(nèi)存中(我測(cè)試了100萬(wàn)行),我也用類似的數(shù)據(jù)測(cè)試了Memcached(我使用libmemcached和memcached_get()獲取用戶數(shù)據(jù)),在MySQL SQL測(cè)試中,我使用了一個(gè)傳統(tǒng)的SELECT語(yǔ)句:“SELECT user_name, user_email, created FROM user WHERE user_id=?”,Memcached和HandlerSocket客戶端代碼均使用C/C++編寫,所有客戶端程序都位于遠(yuǎn)程主機(jī)上,通過(guò)TCP/IP連接到MySQL/Memcached。最高的吞吐量情況如下:
- approx qps server CPU util
- MySQL via SQL 105,000 %us 60% %sy 28%
- memcached 420,000 %us 8% %sy 88%
- MySQL via HandlerSocket 750,000 %us 45% %sy 53%
通過(guò)HandlerSocket比傳統(tǒng)的SQL語(yǔ)句吞吐量要高出7.5倍,這說(shuō)明了MySQL的SQL層是非常耗資源的,如果能跳過(guò)這一層性能肯定會(huì)大大提升。有趣的是,MySQL使用HandlerSocket時(shí)的速度比使用Memcached快178%,并且Memcached消耗的%system資源也更多,雖然Memcached是一個(gè)很好的產(chǎn)品,但仍然有優(yōu)化的空間。
下面是oprofile輸出內(nèi)容,是在MySQL HandlerSocket測(cè)試期間收集到的,在核心操作,如網(wǎng)絡(luò)數(shù)據(jù)包處理,獲取數(shù)據(jù)等的CPU資源消耗(bnx2是一個(gè)網(wǎng)絡(luò)設(shè)備驅(qū)動(dòng)程序)。
- samples % app name symbol name
- 984785 5.9118 bnx2 /bnx2
- 847486 5.0876 ha_innodb_plugin.so.0.0.0 ut_delay
- 545303 3.2735 ha_innodb_plugin.so.0.0.0 btr_search_guess_on_hash
- 317570 1.9064 ha_innodb_plugin.so.0.0.0 row_search_for_mysql
- 298271 1.7906 vmlinux tcp_ack
- 291739 1.7513 libc-2.5.so vfprintf
- 264704 1.5891 vmlinux .text.super_90_sync
- 248546 1.4921 vmlinux blk_recount_segments
- 244474 1.4676 libc-2.5.so _int_malloc
- 226738 1.3611 ha_innodb_plugin.so.0.0.0 _ZL14build_template
- P19row_prebuilt_structP3THDP8st_tablej
- 206057 1.2370 HandlerSocket.so dena::hstcpsvr_worker::run_one_ep()
- 183330 1.1006 ha_innodb_plugin.so.0.0.0 mutex_spin_wait
- 175738 1.0550 HandlerSocket.so dena::dbcontext::
- cmd_find_internal(dena::dbcallback_i&, dena::prep_stmt const&,
- ha_rkey_function, dena::cmd_exec_args const&)
- 169967 1.0203 ha_innodb_plugin.so.0.0.0 buf_page_get_known_nowait
- 165337 0.9925 libc-2.5.so memcpy
- 149611 0.8981 ha_innodb_plugin.so.0.0.0 row_sel_store_mysql_rec
- 148967 0.8943 vmlinux generic_make_request
因?yàn)镠andlerSocket是運(yùn)行在MySQL內(nèi)部的,并直接與InnoDB打交道,你可以使用常見的SQL命令,如SHOW GLOBAL STATUS獲得統(tǒng)計(jì)信息,Innodb_rows_read達(dá)到了750000+是值得一看的。
- $ mysqladmin extended-status -uroot -i 1 -r | grep "InnoDB_rows_read"
- ...
- | Innodb_rows_read | 750192 |
- | Innodb_rows_read | 751510 |
- | Innodb_rows_read | 757558 |
- | Innodb_rows_read | 747060 |
- | Innodb_rows_read | 748474 |
- | Innodb_rows_read | 759344 |
- | Innodb_rows_read | 753081 |
- | Innodb_rows_read | 754375 |
- ...
測(cè)試用機(jī)詳細(xì)規(guī)格如下:
型號(hào):戴爾PowerEdge R710
CPU:Nehalem 8核,E5540@2.53GHz
內(nèi)存:32GB(所有數(shù)據(jù)都裝入緩沖池)
MySQL版本:5.1.50,InnoDB插件
Memcached/libmemcached版本:1.4.5(Memcached),0.44(libmemcached)
網(wǎng)絡(luò):Boradcom NetXtreme II BCM5709 1000Base-T(內(nèi)建四端口,使用了其中三個(gè))
Memcached和HandlerSocket都做了網(wǎng)絡(luò)I/O限制,當(dāng)我測(cè)試單個(gè)端口時(shí),HandlerSocket的成績(jī)是260000qps,Memcached的成績(jī)是220000qps。
HandlerSocket的特點(diǎn)和優(yōu)勢(shì)
HandlerSocket有許多特點(diǎn)和優(yōu)勢(shì),其中有一些是對(duì)我們真正有益的。
1、支持大量的查詢模式
HandlerSocket支持主鍵/唯一性查詢,非唯一性索引查詢,范圍掃描,LIMIT和INSERT/UPDATE/DELETE,不支持未使用任何索引的操作,multi_get操作(類似于in(1,2,3)) - 通過(guò)單一網(wǎng)絡(luò)往返獲取多行數(shù)據(jù) – 也是支持的。
2、可以處理大量并發(fā)連接
HandlerSocket連接是輕量級(jí)的,因?yàn)镠andlerSocket采用了epoll()和工作線程/線程池架構(gòu),MySQL內(nèi)部線程的數(shù)量是有限的(可以由my.cnf中的handlersocket_threads參數(shù)控制),因此你可以建立上千或上萬(wàn)的網(wǎng)絡(luò)連接,穩(wěn)定性不會(huì)受到任何影響(消耗太多的內(nèi)存,造成巨大的互斥競(jìng)爭(zhēng)等,如bug#26590,bug#33948,bug#49169)。
3、極好的性能
HandlerSocket相對(duì)于其它NoSQL陣容性能表現(xiàn)一點(diǎn)也不遜色,事實(shí)上,我還沒有看到哪個(gè)NoSQL產(chǎn)品在一臺(tái)普通服務(wù)器上可以執(zhí)行750000+次查詢。
HandlerSocket不僅消除了SQL相關(guān)的函數(shù)調(diào)用,也優(yōu)化了網(wǎng)絡(luò)/并發(fā)相關(guān)的問題。
***更小的網(wǎng)絡(luò)數(shù)據(jù)包
HandlerSocket協(xié)議和傳統(tǒng)MySQL協(xié)議相比更簡(jiǎn)單,更小,因此整個(gè)網(wǎng)絡(luò)的流量也更小。
***運(yùn)行有限的MySQL內(nèi)部線程數(shù)
參考上面的內(nèi)容。
***客戶端請(qǐng)求分組
當(dāng)大量的并發(fā)請(qǐng)求抵達(dá)HandlerSocket時(shí),每個(gè)工作線程盡可能多地聚集請(qǐng)求,然后同時(shí)執(zhí)行聚集起來(lái)的請(qǐng)求和返回結(jié)果,這樣可以大大地提高性能,只是要犧牲一點(diǎn)響應(yīng)時(shí)間,例如,你可以得到以下好處,如果有人感興趣,我會(huì)在今后的文章中對(duì)它們加以深入的解釋。
減少fsync()調(diào)用的次數(shù)
減少?gòu)?fù)制延遲
4、沒有重復(fù)的緩存
當(dāng)你使用Memcached緩存MySQL/InnoDB記錄時(shí),在Memcached和InnoDB緩沖池中均緩存了這些記錄,因此效率非常低(內(nèi)存仍然很貴?。?,由于HandlerSocket插件訪問InnoDB存儲(chǔ)引擎,記錄可以緩存在InnoDB緩沖池中,這樣其它SQL語(yǔ)句就可以重復(fù)使用它。
5、沒有數(shù)據(jù)不一致的現(xiàn)象
由于數(shù)據(jù)只存儲(chǔ)在一個(gè)地方(InnoDB內(nèi)),不需要在Memcached和MySQL之間檢查數(shù)據(jù)一致性。
6、崩潰安全
后端存儲(chǔ)是InnoDB,它是事務(wù)性和崩潰安全的,即使你設(shè)置innodb-flush-log-at-trx-commit!=1,在服務(wù)器崩潰時(shí)也只會(huì)丟掉<1秒內(nèi)的數(shù)據(jù)。
7、可以從MySQL客戶端使用SQL
在許多情況下,人們?nèi)匀幌M褂肧QL(如生產(chǎn)摘要報(bào)告),這就是為什么我們不能使用嵌入式InnoDB的原因,大多數(shù)NoSQL產(chǎn)品都不支持SQL接口,HandlerSocket僅僅是一個(gè)MySQL插件,你可以從MySQL客戶端發(fā)送SQL語(yǔ)句,當(dāng)你需要高吞吐量時(shí)最好使用HandlerSocket協(xié)議。
8、MySQL所有操作都將受益
因?yàn)镠andlerSocket在MySQL內(nèi)部運(yùn)行,因此所有MySQL操作,如SQL,在線備份,復(fù)制,通過(guò)Nagios/EnterpriseMonitor監(jiān)控等都是支持的,HandlerSocket獲得可以通過(guò)普通的MySQL命令監(jiān)控,如SHOW GLOBAL STAUTS,SHOW ENGINE INNODB STATUS和SHOW PROCESSLIST等。
9、不需要修改/重建MySQL
因?yàn)镠andlerSocket是一個(gè)插件,它支持MySQL社區(qū)版和企業(yè)服務(wù)器版,無(wú)需對(duì)MySQL做出任何修改就可以使用。
10、獨(dú)立于存儲(chǔ)引擎
雖然我們只測(cè)試了5.1和5.5 InnoDB插件,但HandlerSocket可以和任何存儲(chǔ)引擎交互。
注意事項(xiàng)和限制
1、需要學(xué)習(xí)HandlerSocket API
盡管它很容易使用,但你仍然需要學(xué)習(xí)如何與HandlerSocket交互,我們提供了C++ API和Perl綁定。
2、沒有安全功能
和其它NoSQL數(shù)據(jù)庫(kù)類似,HandlerSocket不支持安全功能,HandlerSocket的工作線程以系統(tǒng)用戶權(quán)限運(yùn)行,因此應(yīng)用程序可以訪問通過(guò)HandlerSocket協(xié)議的所有表,當(dāng)然,你可以象其它NoSQL產(chǎn)品一樣使用防火墻過(guò)濾數(shù)據(jù)包。
3、對(duì)于HDD綁定工作負(fù)載沒有優(yōu)勢(shì)
對(duì)于HDD I/O綁定工作負(fù)載,數(shù)據(jù)庫(kù)每秒無(wú)法執(zhí)行數(shù)千次查詢,通常只有1-10%的CPU利用率,在這種情況下,SQL執(zhí)行層不會(huì)成為瓶頸,因此使用HandlerSocket沒有什么優(yōu)勢(shì),我們只在數(shù)據(jù)完全裝載到內(nèi)存的服務(wù)器上使用HandlerSocket。
DeNA在生產(chǎn)環(huán)境中使用HandlerSocket
我們已經(jīng)在生產(chǎn)環(huán)境中使用了HandlerSocket插件,效果是很明顯的,最終我們減少了許多Memcached和MySQL從屬服務(wù)器,整個(gè)網(wǎng)絡(luò)流量也減少了,目前我們還沒有發(fā)現(xiàn)任何性能問題(如響應(yīng)時(shí)間慢,延遲等)。
我認(rèn)為MySQL完全被NoSQL/數(shù)據(jù)庫(kù)社區(qū)低估了,MySQL的歷史悠久,我的前同事們也在不斷改進(jìn)它,從NDBAPI可以看出MySQL有成為NoSQL的潛力,存儲(chǔ)引擎API和守護(hù)進(jìn)程接口是完全獨(dú)立的,使得Akira和DeNA開發(fā)HandlerSocket成為可能,作為MySQL一名前員工和對(duì)MySQL長(zhǎng)期的了解,我想看到MySQL變得更好,更受歡迎,不只作為一個(gè)RDBMS,也應(yīng)該成為NoSQL陣營(yíng)中的一員。
HandlerSocket插件是開源的,可以免費(fèi)使用,歡迎你下載和使用,并希望聽到你的反饋。
原文出處:Using MySQL as a NoSQL - A story for exceeding 750,000 qps on a commodity server
【編輯推薦】