什么样的云数据库架构选型才能做到安全,稳定又可靠?
更多深度文章,请关注云计算频道:https://yq.aliyun.com/cloud
摘要:从传统IT部署到云,人肉运维已经是过去式,云上运维该怎么开展?人工智能对于运维“威胁论”也随之袭来,如何去做更智能的活,当下很多运维人在不断思考和探寻答案。在2017云栖社区运维/DevOps在线技术峰会上,阿里云数据库技术专家喜乐就为大家分享了对于云数据库的选型的考量和云数据库的使用经验以及对于云数据库未来的展望,精彩不容错过。
以下内容根据演讲视频以及PPT整理而成。
演讲者简介:
喜乐,阿里云数据库技术专家,2010年加入阿里巴巴,最近四年时间一直在数据库技术组,专注于云数据库的业务和架构。
本次分享主要分为以下四个部分:
一、背景
二、云数据库架构选型
三、云数据库的使用经验谈
四、展望未来
一、背景
近几年,DevOps一直都是一个特别火的话题,DevOps旨在将开发、线上部署、运维、质量控制以及技术运营等全部工作都整合在一个团队里,通过团队成员之间的紧密配合实现产品的快速迭代。曾经有的技术团队做到了在一天之内发布产品10次以上,如果技术团队拥有了DevOps的能力之后,这个团队的产品就能够实现在线上进行快速迭代,也就能够适应互联网飞速发展环境下的业务需求。
本次分享的主题主要与数据库相关,将主要为大家介绍作为一名开发人员需要掌握哪些最关键的数据库技术点,希望本次的分享能够为大家在架构的设计、线上运维以及问题的排查等方面提供一些帮助和指导,也希望大家能够通过学习数据库技术进一步提升自己的DevOps能力。
二、云数据库架构选型
如今包括企业级产品在内的互联网产品越来越丰富,传统的数据库产品只有OLTP和OLAP的,但是在未来数据库产品会越来越多样化。目前的阿里云的数据库产品也已经非常丰富了,可以提供比如像传统的MySQL、SQL Server、PG、HBASE、Redis以及MongoDB等数据库产品,而且如果单机无法存储全部数据还会提供数据库分片技术。目前,数据库的形态越来越多,所以大家可能在数据库的选型上会产生一些困惑,本次分享会为大家介绍一些与数据库选型相关的知识,链路的形态、安全性、可靠性、易用性、还有应用的架构和业务的类型,这些方面都会影响大家对于数据库选型的考量。
阿里云能够提供多种类型的云数据库。接下来首先介绍一下数据库架构三种最基本的形态,下图中最左边是一种传统的主备架构,这种架构采用的都是本地存储的方式而非共享存储,前面会使用LVS。对于这种架构而言,在通常情况下,用户只会连接到主数据库上,而备库采用热备的方式进行实时地数据同步。
上图中的第二种形态是一个三节点的数据库架构,相比第一种架构,这里面加入了一个Hidden节点。在双节点时通过MySQL具有的半同步机制基本上可以做到数据不丢失,但是在极端的情况下,比如在网络和主机同时故障的时候或者备库存在延迟的情况下,数据可靠性就可能得不到保证。当使用了三节点之后,主库写入任何一条数据时,都要让事务传入到其中的一个备库上,之后才能够返回给用户,这样就保证了数据一定是在两个节点同时写入的,这就是三节点的最基本模型。当然这个模型还可以扩展成为五节点、七节点这样的模型,以前的一些分布式数据库就是依靠这样的模式来实现的,这样能够在出现数据库的单点故障时保证数据的零丢失。
上图中的第三种形态是一种共享存储的数据库架构,通常情况下只存在一个主数据库,后面存在多个备库,但是中间的存储却只有一份,主备数据库都将数据写到共享存储上。当然对于共享存储而言,一般也会存储三份。这种架构和前面提到的第二种架构的差别在于:在第二种架构方式中,当切换到备库之后,就直接基于备库本地存储的数据对外提供服务,而第三种架构则是使用原来的共享存储,实际上还是原来那份存储提供服务,这就会涉及到对于日志进行应用,所以会需要多花费一些时间,但是上面Master和Slave节点的服务器实际上是无状态的,这样的架构下所能提供的数据可靠性就会更强一些。这三种架构目前已经应用于MySQL、SQL Server、PG、Redis、MongoDB这几种基础的数据库中了。
下图的架构就是Redis Sharding的结构,顾名思义其就是一种分片的结构。大家可以看到图中存在Proxy节点也就是mongos中间节点,其下面则是刚才提到的主备的结构。所有的数据都会按照一种分片的规则路由到下面的某一个分片上来提供服务,而路由的规则则会存储在一个组件上,这就是一种典型的分片结构。这里的结构在前面只加了一个LVS,所以整个Sharding只有一个VIP。
下图是MongoDB Sharding的结构,当数据量超过单机的承受能力之后,往往需要进行横向的扩展,此时就可以采取这样的Sharding结构。其下面的每一个分片都是之前提到的三节点的结构形态,通过多个mongos将他们组合起来,每一个mongos前面都会架设一个VIP,也就是说用户购买了这样的MongoDB Sharding之后会拿到多个VIP,这样在使用上就会更加灵活。
三、云数据库使用经验谈
接下来就为大家分享关于云数据库使用方面的经验之谈。对于云数据库的使用而言,如果想要做到安全,稳定又可靠,其实存在很多关键点,其中比较重要的就如同下图中所列举出来的这些点:应用数据源配置、报警配置、可运维时间选择、慢SQL监控及优化、参数选择、主备数据库之间的同步方式、数据备份、日志备份、账户管理、存储架构、网络安全以及架构安全等,在后面将会为大家进行更加详细的介绍。下图中左边的是整个系统从底层的硬件和操作系统一直到最上面的应用系统的分层结构。今天主要分享的就是数据库的服务,相应的就是红框里这部分,也就是应用架构到数据库服务这两层之间的部分,这里就涉及到设计、优化以及配置。
应用数据源配置
关于应用数据源配置,首先建议所有应用系统在使用云数据库时要使用长连接,这样应用程序就能够使用连接池,使用长连接的消耗最小并且不必每次都建立连接。其次就是应用程序应该能够自动进行重连,也就是说当网络发生变更的时候或者当数据库的主库发生故障发生自动切换的时候,如果应用程序具有自动重连的机制就可以做到在几秒之内自动重新连接到新的数据库上,这样对于应用程序的影响也会是最小的,所以应用程序一定要能够进行自动重连。第三个建议就是对于连接池超时的配置,这部分至少需要连接超时、socket超时这两个配置,链接超时指的是判断首次进行TCP三次握手的时候发出ACK包的回包有没有超时;socket超时是指在建立连接之后,在向云数据库发送数据之后超时了,没有得到任何的回包,这有可能是在数据包发送的途中连接断开了,也有可能是数据包已经到达Server了,但是Server回包时超时了,这两种情况都可能造成socket超时。其实对于像Java这样比较成熟的语言而言,会具有像JDBC这样的驱动,还可能存在SQL Statement超时。SQL Statement超时不是数据库本身提供的,一般情况下是由客户端自己完成的,因为数据库采用的都是停等协议,当客户端给数据库发送一个SQL之后就会阻塞在这里,如果当SQL发出去了,到一定时间还没有返回SQL的查询结果,客户端就会再启动一个线程向数据库发送一个Kill的命令将之前的那个连接杀死,中间的这段时间就需要通过SQL Statement超时来进行设置。
另外,所有应用客户端连接池的最大连接数总和应小于数据库的最大连接数。通常情况下,可能会存在很多个应用连接数据库,这些应用去连接数据库时都会设置自己连接池的最大连接数,如果当所有的应用所设置的链接总数大于数据库所设置的最大连接数,就会发生将数据库的连接撑爆的情况。超过最大连接数之后再请求的连接就会被数据库服务器拒绝,这就会对于应用造成很大的伤害,所以推荐在实现客户端时或者开发同学在配置连接池时一定要保证客户端连接池的最大连接数总和小于数据库最大连接数。有的云数据库可以将连接数作为购买项进行设置的,也有的需要通过对于数据库参数的调整进行设置,大家需要根据自己所使用的数据库进行设置。
除此之外,如果应用能统计业务SQL的执行频率及执行时间的监控数据那就最好不过了。通常情况下按照三层设计的DAO层就是专门负责连接数据库的,希望大家能够对于这一层的代码进行切面,无论使用单个数据源还是多个数据源,都应该对于所有关于数据库的操作都要统计SQL执行频率和执行时间的监控数据,这样当每次进行应用发布的时候,如果增加或者修改了SQL就可以及时得到该条SQL在线上真正运行时的执行效果,这样对于应用问题的排查也会起到非常大的帮助。对于淘宝和天猫而言,都会有非常成熟的数据库执行频率和执行时间的监控,所以建议大家在开发自己的应用时也设计实现这样的模块,并且目前也已经出现了很多比较成熟的第三方库能够实现这些功能。
上图所展示的是DNS访问登到ECS上,ECS通过虚拟IP连接到数据库的一个数据链路。这是通常情况下的数据链路,除此之外还有一种Proxy链路,也叫作高安全链路,也就是在SLB后面会架设一个中间层Proxy。
报警配置
对于报警配置而言,其实云监控已经能够设置很多的报警了,但是通过数据统计发现通常情况下大家都不太关心这部分,这是不应该的。无论使用的是哪一个云数据库都应该在云监控上设置自己的报警,因为有一些阀值是根据应用的压力进行调节的,比如通常情况下,数据库服务器的压力是CPU可以跑到50%,那么可以设置阀值为70%,如果在某一次应用发布之后CPU的占用率一下子就大幅度上升了,此时给开发人员发一条短信或者报警就能够帮助开发人员及时发现线上数据库存在的潜在问题。
报警和监控其实分为两部分,一部分监控的数据采集包括了很多指标,比如CPU、内存、磁盘IO以及各种数据库引擎特殊的属性,这些指标希望大家都能够关注,因为监控已经将这些指标从曲线上拉取出来了,如果在指标的监控曲线上看到存在巨幅波动,一定是出现了应用系统的变更或者数据库的配置有所变更,这样大家就能够对于数据库性能上的指标有所了解。另外一个就是报警,当数据库存在问题的时候,可能最多是性能或者故障问题,大家可以及时收到报警的信息,不至于造成很大的损失。
除了上面所说的,还应该设置日志的管理,这里面包含了SQL日志和慢日志。SQL日志就是通常在数据库上执行的增删改查的SQL,如果开启了SQL审计就会将这些数据都统计下来;慢日志则是将应用连接上去之后根据大家设置的慢SQL的阀值而统计出来的运行稍慢的SQL,对于这些运行稍慢的SQL都是需要进行优化的。一些SQL需要运行数分钟甚至一个小时,这样的SQL对于数据库而言不是正常的,除非开发同学认为这条SQL是分析性的SQL,但是对于通常的OLTP的应用,是不应该出现需要运行数分钟甚至数小时的SQL的。除了之前所提到的诊断工具之外,阿里云还提供了实例诊断报告、资源分析以及SQL分析的服务。实例诊断报告其实是非常有用的,建议开发同学能够进行诊断,这样就能在诊断报告中体现出应用发布之后的全部影响,而且诊断报告中会对于重点的一些问题进行标记,比如CPU、内存以及IO等等,如果判定为不正常就会标红来提醒开发人员,减少了开发过程中的诊断工作。
可维护时间
刚刚接触数据库的同学可能不太了解可维护时间这个概念,其实可维护时间和之前提到的链路是紧密相关的,通常情况下即使自己搭建数据库,也会出现数据库损坏、升级、重启或者网络需要进行变更的时候,这个时候连接一定会断开。后端像阿里云这样的云厂商进行运维性工作的时候往往可能会导致数据库出现闪断,这个闪断的时间不可能是随时的,因为这样对于应用的影响会比较大,所以就需要设置一个可维护时间,当客户设置好可维护时间之后,阿里云就能够保证所有的运维出现对用户造成影响的阶段都发生在可维护时间内,这样就可以尽量降低维护对于应用的影响。
这里介绍一下哪些任务可能会受到可维护时间的影响,比如:
1)内核小版本升级
2)机器损坏迁移
3)主库不可用主备切换
4)网络切割,变更
其实这里面最主要影响到了VIP,也就是LVS到后端的RS也就是物理机的IP之间的对应关系,而且更换VIP时也需要在可维护时间内执行。
慢SQL监控以及优化
对于慢SQL而言,应该如何进行分析和优化呢?其实可以从这样的几个角度进行考虑。
目前使用量最大的是MySQL数据库,MySQL的引擎有Innodb和Myisam,建议使用Innodb引擎,一方面,这是因为Myisam殷勤在进行主备复制时无法保证事务,这样就有可能导致中断;除此之外,Myisam在主库进行备份的时候会进行锁表,这样就会影响用户应用的访问。另一方面,阿里云对于Innodb的内核也进行了升级,并且增加了自增主键ID,也就是将一个隐式列当做主键,当开发的同学不去设置这个主键时就会增加一个隐式的主键。建议大家对于每一张表都建立一个合理的索引和主键,这里面就会涉及到大家需要做执行计划,当拿到一条SQL语句后,大家可以解释一下看看其执行计划是什么。如上图所示的是一条PG的执行计划,在其中可以清楚地看到这条SQL中使用了哪些操作,从其中可以看到这条SQL到底坏在哪里。当然大家也可以购买云服务来实现这样的分析。
账户管理和链路安全
只要是涉及到链路的内容都是非常重要的,当用户购买完阿里云的数据库服务之后,所有的白名单都是禁止访问的,希望大家能够自定义地设置IP的白名单。只有在设置了白名单之后才能继续使用服务,不建议大家一律都设置成为可通过,因为这样是极其不安全的。
除此之外,当大家使用了ECS去连接数据库,这里面就会存在一个ECS安全组的概念,当将一些ECS划归到安全组里面之后,后面如果在数据库中设置了安全组就会把ECS的IP同步到数据库中来。目前ECS安全组同步到云数据库这样的功能也即将上线,这样就能够解决每次购买ECS之后加减IP达到麻烦。
其实最推荐大家使用VPC网络,因为使用了VPC网络就可以与其他的所有用户的服务从网络上隔离开来。第三点建议就是对于账户数量以及数据库的数量进行控制,很多云用户使用了很多的账户和数据库,而这样的做法不是一种很好的做法,因为当账户很多之后,一个数据的权限就会呈指数地向上增长,因为每个账户或者每个DB都能有权限,并且权限还可能各不相同。当执行刷权限操作时就会消耗很长的时间,这样对整个数据库的使用而言是非常不利的,这里推荐大家升级到MySQL 5.6版本,当然目前绝大多数用户也都是使用的MySQL 5.6了,如果还没有升级的话希望大家尽快完成数据库升级,这样就可以享受到超级权限账户的功能了,这样其余的子账户都可以由这个超级账户派生出来,而不需要走API的方式。另外还建议每个业务应用都拥有自己的连接数据库的账户,为什么要有这个限制呢,其实是希望通过这样做,让大家在分析数据库上的连接和SQL的时候能够知道这条SQL来自哪个账户和应用,而不是只能够知道这条SQL来自的IP地址。
数据备份,日志备份
数据和日志的备份都是非常重要的,因为给在线数据库提供服务就是上述提到的与链路相关的事情,而其实在一种比较极端的情况下,比如购买了两节点或者三节点的数据库后,如果真的发生了灾难性故障的时候还会有一份离线的数据,那么通过离线的数据就能够恢复到日志已经上传到OSS上的最近的时间点,所以需要及时检查云数据库上的数据备份和日志备份是否有效,还可以适时地执行一次数据恢复来试一下数据能否正常地恢复回来,这无论是对于一个应用还是对于一家企业而言,都是非常核心的任务。
除了定期查看备份是否正常,还需要关注备份文件的大小。当数据库存储的数据量非常大的时候,比如单机数据量达到几个T之后,进行一次数据备份的时间就会非常的漫长,很有可能出现备份超时或者出现了其他的问题,所以对于数据量特别大的应用一定要经常检查自己的数据备份是否是正常的,而当阿里云发现一些用户的数据备份不正常时也会及时提醒用户。这里的一个关键点就是防止binlog刷新过快,线上的一些binlog刷新是很快的,比如1分钟一个500M的binlog,对于这样的应用就应该反思使用的数据库是否合适了。因为对于OLTP这样的应用而言,不应该存在大量的插入操作,如果存在大量的插入操作而查询和更新操作很少,这样的应用应该使用像HBASE这样的数据库,而不应该使用事务型的数据库。如果存在大量的数据更新就应该考虑是不是应该使用缓存、缓冲或者异步系统等,在应用级别想办法而不是把所有的数据更新都塞到数据库里让数据库承担。因为每个更新都会产生binlog,如果在短时间内产生大量的binlog就会造成应用的不稳定,一旦主库宕掉,就可能有大量的binlog积攒在本地没有得到及时上传,这样在灾难恢复或者主备复制时都会造成障碍,比如主库产生了大量的binlog,备库不能及时消费就会造成延迟,这样当主库故障切换到备库上时等待恢复的时间就会非常长。这一系列都是相关联的,所以大家应该及时检查binlog的运行状况。
参数设置及复制方式设置
对于数据库的参数而言,比如像典型的MySQL、SQL Server往往都有几十个参数,而常用的参数并不多,所以建议开发同学能够检查自己的数据库配置是否正确。
通常情况下,大家购买阿里云的数据库服务的时候都会设置了推荐的参数,这些参数都是经过阿里云的精挑细选推荐给大家使用的比较合理的值。但是实际上对于云数据库而言,阿里云并不知道大家的应用对数据库有什么样的特殊要求,所以不同的应用对于数据库的参数可能有不同的影响,比如表的大小写、某些cache的大小等都有可能影响到数据库的性能以及使用。还有就是复制方式的选择,现在默认都是开启了半同步的,但是对于有些云数据库大家往往又会降回异步。其实对于半同步而言,其只是将日志传到备库来然后给客户端进行返回,这样就能够帮助客户端将数据的可靠性做到最好。如果使用异步,当备库有一定延迟的时候,日志无法及时地传到备库中去,这样就会少一部分的binlog。希望大家平时多注意这一点,如果一直使用异步这样高性能的方式,在主库挂掉之后,数据的一致性是可能会丢失的,所以尽管绝大多数情况下都是使用的半同步,如果大家将其改成异步那么对于这一点就一定要注意。除非对于日志类型的应用需要尽可能保证其可用性,并且要求数据能够尽快地插入下去,而且对于数据的一致性要求不高的情况下是可以采用异步的方式的。还有一点就是对于多可用区和单可用区的选择,通常建议大家使用多可用区,多可用区实际上为大家做了机房级别的容灾,当使用像A + B这样的多可用区时,如果A可用区的机房挂掉了,B可用区还可以单独提供服务,这样就不仅仅是主机级别的故障容灾了,也做到了可用区或者机房级别的故障容灾,这一点使用自建数据库的方式是很难做到的。
四、云数据库的未来
未来,阿里云等各大云厂商一定会开发出更多的产品供大家进行选择,所能够提供的数据库不仅仅是以前的事务型或者非事务型数据库,未来的数据库产品可能是五花八门的,越来越多样化的。而云数据库也会变得更加易用、安全、稳定,云数据库的性能也会越来越高,并且将进一步提升产品的成熟度,进而为各行各业乃至全社会提供更好的数据服务。