问题起因
近期一个客户上云,系统用的是Oracle数据库,正确的姿势当然是去O,改用MySQL再上云,但因采用的软件系统来自外购,短时间内无法做去O改造,就采用了购买ECS并在上面安装Oracle的做法,使用SharePlex for Oracle做主备同步,具体架构如下:
这个架构看起来有应用的负载均衡,有数据库的主备做高可用,有SSD云盘保证IO,有快照做容灾,还是挺完美嘛~但实际使用中,就发现问题多多。
问题一:ECS实例选型
该用户选择的ecs.hfg5型实例,属于“高主频型”,让我们看看这个类型实例的适用场景https://help.aliyun.com/document_detail/25378.html#localssd:“可以满足高性能前端集群、Web 服务器、批量处理、分布式分析、高性能科学和工程应用、广告服务、MMO 游戏、视频编码等场景”,有没有做数据库服务的场景?可能用户觉着选择“高主频型”后,计算能力是足够了,再配合上“SSD云盘”,那存储上的IO也不是瓶颈,岂不是Perfect?
然而在上线后,系统访问压力增大才发现,实际的数据库性能总是上不去,最后发现问题还是在于磁盘IO上:
数据盘队列长度一直在5左右,随便搜搜关于磁盘队列长度的讨论,比如:
http://www.ithacks.com/2008/09/12/high-avg-disk-queue-length-and-finding-the-cause/,“As a general rule for hard disks, an Avg Disk Queue Length greater than 2 (per hard disk) for extended periods of time is considered undesirable.”,还有“Disk Queue Length is over 2 and % Disk Time is hovering at 60% or above, you may want to look into a possible I/O bottleneck.”,嗯,似乎确实有点问题哈。
既然都用了SSD云盘了,为什么还有磁盘IO瓶颈呢?经过找块存储的同学沟通后,确认IO带宽并不会是瓶颈,瓶颈是出在延迟上,既然是云盘,是会增加那么一丁点延迟的,经过测试,SSD云盘的写延迟在1ms左右,读延迟在1~2ms,这个结果其实并不差(比行业水平,比如其他云供应商还是强滴),但用在对读写延迟高度敏感的数据库服务器上,就稍显不够了。
那么既然SSD云盘都不够,是不是我们就该放弃云上自建数据库,下云得了?答案是No!其实从一开始我们就有更好的选择,那就是选择“本地SSD”型的ECS,我们来看看这个类型的ECS用在什么场景:“对应本地盘存储类型为NVMe SSD资源,高随机 IOPS 和高顺序读写吞吐、低时延。适用于 OLTP 联机事务处理、NoSQL 数据库、Hadoop 等应用场景”,看到没,这才是真正该选择用于自建数据库的ECS实例类型,前面那是方向错了(但努努力还是有救的,后面再说)。
话说阿里云还是提供过非实例型本地SSD盘(https://promotion.aliyun.com/act/aliyun/localssd.html),只不过现在下架了,这个选项就不再在考虑范围内了。
问题二:磁盘的配置
看系统性能图可以发现,用户的数据库服务器其实只有两块盘,一个是系统盘(高效云盘),另一个是数据盘(SSD云盘),数据、日志等都写在数据盘上,在高访问压力的时候,除了大量的数据写入外,也产生巨量的redo log。那么数据、日志分别写不同的磁盘,是否可以提高并行程度,从而改进写入效率呢?
说做就做,请用户新购买个SSD云盘,把当前9组redo log全部从当前数据库盘挪到新盘,并新加9组redo log,这样18个日志组都存在新盘中:
现在系统架构变这样了:
再看看系统性能情况:
数据盘的队列长度1,已经到了合理范围内,现在压力到了日志盘(F盘),似乎有点儿矫枉过正了,两个盘又有点写入不均匀。但是anyway,数据库的IO性能大有改善,在业务顶峰的时候也妥妥的扛得住。
虽然用户系统扛得住,但咱们还是要总结经验教训的,得找正式说法不是~其实Oracle官方文档已经早早的给咱们指明这个道路啦https://docs.oracle.com/cd/B28359_01/server.111/b28310/onlineredo002.htm#ADMIN11312,“Datafiles should also be placed on different disks from redo log files to reduce contention in writing data blocks and redo records.”。当然系统还可以进一步优化,比如数据文件也分布在不同的盘上,比如数据文件和日志文件怎么分布才能取得最佳平衡点,这就是下一步目标了。
问题三:快照容灾
OK,现在性能的问题解决了,是不是就一切OK了呢?别急,还早着了,下一个问题就是用快照做数据容灾不靠谱。如果用“oracle datafile corrupted”搜一下,会发现那结果是相当的多,估计背后都是满满的眼泪~在ECS上对云盘做快照,因为是不停机状态,数据文件更容易处于一个不完全的状态,换句话说,在真正需要基于快照恢复的时候,你会发现有很大的几率告诉你因为数据文件损坏,数据库无法启动。
在云下的时候,数据文件被损坏了还是能恢复的,条件是:“A datafile can still be recovered if no backup exists for it, provided: a、all redolog files since the creation of the datafile are available;b、the control file contains the name of the damaged file (that is, the control file is current, or is a backup taken after the damaged datafile was added to the database)”,可以发现这个在云上是很难满足的,也就代表你从快照恢复数据库也是很难满足的。
那正确的容灾姿势是什么呢?见下图:
其中备份到OSS这个其实可选,毕竟云盘提供9个9的可靠性(见https://help.aliyun.com/document_detail/25382.html),OSS也不过10个9,主备实例的云盘加上备份用的云盘全挂的概率实在不高。如果希望能够进一步提高数据的可靠性(及时备份),可以在主实例上做rman数据备份,这会损失一点主实例的性能。
问题四:快照时机
上个问题提到快照容灾不靠谱,容易导致数据文件损坏,无法做灾难恢复。其实用户使用快照还有另一个有问题的地方,就是为了容灾中尽量少损失数据,设置了每3个小时做一次快照,而其中有几次会发生在业务高峰期!这就导致了在快照的时间点(因为数据量巨大,快制作快照需要的时间比较久)会因为备份争抢磁盘的IO,这会导致数据库性能的进一步恶化,这也是在实际使用中发生性能不够的一个重要的因素。正常的快照操作应该在业务低谷时候做。
问题五:数据库HA方案
现在我们回过头来看看该用户的Oracle HA方案,架构里面看起来似乎做到了HA,但实际还离得远,很简单,如果主实例出故障,那么会怎么切换?首先这没有自动切换的机制,如果半夜三更没人值班,发生故障了只能等业务出问题了,再去找运维人员,然后做手动切换。
那找到运维人员是不是就能快速恢复?No!既然是应用服务器上直连数据库服务器,那么不管使用IP还是实例名,切到备服务器都需要修改应用服务器的配置,然后重新应用,这个时间可就长了,别说做不到业务无感的自动切换,连快速恢复都算不上。
数据库HA最常见的实践是用VIP,但在阿里云里面现在是不支持VIP的使用,如果对数据库的请求走“SLB+多ECS(ECS内再自建load balancer)”来实现failover似乎性能的损失会比较大,目前看来还没能找到比较靠谱的云上自建数据库HA方案,如果哪位知道还请指点一下:)
当然如果哪天咱们阿里云提供类似AWS Route53中的Private DNS服务,也许这个问题就好解了,毕竟“You can now use Route 53 to manage the internal DNS names for your application resources (web servers, application servers, databases, and so forth) without exposing this information to the public Internet. This adds an additional layer of security, and also allows you to fail over from a primary resource to a secondary one (often called a “flip”) by simply mapping the DNS name to a different IP address.”