低成本和高性能MySQL云数据的架构探索

转载 2013年12月03日 20:20:33

MySQL作为一个低成本、高性能、可靠性好而且开源的数据库产品,在互联网企业应用非常广泛,例如淘宝网有数千台MySQL服务器的规模。虽然近两年来NoSQL的发展很快,新产品层出不穷,但在业务中应用NoSQL对开发者来说要求比较高,而MySQL拥有成熟的中间件、运维工具,已经形成一个良性的生态圈等,因此从现阶段来看,MySQL占主导性,NoSQL为辅。
在过去一年时间里,我们(阿里集团核心系统数据库团队)在MySQL托管平台方向做了大量工作,设计和实现了一套UMP(Unified MySQL Platform)系统,提供低成本和高性能的MySQL云数据服务。开发者从平台上申请MySQL实例资源,通过平台提供的单一入口来访问数据,UMP系统内部维护和管理资源池,以对用户透明的形式提供主从热备、数据备份、迁移、容灾、读写分离、分库分表等一系列服务。平台通过在一台物理机上运行多个MySQL实例的方式来降低成本,并且实现了资源隔离,按需分配和限制CPU、内存和IO资源,同时支持不影响提供数据服务的前提下根据用户业务的发展动态的扩容和缩容。

架构的演变
UMP系统第一版基于mysql-proxy 0.8版修复若干bug,并对proxy插件中管理用户连接和数据库连接的状态机流程进行一些修改,同时编写Lua脚本实现去中心数据库获取用户认证信息和后台数据库地址,对用户进行验证,建立到后台数据库的连接和转发数据包等逻辑。

图1 UMP系统的第一版采用MySQL Proxy

在开发和部署第一版的过程中,我们逐渐认识到几个问题:

首先,mysql-proxy 0.8版对多线程的支持比较简单粗暴,多个工作线程共享同一个消息队列,同时监听着同一个socketpair通道,当有新事件进入消息队列后,socketpair会被写入一个字节,所有休眠中的线程都会被唤醒,去竞争一个互斥锁从消息队列中取任务。这种实现一是造成“惊群”现象,多个线程被唤醒但只有一个线程需要去任务,二是任务的CPU亲缘性比较差,在同一个状态机上触发的事件会在多个处理器上来回切换执行。此外,mysql-proxy中还使用了全局Lua锁,同时仅允许一个工作线程执行Lua脚本(计划在0.9版本中改进),因此mysql-proxy多线程模式下的性能远不能同CPU核数保持线性增长,甚至在16核上的性能还不如4核。而使用单进程模式时,一台物理机上需要部署多个进程才能有效利用机器的处理能力,但给部署、监控和服务的升级带来麻烦。
其次,限于mysql-proxy的框架,功能上不容易扩展,实现用户的连接数限制、QPS限制、以及主从切换、读写分离、分库分表等一系列功能比较困难。
最后,mysql-proxy的社区近些年来并不活跃,而且C语言对开发者功底的要求比较高,很难要求团队所有成员协同开发出兼顾优雅和正确性的代码。
因此我们决定用Erlang语言重新编写proxy服务器,替换了原有的mysql-proxy模块。目前整个项目拥有5万行Erlang源码,3万行C/C++源码,2万行其他语言源码。

为什么选择Erlang语言
Erlang是一个结构化的、动态的、函数式的编程语言。常见的一个说法是Erlang是面向并发的(concurrent-oriented),这主要指Erlang在语言中定义了Erlang进程的概念和行为(下文中凡是“Erlang进程”都是指Erlang语言中定义的进程,以区分于大家熟悉的操作系统进程),和操作系统的进程/线程相比,Erlang进程同样是并发执行的单位,但特别的轻量级,它是在Erlang虚拟机内管理和调度的“绿进程”,即用户态进程。举个例子,在关闭了HiPE和SMP支持的Erlang虚拟机中,一个新创建的进程占用的内存仅为309个字(word,64位服务器上为8个字节),其中233个字为堆空间(包含栈),创建和结束一个进程的代价约耗时1~3微秒,而一个Erlang虚拟机中可以同时支持几十万甚至更多个进程。

图2 Erlang的轻量级进程

说到Erlang语言,就必须提及OTP(Open Telecom Platform,开放电信平台),OTP是用于开发分布式的、高容错性的Erlang应用程序的框架与平台。例如,一个Erlang节点连接并注册到Erlang集群上,发现集群中的其他节点,与它们进行RPC通信,都在OTP里的kernel服务中实现的。OTP和Erlang语言关系如此紧密以至于两者通常合称为Erlang/OTP,因此从严格的意义上来讲,应该说我们选择了Erlang/OTP为主来构造UMP系统。Erlang/OTP很好的抽象了开发一个分布式的、高容错性的应用程序所需的要素,包括:网络编程框架、序列化和反序列化、容错、热部署。
为了支持并发,服务器端多采用多进程/多线程模型,即每个进程/线程处理一个客户端连接,受限于操作系统资源,每台服务器可以处理的并发连接数并不高,同时由于进程/线程上下文切换开销,系统的性能会受到影响。而开发高并发、高性能的服务器一般采用事件驱动的状态机模型,底层采用非阻塞I/O(Linux中的epoll,BSD系统中的kqueue,Java中的nio)或者异步I/O,或者采用异步的事件通知的I/O框架,例如C/C++下的ACE、boost::asio、libevent,Java下的MINA等,在业务层则使用状态机来表示每个客户端连接,通过I/O事件、超时事件驱动着状态机进行跳转,每个进程/线程可以处理成千上万个客户端连接。事件驱动的状态机模型和多进程/多线程模型相比虽然并发量更大、性能更好,但是把业务逻辑表达成状态机是一件困难的事情,相比而下,多进程/多线程模型中业务逻辑可以实现为顺序执行的代码,开发起来要简单的多。
Erlang/OTP中的网络编程模型则结合了两者的优点,每个Erlang进程处理一个客户端连接,业务逻辑是顺序执行的。而Erlang进程是极轻量级的,可以认为每个Erlang进程是一个状态机,堆和栈上的数据是这个状态机的状态,而Erlang进程收到数据包或是其他进程发来消息后执行处理例程相当于状态机的跳转,因此也具有高并发和高性能的优势。
Erlang/OTP定义了“external term format”协议将Erlang数据结构与二进制串相互转化,用C实现在Erlang虚拟机中,跨节点通讯时遵从这个协议。因此,开发者无需额外考虑序列化和反序列化的问题。
至于容错,Erlang进程的数据空间是相互隔离的,没有共享内存,因此一个Erlang进程崩溃不会影响其他Erlang进程的运行,更不会造成Erlang虚拟机崩溃。OTP还提供了监督树机制和heart模块,前者在监控到Erlang进程崩溃时进行故障恢复,后者发现Erlang虚拟机失去响应时重启程序。
Erlang/OTP提供热部署方式,可以避免服务升级时造成不可用时间。此外,OTP还提供了一些在系统运行时观察系统状态的工具,例如lcnt工具,可以统计虚拟机内部的锁使用次数和冲突次数,指导系统的优化。

当前系统架构
在设计UMP系统时,我们遵循了以下几条原则:
l 系统对外保持单一入口,对内维护单一的资源池。
l 保证服务的高可用性,消除单点故障。
l 保证系统是弹性可伸缩的,可以动态的增加、删减计算与存储节点。
l 保证分配给用户的资源也是弹性可伸缩的,资源之间相互隔离。

UMP系统中的角色包括:controller服务器、proxy服务器、agent服务器、API/Web服务器、日志分析服务器、信息统计服务器。
依赖的开源组件有:Mnesia、LVS、RabbitMQ、ZooKeeper

图3当前UMP系统架构图

Mnesia是OTP提供的分布式数据库,与MySQL NDB出自同门,都是上世纪90年代中期Ericsson为电信业务研发的数据产品。Mnesia支持事务,支持透明的数据分片,利用两阶段锁实现分布式事务,可以线性扩展到至少50个节点。从CAP理论的角度上来说,Mnesia更倾向于牺牲可用性来换取强一致性,属于CP阵营,但它也提供了脏读、脏写操作,可以绕过事务管理去操作数据,这时不保证一致性,这又类似于AP的系统。在工程实践中,我们用事务去修改关键数据例如路由表,而用脏写接口去写非关键数据例如用户的状态信息,读取数据用脏读接口。
Controller服务器向UMP集群提供各种管理服务,实现元数据存储、集群成员管理、MySQL实例管理、故障恢复、备份、迁移、扩容等功能。Controller服务器上运行了一组mnesia分布式数据库服务,系统的元数据比如集群成员,用户的配置和状态信息,以及用户名到后端MySQL实例地址的映射关系(路由表)等都存储在mnesia里,其它服务器组件通过发送请求到controller服务器获取用户数据。为了达到高可用性,系统中会部署多台controller服务器,它们会通过ZooKeeper提供的分布式锁算法选举出一个leader,这个leader负责调度和监控各种系统任务,例如创建和删除数据库实例、备份、迁移等。这些系统任务可以分成多个步骤,而且会涉及到系统中的多个组件,例如主库、从库、proxy服务器等,还需要提供失败时回滚的方法,因此我们采用类似工作流的方式来实现。每个系统任务都是分成多个阶段的Erlang进程,每执行完一个步骤跳进入下个步骤之前会把中间状态持久化到mnesia中,如果任务因为节点故障的原因停止,leader会检测到并重新发起该任务,任务重启后会从上一次失败的“断点”继续向下执行。
API/Web服务器向用户提供了系统管理界面。它们是基于开源项目Mochiweb与Chicago Boss开发的,Mochiweb提供http/https服务,而Chicago Boss是由Nginx的作者之一Evan Miller开发,提供类似Rails的MVC框架。和Rails比,Erlang开发的框架天生就对并发有很好的支持,每个请求占用一个轻量级的Erlang进程,而Rails虽然在最近引入了多线程安全,但处理每条请求的时候仍然是独占整个进程的,因此需要使用多进程模型处理并发请求,通过Phusion Passenger等应用服务器进行派发。
Proxy服务器向用户提供访问MySQL数据库的服务,它完全实现了MySQL协议,用户可以使用已有的MySQL客户端连接到proxy服务器,proxy服务器通过用户名获取到用户的认证信息、资源配额的限制(例如最大连接数、QPS、IOPS等),以及后台MySQL实例的地址(列表),再将用户的SQL查询请求转发到正确的MySQL实例上。除了数据路由的基本功能外,Proxy服务器中还实现了资源限制、屏蔽MySQL实例故障、读写分离、分库分表、记录用户访问日志的功能。Proxy服务器是无状态的,服务器宕机不会对系统中其他服务器造成影响,只会造成连接到该proxy的用户连接断开。多台Proxy服务器采用LVS HA方案实现负载均衡,用户应用重连后会被LVS定向到其他的proxy上。
Agent服务器部署在运行MySQL进程的机器上,用来管理每台物理机上MySQL实例,执行创建、删除、备份、迁移、主从切换等操作,收集和分析MySQL进程的统计信息、bin log、slow query log。
日志分析服务器会存储和分析Proxy服务器传入的用户访问日志,并实现了实时索引供用户查询一段时间内的慢日志和统计报表。信息统计服务器定期将采集到的用户的连接数、QPS数值,以及MySQL实例的进程状态用RRDtool进行统计,可以画图展示到Web界面上,也可以为今后实现弹性的资源分配和自动化的MySQL实例迁移提供依据。
UMP系统中各节点间的通信(不包括SQL查询、日志等大数据流的传输,这些还是直接走TCP的)都通过RabbitMQ,作为消息通讯的中间件来使用,来保证消息发送的可靠性。ZooKeeper则主要发挥配置服务器、分布式锁,以及监控所有MySQL实例的作用。在多个组件的协同作业下,整个系统实现了对用户透明的容灾、读写分离、分库分表功能。系统内部还通过多个小规模用户共享同一个MySQL实例,中等规模用户独占一个MySQL实例,多个MySQL实例共享同一个物理机的方式实现资源的虚拟化,降低整体成本。在资源隔离方面,通过Cgroup限制MySQL进程资源,以及在proxy服务器端限制QPS相结合的方法,UMP系统实现了资源虚拟化的同时保障用户的服务质量。此外,UMP系统综合运用SSL数据库连接、数据访问IP白名单、记录用户操作日志、SQL拦截等技术保护用户的数据安全。

结束语

UMP系统的一些组件,例如proxy服务器和日志分析服务器,目前已经运用在天猫的聚石塔平台中,为电商和ISV提供安全的数据云服务。此外,UMP系统还运用在淘宝的店铺装修平台中,为开发者提供数据服务。下一阶段,我们希望UMP系统可以为进一步降低集团内部数据存储的成本做出贡献。

附上UMP portal部份截屏:

图4 MySQL实例情况

图5 用户实例管理

图6 dashboard

祝玩得开心!

Post Footer automatically generated by wp-posturl plugin for wordpress.

低成本和高性能MySQL云数据库架构探索

低成本和高性能MySQL云数据库架构探索 2012年09月13日12:21 it168网站原创 作者:景保玉 编辑:景保玉 我要评论(0) 标签: mysql   【IT16...
  • ly4983
  • ly4983
  • 2014年01月19日 14:50
  • 601

(转载:太经典)低成本和高性能MySQL云数据的架构探索

转载:http://blog.yufeng.info/archives/2349 MySQL作为一个低成本、高性能、可靠性好而且开源的数据库产品,在互联网企业应用非常广泛,例如淘宝网...
  • zhangxinrun
  • zhangxinrun
  • 2012年10月31日 18:38
  • 3554

高性能mysql第三版 免费下载

下载地址:高性能mysql第三版.pdf
  • jiongyi1
  • jiongyi1
  • 2017年11月22日 01:19
  • 197

淘宝曹伟分析低成本、高性能MySQL云数据架构

http://www.infoq.com/cn/news/2012/10/taobao-ump 作者 郑柯 发布于 2012年10月25日 曹伟是淘宝数据库研发组的成员,前不久他在内部...
  • washingto
  • washingto
  • 2012年11月15日 22:59
  • 1829

《高性能MySQL》读书笔记--多版本并发控制算法

InnoDB存储引擎MVCC的实现策略: 在每一行数据中额外保存两个隐藏的列:当前行创建时的版本号和删除时的版本号(可能为空)。这里的版本号并不是实际的时间值,而是系统版本号。每开始 个新的事务,系...
  • xifeijian
  • xifeijian
  • 2015年04月25日 22:45
  • 6949

《高性能MySQL》读书笔记(上)

《High Performance MySQL》真是本经典好书,从应用层到数据库到硬件平台,各种调优技巧、常见问题全都有所提及。数据库的各种概念技巧平时都有接触,像索引、分区、Sharding等等,但...
  • dc_726
  • dc_726
  • 2014年12月06日 19:31
  • 6496

《高性能MySQL》读书笔记--查询性能优化

对于高性能数据库操作,只靠设计最优的库表结构、建立最好的索引是不够的,还需要合理的设计查询。如果查询写得很糟糕,即使库表结构再合理、索引再合适,也无法实现高性能。查询优化、索引优化、库表结构优化需要齐...
  • xifeijian
  • xifeijian
  • 2015年05月09日 20:34
  • 8527

MySQL高性能优化

表的优化与列类型选择表的优化1、定长与变长分离定长:id int 占 4 个字节,char(4)占 4 个字符长度等等核心且常用字段,应该建成一个定长,并放在一张表。变长字段:varchar、text...
  • xsj_blog
  • xsj_blog
  • 2017年07月08日 16:23
  • 330

高性能MySQL之运行机制

MySQL服务器逻辑架构 最上层:链接处理,授权认证,安全等处理 第二层:查询解析、分析、优化、缓存以及内置函数(如:日期,时间,数学和加密函数) 第三层:包含了存储引擎,存储引擎负责数据的存储和提取...
  • abundantstudy
  • abundantstudy
  • 2017年03月15日 18:04
  • 1928

【学习笔记】高性能MySQL(第三版)——第1章:MySQL架构与历史

MySQL并不完美,却足够灵活,能够适应高要求的环境,例如Web类应用。同时,MySQL既可以嵌入到应用程序中,也可以支持数据仓库、内容索引和部署软件、高可用的冗余系统、在线事务处理系统(OLTP)等...
  • qq157962718
  • qq157962718
  • 2016年03月28日 01:08
  • 725
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:低成本和高性能MySQL云数据的架构探索
举报原因:
原因补充:

(最多只允许输入30个字)