一、简介
Atlas是由 Qihoo 360公司Web平台部基础架构团队开发维护的一个基于MySQL协议的数据中间层项目。它在MySQL官方推出的MySQL-Proxy 0.8.2版本的基础上,修改了大量bug,添加了很多功能特性。目前该项目在360公司内部得到了广泛应用,很多MySQL业务已经接入了Atlas平台,每天承载的读写请求数达几十亿条。
主要功能:
123456 | 1.读写分离2.从库负载均衡3.IP过滤4.自动分表5.DBA可平滑上下线DB6.自动摘除宕机的DB |
二、Atlas相对于官方MySQL-Proxy的优势
1234 | 1.将主流程中所有Lua代码用C重写,Lua仅用于管理接口2.重写网络模型、线程模型3.实现了真正意义上的连接池4.优化了锁机制,性能提高数十倍 |
三、Atlas详细说明
1234567 | 1.Atlas的安装2.Atlas的运行及常见问题3.Atlas的分表功能简介4.Atla部分配置参数及原理详解5.Atlas的架构6.Atlas的性能测试7.Atlas功能特点FAQ |
四、Atlas的需求及Bug反馈方式
如果用户在实际的应用场景中对Atlas有新的功能需求,或者在使用Atlas的过程中发现了bug,欢迎用户发邮件至zhuchao[AT]360.cn,与我们取得联系,我们将及时回复。另外有热心网友建立了QQ群326544838,开发者也已经加入,方便讨论。
五、名字来源
Atlas:希腊神话中双肩撑天的巨人,普罗米修斯的兄弟,最高大强壮的神之一,因反抗宙斯失败而被罚顶天。我们期望这个系统能够脚踏后端DB,为前端应用撑起一片天。
六、安装
Atlas的安装非常简单,从https://github.com/Qihoo360/Atlas/releases地址下载相应的rpm包直接安装即可,可能有一些依赖关系,yum都能解决的,就不多讲了!
七、配置文件:
配置文件位置/usr/local/mysql-proxy/config下面,就我的内网应用而言,我创建新的配置文件如下:
123456789101112131415161718192021222324252627282930313233343536373839 | [mysql-proxy]#带#号的为非必需的配置项目#管理接口的用户名admin-username=admin#管理接口的密码admin-password=passw0rd#Atlas后端连接的MySQL主库的IP和端口,可设置多项,用逗号分隔proxy-backend-addresses=192.168.1.66:3306#Atlas后端连接的MySQL从库的IP和端口,@后面的数字代表权重,用来作负载均衡,若省略则默认为1,可设置多项,用逗号分隔proxy-read-only-backend-addresses=192.168.1.64:3306,192.168.1.244:3306#用户名与其对应的加密过的MySQL密码,密码使用PREFIX/bin目录下的加密程序encrypt加密,下行的user1和user2为示例,将其替换为你的MySQL的用户名和加密密码!#pwds = user1:+jKsgB3YAG8=, user2:GS+tr4TPgqc=pwds=root:FYCDJMDki+SiquyHfJnWyQ==#设置Atlas的运行方式,设为true时为守护进程方式,设为false时为前台方式,一般开发调试时设为false,线上运行时设为truedaemon=true#设置Atlas的运行方式,设为true时Atlas会启动两个进程,一个为monitor,一个为worker,monitor在worker意外退出后会自动将其重启,设为false时只有worker,没有monitor,一般开发调试时设为false,线上运行时设为truekeepalive=true#工作线程数,对Atlas的性能有很大影响,可根据情况适当设置event-threads=64#日志级别,分为message、warning、critical、error、debug五个级别log-level=message#日志存放的路径log-path=/usr/local/mysql-proxy/log#SQL日志的开关,可设置为OFF、ON、REALTIME,OFF代表不记录SQL日志,ON代表记录SQL日志,REALTIME代表记录SQL日志且实时写入磁盘,默认为OFF#sql-log = OFF#实例名称,用于同一台机器上多个Atlas实例间的区分#instance = test#Atlas监听的工作接口IP和端口proxy-address=0.0.0.0:1234#Atlas监听的管理接口IP和端口admin-address=0.0.0.0:2345#分表设置,此例中person为库名,mt为表名,id为分表字段,3为子表数量,可设置多项,以逗号分隔,若不分表则不需要设置该项#tables = person.mt.id.3#默认字符集,设置该项后客户端不再需要执行SET NAMES语句#charset = utf8#允许连接Atlas的客户端的IP,可以是精确IP,也可以是IP段,以逗号分隔,若不设置该项则允许所有IP连接,否则只允许列表中的IP连接#client-ips = 127.0.0.1, 192.168.1#Atlas前面挂接的LVS的物理网卡的IP(注意不是虚IP),若有LVS且设置了client-ips则此项必须设置,否则可以不设置#lvs-ips = 192.168.1.1 |
八、启动关闭重启:
123 | # /usr/local/mysql-proxy/bin/mysql-proxyd instance start# /usr/local/mysql-proxy/bin/mysql-proxyd instance stop# /usr/local/mysql-proxy/bin/mysql-proxyd instance restart |
九、负载读写分离测试:
12345678910111213141516171819202122232425262728293031323334 | [root@YQD-Intranet-DB-NO2~]# mysql -uroot -p***** -h192.168.1.63 -P1234WelcometotheMySQLmonitor. Commandsendwith;org.YourMySQLconnectionidis1295815494Serverversion:5.0.81-logSourcedistribution Copyright(c)2009-2013PerconaLLCand/oritsaffiliatesCopyright(c)2000,2013,Oracleand/oritsaffiliates.Allrightsreserved. OracleisaregisteredtrademarkofOracleCorporationand/oritsaffiliates.Othernamesmaybetrademarksoftheirrespectiveowners. Type'help;'or'h'forhelp.Type'c'toclearthecurrentinputstatement. root@(none)10:28:46>showvariableslike"server_id";+---------------+-------+|Variable_name|Value|+---------------+-------+|server_id |3 |+---------------+-------+1rowinset(0.00sec) root@(none)10:28:48>showvariableslike"server_id";+---------------+-------+|Variable_name|Value|+---------------+-------+|server_id |2 |+---------------+-------+1rowinset(0.00sec) 开启sql日志,日志显示如下:[06/27/201410:36:56]C:192.168.1.228:50179S:192.168.1.244:3306OK0.419"SHOW CREATE TABLE `t_categary`"[06/27/201410:36:56]C:192.168.1.228:50180S:192.168.1.64:3306OK0.739"SELECT * FROM `t_categary` LIMIT 0, 1000"[06/27/201410:36:56]C:192.168.1.228:50180S:192.168.1.244:3306OK0.724"SHOW COLUMNS FROM `cat_db`.`t_categary`" |
OLTP基准测试:
OLTP基准测试模拟了一个简单的的事务处理系统的工作负载。下面的例子使用的是一张百万行记录的表,第一步先生成这张表:
123456789 | # time sysbench --test=oltp --db-driver=mysql --mysql-engine-trx=yes --mysql-table-engine=innodb --mysql-host=127.0.0.1 --mysql-port=1234 --mysql-user=root --mysql-password=****** --oltp-table-size=1000000 preparesysbench 0.4.12: multi-threaded system evaluation benchmark Creating table 'sbtest'...Creating 1000000 records in table 'sbtest'... real0m58.132suser0m0.209ssys0m0.036s |
接下来可以运行测试,这个例子采用了16个并发线程,只读模拟测试:
123456789101112131415161718192021222324252627282930313233343536373839404142434445 | # time sysbench --test=oltp --db-driver=mysql --mysql-engine-trx=yes --mysql-table-engine=innodb --mysql-host=127.0.0.1 --mysql-port=1234 --oltp-read-only=on --mysql-user=root --mysql-password=****** --oltp-table-size=1000000 --num-threads=16 runsysbench0.4.12: multi-threadedsystemevaluationbenchmark Runningthetestwithfollowingoptions:Numberofthreads:16 DoingOLTPtest.RunningmixedOLTPtestDoingread-onlytestUsingSpecialdistribution(12iterations, 1pctofvaluesarereturnedin75pctcases)Using"BEGIN"forstartingtransactionsUsingauto_incontheidcolumnMaximumnumberofrequestsforOLTPtestislimitedto10000Threadsstarted!Done. OLTPteststatistics: queriesperformed: read: 140000 write: 0 other: 20000 total: 160000 transactions: 10000 (1007.89persec.) deadlocks: 0 (0.00persec.) read/writerequests: 140000(14110.48persec.) otheroperations: 20000 (2015.78persec.) Testexecutionsummary: totaltime: 9.9217s totalnumberofevents: 10000 totaltimetakenbyeventexecution:158.5972 per-requeststatistics: min: 10.86ms avg: 15.86ms max: 25.08ms approx. 95percentile: 18.51ms Threadsfairness: events(avg/stddev): 625.0000/4.08 executiontime(avg/stddev): 9.9123/0.00 real0m10.198suser0m1.216ssys0m2.583s |
从时间上来看比之前haproxy测试要略慢,还是haproxy的性能更靠谱,但是haproxy需要在应用层实现读写分离,就是代码了
tpcc压测:
12345678910 | root@(none) 10:46:19>create database tpcc5;Query OK, 1 row affected (0.54 sec) # mysql -uroot -p******* -h192.168.1.63 -P1234 tpcc5 < create_table.sql Warning: Using a password on the command line interface can be insecure.ERROR 1231 (42000) at line 140: Variable 'foreign_key_checks' can't be set to the value of 'NULL' # mysql -uroot -p******* -h192.168.1.63 -P1234 tpcc5 < add_fkey_idx.sql Warning: Using a password on the command line interface can be insecure.ERROR 1231 (42000) at line 23: Variable 'foreign_key_checks' can't be set to the value of 'NULL' |
tpcc导入表时出错了,提示变量foreign_key_checks不能设置为NULL值,暂且不管它,继续测试:
123456789101112131415161718192021222324 | # ./tpcc_load 192.168.1.63:1234 tpcc5 root "********" 3****************************************###easy### TPC-C Data Loader ****************************************<Parameters> [server]:192.168.1.63 [port]:1234 [DBname]:tpcc5 [user]:root [pass]:LVS@071103 [warehouse]:3TPCCDataLoadStarted...LoadingItem..................................................5000..................................................10000..................................................15000..................................................20000..................................................25000..................................................30000..................................................35000..................................................40000..................................................45000..................................................50000下面省略N行....................................... |
1234567891011121314151617181920212223242526272829303132333435 | # ./tpcc_start -h192.168.1.63 -P1234 -dtpcc5 -uroot -p******** -w3 -c32 -r10 -l600******************************************###easy### TPC-C Load Generator ******************************************中间省略N行.................................................<RawResults> [0]sc:5059 lt:0 rt:0 fl:0 [1]sc:5057 lt:0 rt:0 fl:0 [2]sc:506 lt:0 rt:0 fl:0 [3]sc:506 lt:0 rt:0 fl:0 [4]sc:506 lt:0 rt:0 fl:0in600sec. <RawResults2(sumver.)> [0]sc:5059 lt:0 rt:0 fl:0 [1]sc:5059 lt:0 rt:0 fl:0 [2]sc:506 lt:0 rt:0 fl:0 [3]sc:506 lt:0 rt:0 fl:0 [4]sc:506 lt:0 rt:0 fl:0 <ConstraintCheck>(allmustbe[OK])[transactionpercentage] Payment:43.47%(>=43.0%)[OK] Order-Status:4.35%(>=4.0%)[OK] Delivery:4.35%(>=4.0%)[OK] Stock-Level:4.35%(>=4.0%)[OK][responsetime(atleast90%passed)] New-Order:100.00% [OK] Payment:100.00% [OK] Order-Status:100.00% [OK] Delivery:100.00% [OK] Stock-Level:100.00% [OK] <TpmC> 505.900TpmC |
经过一段时间的使用,发现atlas目前是比较稳定的,但是性能不作过多评价!有时面面俱到真是难!多一层代理,性能肯定会下降,如果程序端能实现读写分离,直连集群或主备,那样的性能应该是最好的。
[参考资料]采用Atlas+Keepalived实现MySQL读写分离、读负载均衡 - http://sofar.blog.51cto.com/353572/1601552/