程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 數據庫知識 >> MYSQL數據庫 >> 關於MYSQL數據庫 >> MySQL下的NoSQL解決方案HandlerSocket

MySQL下的NoSQL解決方案HandlerSocket

編輯:關於MYSQL數據庫

     目前使用MySQL的網站,多半同時使用Memcache作為鍵值緩存。雖然這樣的架構極其流行,有眾多成功的案例,但過於依賴Memcache,無形中讓Memcache成為故障的根源:

    Memcache數據一致性的問題:當MySQL數據變化後,如果不能及時有效的清理掉過期的數據,就會造成數據不一致。這在強調即時性的Web2.0時代,不可取。

    Memcache崩潰後的雪崩效應:作為緩存的Memcache一旦崩潰,MySQL很可能在短時間內承受高負載而宕機。據說前段時間新浪微博就遭遇了這樣的問題。

    注:關於清理過期數據的問題,可以在程序架構上想辦法,如果數據操作有統一DAO封裝的話,可以利用Observer模式來清理過期數據,非主題內容,資料自查。

    面對這些問題,HandlerSocket項目是個不錯的解決方案,它通過插件的方式賦予MySQL完整的NoSQL功能,從原理上講,它跳過MySQL中最耗時的語法解析,查詢計劃等步驟,直接讀取數據,如果內存夠大,能裝下索引,MySQL的查詢效率能提高若干倍!

    性能測試實例:Using MySQL as a NoSQL – A story for exceeding 750,000 qps (GFW)

    因為HandlerSocket的性能足夠好,所以就沒有必要使用Memcache了,能節省大量的硬件資源,相當低碳!而且HandlerSocket操作的是MySQL放在內存中的索引,沒有額外的緩存,所以自然就不存在數據一致性的問題。

    安裝

    如果使用Percona Server版本的MySQL就簡單了,因為它已經內置了HandlerSocket支持,不過考慮到其內置的版本不夠新,存在一些早已修復的BUG,所以最好采用源代碼編譯。

    官方已經有了一份簡單的安裝文檔,但在我實際安裝時,遇到了一些其他未說明的問題,所以這裡就把相應的安裝過程再寫一遍。

    首先要確保已經安裝了MySQL5.1以上的版本,我用的是Ubuntu操作系統,事先已經用apt安裝了MySQL5.1.37,同時還需要相應的mysql_config,如果是Ubuntu的話,可以:

     

    shell> aptitude install libmysqld-dev

     

    注:如果你用的MySQL是從源代碼編譯的或官方提供的二進制版本,可以略過此步。

    接著下載一份和系統MySQL版本一致的MySQL源代碼和HandlerSocket源代碼:

    mysql-5.1.37.tar.gz

    ahiguti-HandlerSocket-Plugin-for-MySQL-1.0.6-76-gf5f7443.tar.gz

     

    shell> tar zxf mysql-5.1.37.tar.gz
    shell> tar zxf ahiguti-HandlerSocket-Plugin-for-MySQL-1.0.6-76-gf5f7443.tar.gz
    shell> cd ahiguti-HandlerSocket-Plugin-for-MySQL-f5f7443
    shell> ./autogen.sh
    shell> ./configure --with-mysql-source=../mysql-5.1.37
    --with-mysql-bindir=/usr/bin
    --with-mysql-plugindir=/usr/lib/mysql/plugin

     

    其中的參數含義如下:with-mysql-source表示MySQL源代碼目錄,with-mysql-bindir表示MySQL二進制可執行文件目錄(也就是mysql_config所在目錄),with-mysql-plugindir表示MySQL插件目錄,如果不清楚這個目錄在哪,可以按如下方法查詢:

     

    mysql> SHOW VARIABLES LIKE 'plugin%';
    +---------------+-----------------------+
    | Variable_name | Value |
    +---------------+-----------------------+
    | plugin_dir | /usr/lib/mysql/plugin |
    +---------------+-----------------------+

     

    運行命令後,如果你使用的是MySQL5.1.37版本的話,會遇到如下錯誤信息:

    MySQL source version does not match MySQL binary version

    明明我們的MySQL源代碼版本和二進制版本都是5.1.37,為什麼還會出現這個錯誤呢?通過查詢HandlerSocket的編譯腳本,發現原來它會檢索MySQL源代碼目錄中的VERSION文件,可MySQL5.1.37的源代碼目錄裡不知何故竟然沒有這個文件,所以就報錯了,既然知道了原因,那我們就照貓畫虎做一個VERSION文件放到MySQL源代碼目錄,內容如下:

     

    MYSQL_VERSION_MAJOR=5
    MYSQL_VERSION_MINOR=1
    MYSQL_VERSION_PATCH=37
    MYSQL_VERSION_EXTRA=

     

    再次運行configure腳本,應該就OK了,把剩下的步驟進行完:

     

    shell> make
    shell> make install

     

    接著需要配置一下HandlerSocket,編輯MySQL配置文件,加入如下內容:

     

    [mysqld]
    loose_handlersocket_port = 9998
    # the port number to bind to (for read requests)
    loose_handlersocket_port_wr = 9999
    # the port number to bind to (for write requests)
    loose_handlersocket_threads = 16
    # the number of worker threads (for read requests)
    loose_handlersocket_threads_wr = 1
    # the number of worker threads (for write requests)
    open_files_limit = 65535
    # to allow handlersocket accept many concurrent
    # connections, make open_files_limit as large as
    # possible.

     

    此外,InnoDB的innodb_buffer_pool_size,或MyISAM的key_buffy_size等關系到緩存索引的選項盡可能設置大一些,這樣才能發揮HandlerSocket的潛力。

    注:apt包管理下的配置文件一般是/etc/mysql/my.cnf,否則一般是/etc/my.cnf

    最後登陸MySQL並激活HandlerSocket插件:

     

    mysql> INSTALL PLUGIN handlersocket soname 'handlersocket.so';

     

    如果沒有問題的話,就能在MySQL裡看到HandlerSocket的線程了:

     

    mysql> SHOW PROCESSLIST;

     

    也可以通過查詢剛配置的端口是否已經被MySQL占用來確認是否安裝成功:

     

    shell> lsof -i :9998
    shell> lsof -i :9999

     

    完活兒!現在你的MySQL已經具備NoSQL的能力了!

    實戰

    首先創建一個測試用的表:

     

    CREATE TABLE IF NOT EXISTS `test`.`t` (
    `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
    `a` varchar(10) NOT NULL,
    `b` varchar(10) NOT NULL,
    PRIMARY KEY (`id`),
    KEY `a_b` (`a`,`b`)
    ) ENGINE=InnoDB;

     

    注:理論上HandlerSocket支持MyISAM,InnoDB等各種引擎,不過推薦使用InnoDB。

    HandlerSocket的協議非常簡單,指令通過TAB分割,一行就是一個請求。

    打開索引:P <索引標識> <數據庫> <表> <索引> <字段>

    插入數據:<索引標識> ‘+’ <參數個數> <參數1> … <參數N>

    讀取數據:<索引標識> <操作> <參數個數> <參數1> … <參數N> <條數> <偏移>

    SQL原型:INSERT INTO test.t (id, a, b) VALUES (1, ‘a1′, ‘b1′), (2, ‘a2′, ‘b2′)

     

    shell> telnet localhost 9999
    Trying 127.0.0.1...
    Connected to localhost.
    Escape character is '^]'.
    P 1 test t PRIMARY id,a,b
    0 1
    1 + 3 1 a1 b1
    0 1 0
    1 + 3 2 a2 b2
    0 1 0

     

    注:使用HandlerSocket時,因為沒有實際運行SQL,所以Binlog記錄的是Row格式。

    SQL原型:SELECT id, a, b FROM test.t WHERE id = 1 LIMIT 1

     

    shell> telnet localhost 9999
    Trying 127.0.0.1...
    Connected to localhost.
    Escape character is '^]'.
    P 1 test t PRIMARY id,a,b
    0 1
    1 = 1 1 1 0
    0 3 1 a1 b1

     

    SQL原型:SELECT id, a, b FROM test.t WHERE id >=1 LIMIT 2

     

    shell> telnet localhost 9999
    Trying 127.0.0.1...
    Connected to localhost.
    Escape character is '^]'.
    P 1 test t PRIMARY id,a,b
    0 1
    1 >= 1 1 2 0
    0 3 1 a1 b1 2 a2 b2

     

    SQL原型:SELECT id, a, b FROM test.t WHERE a = ‘a1′ AND b = ‘b1′ LIMIT 1

     

    shell> telnet localhost 9999
    Trying 127.0.0.1...
    Connected to localhost.
    Escape character is '^]'.
    P 1 test t a_b id,a,b
    0 1
    1 = 2 a1 b1 1 0
    0 3 1 a1 b1

     

    對HandlerSocket一個常見的誤解是只能執行PRIMARY類型的KV查詢,實際上只要支持索引,一般的簡單查詢它都能勝任,篇幅所限,這裡就不多說了,如果你覺得直接操作telnet有些吃力,也可以使用自己熟悉的客戶端來測試,官方文檔裡有介紹。

    1. 上一頁:
    2. 下一頁:
    Copyright © 程式師世界 All Rights Reserved