问题起因
近期一个客户上云, 系统用的是 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), 只不过现在下架了, 这个选项就不再在考虑范围内了
问题二: 磁盘的配置
接问题一, 客户都已经买好了实例了, 还一口气买了很久, 相关的系统也部署好了, 业务也在运行了, 还沉淀了不少的业务数据, 在系统正繁忙阶段, 也没时间做各种折腾, 需要尽快的优化性能, 这还有救吗? 答案是 Yes!
看系统性能图可以发现, 用户的数据库服务器其实只有两块盘, 一个是系统盘(高效云盘), 另一个是数据盘(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: aall redolog files since the creation of the datafile are available;bthe 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 方案, 如果哪位知道还请指点一下:)
后记: ESSD 云盘
2018 年 1 月 9 日阿里云推出了 ESSD 云盘, 单盘 IOPS 高达 100 万, 单路随机写时延低至 100 微秒, 这个应该是自建数据库中更好的存储解决方案, 有兴趣的同学可以试试这个
来源: http://click.aliyun.com/m/42856/