Atlas介绍

http://www.uml.org.cn/sjjm/2017022805.asp

Atlas是由奇虎360公发的基于MySQL协议的数据库中间件产品,它在MySQL官方推出的MySQL-Proxy 0.8.2版本的基础上,修改了若干Bug,并增加了很多功能特性。目前该产品在360内部得到了广泛应用,覆盖80%以上的MySQL业务,每天读写量达数十亿次,于GitHub开源后,业界几十家公司将其应用于生产环境。

Atlas项目源代码托管地址https://github.com/qihoo360/atlas

产品研发背景

该项目最早在2012年提出,主要为了解决两个问题:

一是业务程序员对数据库细节关注过多。在没有中间件的情况下,应用程序直接连接MySQL的主从库,需要在配置文件中指定主从库的IP和端口,并由业务程序员自行决定将写语句和读语句分别发往主库和从库,在数据量较大的情况下还需要自行管理分库分表等技术细节,使得业务程序员负担较重。

二是DBA运维工作不方便。数据库宕机是家常便饭,在需要切换或上下线数据库时,DBA需要协调业务程序员修改配置,运维操作也会对业务造成一定干扰,影响DBA工作顺利进行。

我们希望能将业务与DB进行一定程度的隔离,使业务程序员尽量少关心DB的细节,可以专注于编写业务逻辑;另一方面DBA的运维操作尽量做到对业务无影响。如此则需要将读写分离、分库分表、平滑上下线DB等逻辑提炼出来,以公共组件的方式提供给以上两类人群使用。从形式上看有两种,一种是独立的中间件服务,另一种集成于客户端的LIB。前者优点是升级更新较方便,而且与语言无关,缺点是网络增加一跳,数据需要转发,性能可能不如LIB形式,后者优缺点正相反。经过权衡我们选择了前者,除以上考虑外还有部分原因是我们团队与各条业务线是独立的部门,要推动业务工程师升级LIB有相当的困难。

开始时调研了MySQL官方的MySQL-Proxy、阿里巴巴的Cobar、Amoeba、TDDL等产品,其中MySQL-Proxy更新缓慢,长期停留在Alpha版阶段,Cobar安装部署相对复杂,Amoeba不支持事务,TDDL未完整开源。最终我们选择了MySQL-Proxy进行二次开发。

技术架构

部署架构

Atlas一般搭配LVS使用,客户端通过LVS访问Atlas,以避免单点故障,当然也可以使用Keepalived等。Atlas后面挂接MySQL的一主多从集群,需要注意的是主从同步需要DBA预先配置好,Atlas只涉及客户端与DB间的网络交互,DB与DB间的通讯与Atlas无关。

图1 读写分离架构

Atlas会把客户端发来的SQL语句根据读写分别路由到主库和从库上,对于有多台从库的情况,还会根据加权负载均衡策略决定选择哪台从库来执行每条读语句。

线程模型

Atlas的线程模型与Memcached相似,都是由一个主线程和若干个工作线程组成。主线程负责监听客户端的新连接,工作线程在系统启动时即创建完成,并监听管道读端的读事件。当有客户端连接到来时,主线程将客户端的IP和端口等信息封装成一个CON结构,然后选择某个工作线程来处理该客户端的请求。选择的方法可以是Round-Robin方式,也可以根据各个线程的负载情况选择负载最轻的线程(可以粗略认为待处理队列最短即为负载最轻)。主线程选定工作线程后,将CON结构放入该线程对应的待处理队列,然后向相应管道的写端写入一个字节(字节内容无所谓),则工作线程会收到管道读端的读事件,并从队列中取出CON结构,进行下一步处理。当然也可改用Linux的新系统调用eventfd实现对工作线程的唤醒,性能比管道更高。

图2 线程模型

两个经典技术问题

字符集

MySQL支持多种字符集,字符集状态与会话(连接)绑定,即各个连接上的字符集互不相干。而Atlas拥有连接池,要求实现连接复用,这就不可避免会导致字符集混乱。

图3 访问架构

如图3所示,客户端发来SET NAMES UTF8语句,Atlas从连接池里取出一个空闲连接(连接1),在连接1上执行该语句后,将连接1放回连接池。客户端再发来一条SELECT语句,Atlas又从连接池里取出一个空闲连接(连接2),连接2大概率与连接1不是同一个连接,在连接2上执行SELECT语句,而连接2并未设置UTF-8字符集,因此造成乱码。

图4 访问架构

解决方案:Atlas记录每个客户端和每个连接的当前字符集状态(以一个正整数表示即可)并进行相关修正。当客户端发来SQL语句时,Atlas会检查该语句是否要设置字符集(SET NAMES或SET CHARACTER_XXX)。如某个客户端发来SET NAMES UTF8,Atlas从连接池内取出连接1并执行该语句,执行成功后,将该客户端和连接1的当前字符集均置为UTF-8。之后该客户端发来SELECT语句(或其他非SET类语句),Atlas从连接池内取出连接2,然后比较客户端的当前字符集(上步已设置为UTF-8)和连接2的当前字符集(假定为GBK),若一致则直接执行,若不一致则在SELECT前插入一条SET NAMES UTF8,将两条语句一起发给MySQL,第一条语句起到将连接2的字符集修正为UTF-8的作用,然后再执行SELECT则不会乱码。当然也可以进一步优化,就是由Atlas直接返回SET类语句的结果(OK)给客户端,省去一次与MySQL的交互过程。

自验证

图5 连接认证

图5是MySQL的连接认证示意图。

1.Connect阶段,客户端建立与MySQL的TCP连接;

2.HandShake阶段,MySQL向客户端发送握手包,其中携带多项信息,如服务端的特性标志、字符集等,此处我们主要关心的是其包含的20个字节的随机串;

3.Auth阶段,客户端将握手包内的随机串取出,与自身的密码一起执行以下运算SHA1( password) XOR SHA1( “20-bytes random data from server” SHA1( SHA1( password ) ) ),得到一个加密串,加上客户端的用户名、特性标志、字符集等附加信息,组成认证包发给MySQL。

4.Auth-Result阶段,MySQL通过在mysql.user中保存的该用户名对应的密码,也执行同样的运算得到一个加密串,并与认证包中的加密串对比,若相同则认为密码正确,返回结果OK给客户端,否则返回ERR拒绝连接。

返回OK后应用层连接即建立完毕,接下来客户端向MySQL发送SQL语句,并从MySQL接收语句的执行结果,然后再发送下条语句……直至有一方断开连接为止。

图6 Atlas连接访问工作原理

图6是1.x版本的Atlas的工作过程。

可以看到,在连接认证阶段,Atlas简单地透传客户端与MySQL双方的通讯包。初看似乎并没有问题,但考虑到Atlas后面挂接的是一主多从多台MySQL时,情况就变得比较复杂。

客户端向Atlas建立连接时,Atlas需要选择转而向哪台MySQL建立连接。以最简单的一主一从为例:若Atlas向主库建连接,则从库上没有连接,无法实现读写分离;若向从库建连接,则问题更严重,因为主库上没有连接,所以写语句无法执行。那么能不能同时向两台MySQL建连接呢?问题在于两台MySQL都会发送握手包,而客户端遵循MySQL协议,它不可能一次接受两个握手包……

在1.x中,我们使用了一个取巧的办法,即在主库上预留一定数量的连接,比如32个。客户端向Atlas建立连接时,首先检查主库上的连接数是否已经达到32个,若未达到则向主库建连接,若已达到则向从库建连接。这样既保证了写语句可以在主库上执行,又使得读语句可以在从库上执行,从而正确实现读写分离。这个办法有几个潜在的问题:

1. 若有多于32个客户端同一瞬间发送写语句,则主库上连接数将不够用,当然也可以让某些客户端阻塞等待其他客户端让出连接来部分解决;

2. 无法支持长连接;

3. 在主库连接数达到32个之前,仍然无法读写分离。

仔细分析以上情况,可以得知,其本质原因是Atlas需要依赖客户端的连接动作转而向MySQL建连接,因此能建立连接的数量最大不超过客户端的Connect次数,这就极大地制约了Atlas作为中间件的灵活性。为了摆脱这一束缚,就要求Atlas能自主决定何时、向哪台MySQL、建立多少个连接。实现该特性的前提是,Atlas必须知悉客户端的用户名和密码,因为从1.x的交互图上可知,Atlas透传客户端的认证包给MySQL,而认证包内只有加密串而没有密码明文,也不可能反解(否则我们就破解了MySQL的加密协议)。

图7 Atlas 连接访问工作原理

图7是2.x版本Atlas的工作过程。

用户名和密码事先已经作为配置在Atlas启动时加载进来(当然也可以通过Atlas的管理接口进行动态的增删改查)。当客户端来连接Atlas时,Atlas自行产生一个握手包(包含20字节随机串)发给客户端,然后接收客户端发来的认证包,根据配置的用户名和密码进行加密计算并检查结果,根据结果正确与否返回OK或ERR给客户端,从而完成客户端的连接认证工作。客户端发来SQL语句时,Atlas检查连接池中是否有空闲连接,若有则直接使用,若没有则根据配置的用户名和密码自行向MySQL建立新连接,然后供该语句使用。

此方案的优点:真正完全的读写分离,支持长连接,连接按需建立,连接数随并发度上升而增加,随并发度下降而减少(可以依靠MySQL的wait_timeout,也可以由Atlas监控连接的空闲时间)。

小结

从以上内容可以看出,MySQL中间件产品的设计与开发需要对相关协议有比较深入的了解,且因MySQL数据库软件自身的升级,协议还可能随之改变。限于篇幅,还有不少功能点不能一一细述,有兴趣者可查阅项目源码托管平台上的资源。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,607评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,047评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,496评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,405评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,400评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,479评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,883评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,535评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,743评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,544评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,612评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,309评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,881评论 3 306
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,891评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,136评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,783评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,316评论 2 342

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,579评论 18 139
  • 介绍 Atlas 是由 Qihoo 360公司Web平台部基础架构团队开发维护的一个基于MySQL协议的数据中间层...
    九都散人阅读 12,980评论 4 16
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,363评论 25 707
  • 产品需要定位,用户会对产品产生认知,即使用户无意识,实际上也会如此。 医疗类app将自身定位扩展到泛健康毋庸置疑,...
    lastinglulu阅读 197评论 0 0
  • 早上接到一个父亲的电话,表示自己有一个很大的困惑,我问他孩子的名字,他说不能说,说了担心孩子会受影响。他的...
    阿珠zhu阅读 480评论 0 1