一、十億數據,輕松秒出
實時監控領域有兩個顯著的特點,一是數據來源很多而且數據量大,有來自監控攝像頭、GPS、智能設備等;二是需要實時處理。我們的客戶在做實時處理時,就遇到這樣的問題。客戶的某個數據表中有10億條記錄,希望統計類查詢的響應時間在30s以內,而使用單台MySQL的響應時間在300s以上。OneProxy特有的並行查詢功能,讓響應時間降到10s以內。如有疑問,請聯系onesoft007(微信)
二、並行查詢前提之分庫分表
大家都說MySQL不具備並行查詢能力,OneProxy做到了!
在互聯網+的時代,分庫分表已經成為行業的標准解決方案之一。在眾多應用中,數據每天都以GB級別遞增,其中若干個熱點表會達到幾十G或者幾百G。眾所周知,大的數據表在使用和維護時,存在諸多問題。
1)某些DDL操作,響應時間難以接受。添加、修改、刪除數據表字段時,耗時太長(甚至達到幾天),占用大量IO,導致影響線上業務;
2)性能難以提高。一張大表只能放在一台服務器上,而單台服務器的服務能力有限,導致系統的性能受制於單台服務器的能力;
3)統計分析,耗時太長。由於MySQL本身不支持單條SQL語句內的並發,因此一個統計分析型SQL語句,受制於全表掃描的速度,而這是難以接受的,尤其是表無法全部放在內存時。
對於上述問題,一個目前被廣泛采用的解決方案,就是把一個大表拆成多個小表放到多個不同的數據庫中,即分庫分表,如圖1。
圖 1 分庫分表
三、並行查詢原理
OneProxy並行查詢的實現依賴於其自身的分庫分表功能。它通過內置的SQL解析器,將來自客戶端的SQL查詢改寫成帶有分片信息的多個查詢並分發到不同的主機上並行執行,從而極大提高了響應速度,如圖2。
圖2 並行查詢
四、部署
1) 多台linux主機,推薦Centos6 64bit
2)從公司官網下載安裝文件(http://www.onexsoft.com/download)
3) 安裝
A)解壓到指定目錄
mv oneproxy-rhel5-linux64* /usr/local/ tar zxvf oneproxy-rhel5-linux64* |
B)更改啟動文件
cd oneproxy cat demo.sh |
#!/bin/bash export ONEPROXY_HOME=/data/oneproxy
if [ -f ${ONEPROXY_HOME}/oneproxy.pid ]; then kill -9 `cat ${ONEPROXY_HOME}/oneproxy.pid` fi
sleep 2 # valgrind --leak-check=full --show-reachable=yes \ ${ONEPROXY_HOME}/oneproxy --proxy-address=:3307 --proxy-extra-address=:3308 \ --proxy-master-addresses=192.168.1.119:3306@default \ --proxy-user-list=test/1378F6CC3A8E8A43CA388193FBED5405982FBBD3@test \ --proxy-part-tables=${ONEPROXY_HOME}/part.txt \ --proxy-charset=gbk_chinese_ci --proxy-found-rows \ --proxy-group-policy=default:master-only \ --event-threads=6 --proxy-group-security=default:0 \ --log-file=${ONEPROXY_HOME}/oneproxy.log \ --pid-file=${ONEPROXY_HOME}/oneproxy.pid |
更改后
#/bin/bash # export ONEPROXY_HOME=/usr/local/oneproxy
if [ -f ${ONEPROXY_HOME}/oneproxy.pid ]; then kill -9 `cat ${ONEPROXY_HOME}/oneproxy.pid` fi
sleep 2 # valgrind --leak-check=full --show-reachable=yes \ ${ONEPROXY_HOME}/oneproxy --proxy-address=:3307 --proxy-extra-address=:3308 \ --proxy-master-addresses=<IP1>:3306@data1 \ --proxy-master-addresses=<IP2>:3306@data2 \ --proxy-master-addresses=<IP3>:3306@data3 \ --proxy-master-addresses=<IP4>:3306@data4 \ --proxy-master-addresses=<IP5>:3306@data5 \ --proxy-master-addresses=<IP6>:3306@data6 \ --proxy-master-addresses=<IP7>:3306@data7 \ --proxy-master-addresses=<IP8>:3306@data8 \ --proxy-user-list=test/1378F6CC3A8E8A43CA388193FBED5405982FBBD3@test \ --proxy-part-tables=${ONEPROXY_HOME}/hashpart.txt \ --proxy-charset=utf8_bin --proxy-found-rows \ --proxy-group-policy=data1:master-only \ --proxy-group-policy=data2:master-only \ --proxy-group-policy=data3:master-only \ --proxy-group-policy=data4:master-only \ --proxy-group-policy=data5:master-only \ --proxy-group-policy=data6:master-only \ --proxy-group-policy=data7:master-only \ --proxy-group-policy=data8:master-only \ --event-threads=6 \ --keepalive \ --log-file=${ONEPROXY_HOME}/oneproxy.log \ --pid-file=${ONEPROXY_HOME}/oneproxy.pid |
注釋:
A) --proxy-user-list=test/1378F6CC3A8E8A43CA388193FBED5405982FBBD3@test 其中第一個test為連接proxy的用戶名,該用戶名也是用來連接后端數據庫的用戶名;1378F6CC3A8E8A43CA388193FBED5405982FBBD3為test用戶的加密口令;最后一個test為各個數據庫節點中的test數據庫。
B) 口令加密。啟動OneProxy之后,進入管理端口,然后鍵入passwd <string>。
mysql -uadmin -pOneProxy -P4041 --protocol=TCP passwd test |
輸出為:
C) 分表文件hashpart.txt
[ { "table" : "bigtable", "pkey" : "id", "type" : "int", "method" : "hash", "partitions": 256, "groups": ["data1","data2","data3", "data4","data5","data6", "data7","data8"] } ] |
|
其中table:拆分的表;pkey:分表列;type:分表列類型,目前支持的類型為int和char;method:分區方法,目前支持hash,range,list,global
4). 安裝數據節點,並賦予用戶相應權限。
A) MySQL安裝方法 請參考官方安裝文檔https://dev.mysql.com/doc/refman/5.6/en/linux-installation.html
如果你對線程池、SQL級別限流,秒殺解決方案等感興趣,可以使用OneSQL。
下載地址:www.onexsoft.com/download ,解壓替換系統中已有mysqld文件即可。具體使用方法見文檔:http://www.onexsoft.com/OneSQL_Best_Practise.pdf。
B)權限分配
登錄到各個底層數據庫所在的linux主機上,運行如下命令:
mysql -e "grant all privileges on *.* to test@'%' identified by 'test' " |
5). 啟動
sh ./demo.sh |
檢查啟動輸出
cat oneproxy.log |
2015-05-04 19:38:15: (critical) plugin oneproxy 5.4.1-20150425 started
2015-05-04 19:38:15: (critical) valid config checksum = 88429892
6). 檢查后端數據庫節點狀態
進入管理端口(默認端口為4041)
mysql -uadmin -pOneProxy -P4041 --protocol=TCP |
然后鍵入
list backend; |
可以看到輸出為:
status這一欄為UP,表示集群正常。
7). 創建表
登錄OneProxy的轉發端口
mysql -h<OneProxyIP> -P3307 -utest -ptest |
DDL語句:
CREATE TABLE `bigtable` ( `id` bigint(20) NOT NULL, `start` datetime DEFAULT NULL, `icol3` int(11) DEFAULT NULL COMMENT ' 1-10 ', `icol4` int(11) DEFAULT NULL COMMENT ' 1-100 ', `icol5` int(11) DEFAULT NULL COMMENT ' 1-1000 ', `icol6` int(11) DEFAULT NULL, `vcol7` varchar(20) DEFAULT NULL, `vcol8` varchar(20) DEFAULT NULL, `vcol9` varchar(30) DEFAULT NULL, `vcol10` varchar(20) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 |
執行這個語句,會看到報錯: ERROR 1044 (42000): Access denied due to security policy, DDL disabled or DML restricted!
解釋:由於OneProxy為了安全起見,默認是禁止DDL語句的。
解決辦法:從OneProxy管理端口,運行如下命令
mysql -h<OneProxyIP> -uadmin -pOneProxy -P4041 -e "set gaccess data1 0;set gaccess data2 0;set gaccess data3 0;set gaccess data4 0;set gaccess data5 0;set gaccess data6 0;set gaccess data7 0;set gaccess data8 0" |
再次登錄到OneProxy的轉發端口,運行DDL命令即可成功。
經過上面的步驟之后,256個表就在8個底層數據庫中創建好了,分別為bigtable_0 , bigtable_1 .....bigtable_255。
五、測試數據生成
客戶可以使用自己編寫的程序來生成測試數據,也可以使用平民軟件創始人(樓方鑫)編寫的mydbtest軟件。mydbtest不僅可以生成測試數據,也可以根據用戶自定義的SQL語句去執行測試。程序下載地址:
http://www.onexsoft.com/software/mydbtest_linux64.zip
文檔可以從百度雲中找到:
http://pan.baidu.com/s/1mgJpukg#path=%252FOneSQL%252FDocument
然后找到 ”MySQL數據庫測試工具“ 即可下載。具體的使用和詳細的參數,請參考文檔。
本文使用mydbtest來做數據裝載工具,使用方法和配置文件如下
nohup ./mydbtest_linux64.bin query=insert.cnf degree=500 > /dev/null 2>&1 & |
配置文件 insert.cnf
Option user test/test@<OneProxyIP>:3307:data1 loop 100000000 log insert_%p.log time 24h declare vid bigseq 1 10000000000 vstart TIMESTAMP -10 10 vicol3 int 1 10 vicol4 int 1 100 vicol5 int 1 1000 vicol6 int 1 100000 vvcol7 char 10 19 vvcol8 char 10 19 vvcol9 char 10 29 vvcol10 char 10 19 begin insert into bigtable( id , start ,icol3, icol4 , icol5 , icol6 , vcol7, vcol8, vcol9, vcol10 ) values ( :vid , :vstart ,:vicol3, :vicol4 , :vicol5 , :vicol6 , :vvcol7, :vvcol8, :vvcol9, :vvcol10); end |
六、並行查詢測試
測試環境:
OS |
Centos 6.3 x64 |
CPU |
8Core 2.4GHZ |
Memory |
32G |
Disk |
RAID1 300G 7200r/min |
MySQL 配置:
innodb_buffer_pool_size |
24G |
max_connections |
4096 |
tcc_control_min_connections [OneSQL] |
16 |
測試數據:
表名 |
bigtable |
分表數 |
256 |
數據節點數 |
8 |
記錄數 |
1,401,817,594 |
數據文件大小 |
25G * 8 |
測試結果
測試方法 |
響應時間 |
Select count(*) from bigtable 非並行 |
286.38s |
Select /* parrallel */count(*) from bigtable 並行 |
8.23s |
Select icol3,count(*) from bigtable group by icol3; 非並行 |
652.64s |
select /*parallel*/ icol3,count(*) from bigtable group by icol3 並行 |
22.24s |
可以看出並行之后,count(*)性能提升約35倍。