本文来自网易云社区
网易作为国内领先的互联网技术公司,拥有众多的互联网产品与移动手机客户端应用,例如大家耳熟能详的网易博客、云阅读、云音乐、易信等。数据库作为支撑互联网产品最核心的后台服务,对产品的重要性不言而喻。随着产品数量以及应用规模的急剧增长,数据库管理逐渐成为产品发展的瓶颈:
硬件采购周期长,沟通协调成本高,数据库部署需求难以得到快速响应;
硬件利用率低,资源难以做到按需使用,弹性扩展;
服务可用性差、数据可靠性难以保证;
运维自动化程度低,人力成本高;
监控报警不够完善,出现问题难以诊断。
上述问题暴露出当前的数据库管理模式已经难以满足快速发展的互联网世界多变的需求,一个全新的,集中式的,更加智能的数据库管理模式呼之欲出。
网易云数据库(Netease RDS)是由网易数据库技术团队基于开源的MySQL打造的关系数据库云托管平台,构建于网易私有云IaaS服务之上,面向网易众多的互联网和移动终端产品,旨在解决当前数据库管理遇到的诸多问题,提供数据库实例管理、备份管理、在线ScaleUp、高可用、计划任务、监控报警、平台管理员等7大类功能,如图1所示。
图1 网易云数据库核心功能
图2 网易云数据库架构
图2为网易云数据库的总体架构图,下面将详细介绍各个模块扮演的角色和主要功能。
NVS:网易私有云云主机服务,作为MySQL实例的载体,提供数据库所需的CPU、内存和网络资源。每一个MySQL实例都单独部署在一个虚拟机中,管理服务器通过NVS提供的API创建、删除和扩展虚拟机。此外,NVS还提供了安全组功能,能够控制外部访问的IP和端口。
NBS:网易私有云云硬盘服务,向云关系数据库提供远程块设备存储资源。MySQL的数据文件,日志文件等都存在NBS中。NBS支持共享和独享两种硬盘类型,SSD和HDD两种磁盘介质,管理服务器通过API可以创建、删除和扩展硬盘空间。
NOS:网易私有云对象存储服务,向云数据库提供文件存储资源。所有的数据库备份文件都存储在NOS中。NOS提供了类似AWS S3的API接口,允许上传、下载删除对象。
管理服务器:整个系统的调度控制模块,负责实例管理、备份管理、计划任务、高可用、在线ScaleUp、平台管理员、计费相关功能。管理服务器对外负责处理所有来自用户的Http管理操作请求,对内通过调用NVS、NBS、NOS提供的API控制底层的计算、存储和网络资源。
为了实现高可用,通常管理服务器部署在三个物理节点上,利用Zookeeper提供的分布式锁的功能,只有一个对外提供服务。如果该服务器宕机,则系统利用Zookeeper提供的选主的功能选出一个新的节点对外提供服务。
图 3 管理服务器功能模块
图3展示了管理服务器的功能模块,主要包括3层,第一层API层,负责定义数据库资源和封装管理操作,对外提供API接口。第二层管理流程层,负责实现所有的管理操作业务逻辑。第三层,调度控制和外部通信层,主要负责控制和调度所有的管理业务流程,同时封装对外通信的接口。
管理服务器是整个系统的核心,相当于系统的“大脑”。所有的管理操作都是由管理服务器负责触发、组织和实施的。在设计管理服务器时,我们主要面临着两个问题:第一,通常一个完整的数据库管理流程包含较多步骤,而这些管理流程经常需要动态的添加和修改,所以系统的扩展性和可维护性非常重要。第二,所有的实例都由管理服务器集中管理,如果出现网络或者其他硬件、软件故障,造成实例大面积宕机,就会出现大量实例进行故障恢复的情况,而在故障恢复中实例存在重建的可能,这样就会对底层云主机、云硬盘服务造成“风暴”,严重甚至会导致整个系统瘫痪,所以限流尤为关键。
为解决上述两个问题,我们在管理服务器中使用了“工作流”和“队列”的设计。每一个管理流程都被系统定位为一条工作流,每条工作流都是由多个可重复执行的原子操作组成。工作流上的操作都是由线程池中的不同的线程负责完成的,任务之间的并发控制在定义工作流时指定,然后由工作流调度控制模块负责执行。所有的工作流都被定义在一个XML文件中,支持动态修改。这样,动态的添加或者修改管理流程成为一件非常容易的事情。为了达到“限流”的目的,我们设计了一个权重队列,所有进入队列的任务在进入队列时会调用一个外部定义的权重计算函数,计算该任务的重要程度,然后进行排序,最重要的任务位于队首,优先执行。队列可以设置任务执行的速度,同时允许禁止任何任务执行。
Agent:管理服务器在虚拟机的内部代理,和MySQL实例一起部署在虚拟机中,负责执行管理服务器对MySQL实例的管理操做,同时还负责收集数据库层的监控信息。
其他模块:系统库,负责存储数据库实例、备份的元数据信息,作为管理服务器的持久化组件;监控报警服务:负责整理所有的监控信息,允许用户设置报警条件,并在系统达到预设值后,进行报警;日志分析系统:收集所有组件的日志信息,按照用户、实例、节点进行归类整理,进行跟踪报警;认证授权:负责云服务用户的注册、登陆、权限认证等功能。
此外,系统还使用了开源组件ZeroMQ和Zookeeper。
ZeroMQ:消息队列,负责管理服务器和Agent之间的消息通信。ZeroMQ是一种更为轻量级的消息队列,与传统的AMQP协议的消息队列不同,它不需要独立的消息服务器,只需要引用一个lib库即可实现节点之间的通信。因为异步传输、LockFree、消息不持久化等特性,ZeroMQ相比其他消息队列具有更高的消息通信效率。ZeroMQ的设计理念是专注于底层消息的通信,所以ZeroMQ不负责消息的持久化和序列化。对于持久化问题,上层应用可以通过消息重发来保证消息的可靠传输,但是这需要接收方能够判别重复消息,这个可以通过版本号的机制解决,即每一个消息都附带一个版本号字段,重复消息使用相同的版本号,接收方记录当前的版本号,如果出现等于或者小于当前版本号的消息,则认为是重复消息。对于序列化的问题,可以使用google的开源序列化框架protobuf实现。
Zookeeper:开源的针对分布式系统的可靠协调系统,在云数据库中主要实现多个管理服务器之间的分布式锁、统一配置管理和选主的功能。管理服务器在启动时,会去Zookeeper上生成一个有序节点,同时如果该节点不是最小节点,则需要watch前一个比它小的节点,只有最小节点的管理服务器对外提供服务。如果该服务器宕机,则watch该服务器对应节点的standby节点被唤醒,成为新的对外服务节点,这样避免了多个standby 同时watch对外服务节点造成的“惊群现象”。同时,watch宕机节点的所有Agent被唤醒后,会从Zookeeper上获取新的管理服务器节点的信息,完成了配置修改。
由于云托管的服务器相比专用的硬件可靠性有显著下降,所以高可用是云数据库首要解决的问题。实现高可用唯一的途径就是增加冗余,实现自动故障切换。目前现有的业界方案:
DRBD:块级别的同步复制,不仅管理复杂,且存在严重的性能开销。
共享存储:在主机宕机后,从机通过挂载到主机的文件系统上,在主机的数据上执行恢复操作。宕机时间取决于存储引擎的恢复以及预热的速度,通常难以做到1分钟内故障恢复。
复制:使用标准的MySQL复制实现主从同步,目前现有的两种实现:MMM和MHA。MMM不保证数据一致性,MHA需要主机宕机后依然能够通过ssh获取到主机的二进制日志。
网易云数据库选择基于MySQL复制实现高可用,面临的技术难点主要包括数据一致性的保证和实时故障切换:
数据一致性:官方版本的MySQL复制是异步复制,主机上的事务提交以后才会发送给从机,如果在发送给从机前主机宕机,此时主从切换会出现主机上已提交的事务丢失的问题,切换后数据不一致。5.5版本以后MySQL推出了半同步复制,虽然将返回客户端成功与发送从机同步起来,但是还是没解决丢数据的问题。为了保证主从数据的一致性,网易MySQL技术组修改了主机事务提交次序,主机上的事务只有得到从机的确认后才会提交,在内部我们称之为虚拟同步复制(Virtual Sync Replication)。Oracle官方的MySQL 5.7也已经支持类似同样的功能,相信这会成为今后MySQL数据库高可用的一种标准手段。此外,为了保证主机写入性能不受影响,我们在二进制日志层做了GroupCommit减少fsync的次数,提高了二进制的写入性能。经过测试,虚拟同步复制的性能完全能够达到甚至超出MySQL原生异步复制的性能水平。需要注意的是,考虑到从机SQL单线程回放效率的问题,我们这里仅仅是将主机上的更新写入从机的relaylog后即返回,而不是等到从机完全apply该更新(全同步复制),所以从机可能立即读不到这部分更新,这就需要在主从切换后,需要将从机所有未apply的relaylog全部回放完毕后,再提供给用户读写,这就引入了第二个问题,实时切换。
图4 复制过程中事务提交流程
实时切换:由于MySQL复制的过程从机是单线程回放主机上的更新,所以往往会出现从机落后的情况。而为了保证数据的一致性,主从切换后从机落后的时间服务是不可用的,所以要实现实时切换,从机使用多SQL线程并行复制是一种有效解决方案。MariaDB提供了基于行的并行复制,要求是Row格式的二进制日志。我们采取了类似MariaDB的实现方式,根据表的主键判断两个事务是否冲突,从机按照事务分发线程,如果一个事务的更新中包含上一个事务更新涉及的主键,必须等待上个事务执行完后才可执行,否则可并发执行。更重要的是,网易MySQL技术组还实现了并行复制的crash safe功能,保证在意外宕机情况下,依然能够保证主从数据的一致性。
主从切换后,需要对原先的宕机的数据库实例进行修复操作,首先就是要重启。但是我们从图4的事务提交流程可以看出,虚拟同步复制主机事务提交先写入二进制日志,然后再发送给从机,如果在这个过程中主机宕机,就会出现主机上有一部分未提交的二进制日志,而这部分日志中涉及的事务更新也未在从机执行。对于未提交的二进制日志中的事务,MySQL会在系统启动时自动提交,这样就会出现数据不一致的问题。所以我们在重启前,先对二进制日志进行了修剪,去掉了这部分二进制日志,这样就保证了启动后的该实例和当前服务的实例数据一致性,然后再建立到当前对外服务实例的复制关系即可。如果重启失败,则系统会将该实例提交给重建队列进行重建。
除了可靠性,可预测性与控制能力也是云托管的服务器相比专用硬件的软肋,所以完善的监控和运维平台是云数据库能够稳定运行的基本保障。
系统监控,主要采用两种方式:主动探测和问题跟踪。所谓主动探测是指由统一的检测程序定期的调用底层服务和依赖模块的接口,这种方式能够提前发现问题,防患于未然,对于网络、系统库等调用代价不大的接口非常有效,但是对于创建云主机、云硬盘等接口,调用代价过大,并不适用。这时,事后的问题的跟踪和分析变的异常重要,而日志是最主要的技术手段。对于日志按照输出级别进行归类整理,对于错误日志,按照错误标识进行相应的报警。
从网易云数据库的系统架构可以看出,系统作为上层PaaS服务,依赖众多的底层IaaS服务,同时作为一个分布式系统,拥有管理服务器、Agent、计费、认证等多个模块,分散的日志首先需要有统一的格式和规范,这个规范必须能够帮助运维人员快速定位到出现问题的服务和模块,同时体现服务和模块之间的调用关系。网易私有云统一日志格式如下:
ID:用户请求的唯一标识符,由最上层服务在处理用户请求时生成,并由上层服务在调用底层服务时传给底层服务。
Seq:同一请求在同一模块内的日志写入序号,格式为“x.x.x”,用户请求每次跨越模块,Seq递加一层(如从“x.x”,扩展到“x.x.x”)。同一模块内每次写入日志或者调用其它模块前对本层级的seq值加1(如“2.1”到“2.2”)。该值随着服务和模块之间的相互调用进行传递。
Timestamp:打印日志的时间戳。
Level:日志输出级别,可选值有error、warn、info和debug。模块内部日志使用debug,模块之间的调用使用info。
Module:输入日志的模块和服务名称。
Ip:产生日志的服务器IP。
Identifier:用户的标识符。
Op: 日志执行的操作。
Object:操作对象信息,使用Json格式。
description:日志详情,须包含全部异常堆栈。
整个日志规范中最为核心的就是ID和Seq字段,ID是连接多个服务和模块的线索,Seq是体现服务和模块之间调用层级关系的标识。一次云数据库创建请求的ID和Seq变化如图4所示。
图 5 统一日志ID和Seq变化
有了统一的日志格式,剩下的就是一个能够提供日志收集,归类、分析和展示的运维平台。我们利用公司内部的一个日志收集和分析平台LogTracer来收集各个底层服务和系统内部模块的日志,然后进行统一的分类、标注和归档,最后存储在Mongodb中,运维人员登陆运维平台,即可方便的根据请求ID,模块、日志级别等进行检索,同时能够展示出清晰的服务和模块之间的调用关系。
图6 运维平台统一日志
数据库的扩展主要分为两类:ScaleUp和ScaleOut。ScaleUp是指通过增加一台服务器的资源来增强数据库实例的处理能力。资源的动态伸缩是云最显著的优势,所以在云环境下ScaleUp将会变得非常容易。但是底层资源的伸缩过程中,会出现服务的中断,造成数据库的不可用,所以云数据库的ScaleUp需要解决的是资源扩展过程中服务可用性的问题。
借鉴高可用的设计思路,可以通过创建冗余,在从机上先进行ScaleUp,然后通过一次主动的主从切换,将服务切换到已经完成ScaleUp的实例上,从而完成不停服的在线ScaleUp过程。
图 7 云数据库在线ScaleUp
虽然ScaleUp在大多数情况下都能够满足产品的需求,但是单台数据库的性能总是有上限的,尤其是在云环境下,由于各种资源的限制,导致数据库会更早的到达性能瓶颈,这时ScaleOut成为用户的必然选择。ScaleOut是指通过将用户请求分布到多个数据库实例上来提高整体的处理能力。按照网易私有云的规划,网易云数据库并不直接提供用户sharding的功能,而是作为另外一个私有云PaaS服务分布式数据库的底层节点对外提供服务。分布式数据库服务直接利用云数据库提供的API实现数据库实例的操作和管理,然后在上层实现sharding的功能。
云计算拥有低成本、高资源利用率、可扩展等诸多优势,是企业未来资源管理的发展方向。但是云计算并不是天生为数据库设计的,在云端使用关系数据库面临着软硬件可靠性差、可预测性低和控制能力弱等诸多挑战,网易云数据库在架构设计中充分考虑了上述因素的影响,通过虚拟同步复制实现了完全可靠的高可用,通过提供了统一的日志跟踪运维平台方便故障排查和分析,同时提供了在线ScaleUp的功能满足用户自动扩展的需求。目前,已有较多的网易产品使用云数据库。
虽然云数据库提供的功能已经能够满足大多数网易产品的需求,但是仍有较多改进和发展的空间。例如,当前的我们是基于KVM来实现底层计算资源的虚拟化的,未来我们倾向于LXC(Linux Container)更轻量级的虚拟化技术,在功能方面,我们会提供多版本管理等满足更多用户的需求。
网易云新用户大礼包:https://www.163yun.com/gift
本文来自网易云社区,经作者郭忆授权发布。