达梦DSC共享存储集群:从架构原理到运维实战
1. 为什么选择DSC共享存储集群的定位与适用场景做数据库运维这些年我接触过的集群方案不少从最早的主备切换、读写分离到后来的分布式中间件各有各的适用场景。DSC集群在达梦的体系里对应的是Shared Disk架构也就是大家常说的共享存储集群。它的核心逻辑是多台数据库实例节点共享同一份物理存储上的数据文件通过集群管理软件实现节点间的缓存一致性、事务协调和故障转移。我在第一次接触DSC时第一个感受是这玩意儿和Oracle RAC的思路确实很像。它针对的核心场景是对可用性要求极高同时又必须保证数据强一致的业务系统。比如金融交易、电子政务、企业ERP这类核心业务宕机几分钟都可能造成严重后果这时候主备切换的秒级甚至分钟级中断仍然让人提心吊胆而DSC能做到让集群内任何一个节点宕机后业务自动往其他节点漂移应用层几乎无感知。不过要说清楚的是DSC并不是万金油。它对部署环境的要求挺苛刻必须要有共享存储SAN、ASM这类网络要求低延迟、高带宽的私有互联网络。在很多预算有限的团队里一看到“必须上共享存储”这个前提就已经劝退了。所以选型的时候我个人的判断标准是这样的场景推荐方案原因核心交易系统可用性要求99.99%以上DSC数据库层高可用故障自动切换无数据丢失预算有限独立部署多套小业务主备模式成本低部署快手动/半自动切换基本够用海量并发读写压力分散读写分离扩展读能力但维护逻辑在应用层需要跨地域容灾DSC备库同城共享存储集群内做高可用异地再挂备库容灾说实话我碰到过不少团队业务还没到那个量级就急着上集群结果发现运维复杂度远超预期一个节点都还没挂先因为心跳网络抖动把集群给折腾崩溃了。所以选DSC之前先问自己一句业务真的需要这么高的可用性吗如果答案是肯定的那再往下走。2. DSC集群的核心组件与架构拆解DSC从架构层面看其实并不神秘。它由两个核心部分组成集群控制软件DSC和多个数据库实例。这里有一个常见误区很多人以为DSC是一个独立的、像中间件一样跑在数据库之上的服务进程其实不是。DSC是在数据库实例内部集成的集群组件它利用共享存储上的控制文件、数据文件以及实例间的高速私有网络共同完成集群的协调。拿一次数据库启动的过程来说。每个节点我们习惯叫实例启动时会通过集群控制信息去“抢占”或“协商”自己需要管理的资源。共享存储上会有一部分区域专门保存集群的全局状态比如节点列表、数据文件在集群中的lock信息、事务提交的全局排队信息等。这些信息用达梦的术语讲分布在几个关键的内部对象里比如控制文件、数据字典、undofile等它们都在共享盘上每个实例都能访问。多实例访问同一份数据最棘手的问题是缓存一致性。举个例子节点1读了一个数据页放到内存里然后改了它节点2同时也要读这个页它不能直接读共享盘上的旧版本必须拿到节点1最新修改的版本。这个“相互通知”的动作就是通过DSC的高速互联网络来完成的。达梦在这里用的是经典的Cache Fusion思想把单机内存里锁和缓冲区管理的机制扩展到了多个节点之间。另外谈到DSC的部署形态有两节点和多节点的区别。生产环境中最常见的还是两节点DSC因为多数场景下满足高可用就够了多节点能带来更好的扩展性但协调开销也随之增长。这里再引出另一个重要的概念DSC的故障切换模式。它支持自动切换当集群里一个节点因为掉电、网络隔离、操作系统崩溃等原因“失联”后其他健康节点会在内部机制的控制下重新接管它负责的资源整个数据库对外始终是“活着”的状态。说句掏心窝的话DSC架构理解起来不难难的是底层细节——这些细节在官方文档里往往不会写得太细但线上出问题时恰恰是这些细节在起作用。后面我会结合踩坑经历把那些文档上找不到的东西拿出来聊。3. 部署DSC集群前必须盘清楚的硬性条件DSC部署包含一系列前置条件。这里我把自己在项目里总结的“六项必查”列出来任何一项不满足都不建议贸然开工。3.1 共享存储这是DSC的生命线DSC要求数据文件必须存放在所有节点都能直接访问的裸设备或共享文件系统上。注意关键词“直接访问”。网络文件系统NFS不是不能用但踩过的坑告诉我一旦网络延迟波动NFS作为共享存储跑DSC会引发各种诡异的性能问题甚至节点驱逐。生产环境老老实实用SAN存储划分裸设备LUN每个实例挂载相同的LUN路径。磁盘划分方面我一般这样规划数据库相关的数据文件、控制文件、日志文件全部放在共享盘上本地盘系统盘上只放达梦软件安装目录、归档日志可选和本地配置共享盘建议划分为多个LUN物理上分离数据、日志、控制文件避免一个LUN的IO抖动拖垮所有组件。3.2 网络搞定心跳集群就稳了一半DSC的节点之间需要Pass数据页、传递锁信息这套通信对网络质量极其敏感。我看过不少客户环境生产业务网络和DSC内部网络混在一起结果大流量业务一跑集群内部通信延迟飙升节点之间互相怀疑对方“宕机”触发驱逐最后业务反而中断了。正确的做法是独立规划一套私网专门跑节点间通信。我习惯的方案是双网卡绑定使用万兆交换机网段和业务网严格隔离。有条件的话两台交换机做端口聚合和冗余避免单交换机故障导致集群割裂。这里的配置细节包括网卡绑定模式、MTU值等后面实际操作部分会展开。3.3 操作系统与版本校验达梦对操作系统的支持面比较广常见的Linux发行版如麒麟、统信、CentOS等都可以但不同小版本的内核参数补丁情况差异很大。部署前跑一遍官方环境检查脚本确认内核参数、共享内存、信号量等符合要求。具体来说我通常会检查这几个方面是否开启IP转发、是否关闭防火墙或对DSC内部端口放行系统共享内存参数kernel.shmmax、kernel.shmall进程数限制、文件句柄数限制时钟同步服务是否配置多节点之间时间差要控制在很小范围否则事务时间戳会乱套。3.4 集群节点数规划两节点还是三节点看起来只是数量差异实际上故障处理逻辑有本质区别。两节点DSC需要特别考虑“脑裂”防护——当两个节点都认为对方挂了、都试图接管全部资源时如何避免数据损坏。通常引入了表决机制谁能在共享存储上更新某个“心跳”标记谁就有资格继续服务。这个机制依赖共享盘的可用性一旦共享盘整体故障两个节点都会主动退出数据库服务保数据安全。多节点的好处是可用性和扩展性更好但管理和协调复杂度跟着上来了。我的建议是如果需求仅仅是高可用优先两节点如果有明确的扩展性诉求再考虑三节点及以上。3.5 归档模式与备份策略DSC虽然高可用但不代表不需要备份。恰恰相反DSC架构下备份恢复的操作更难因为数据文件在共享盘上逻辑上是一个数据库但实例有多个。我在上线前一定会确认开启归档模式归档日志位置放在可靠存储上最好单独一个LUN定期做全量备份并验证备份集的可恢复性明确备份工具对DSC集群的支持方式不能简单沿用单机备份的思路。3.6 运维团队的技能储备这条经常被忽略但它往往是最致命的。DSC集群的管理和单机数据库管理完全不同出问题时需要判断是哪个节点的故障还是共享存储的故障需要懂集群日志的查看方式需要理解集群模式下DDL、DML的行为变异。如果团队里没人真正懂DSC我强烈建议提前安排一次系统性的培训或者由协助部署的工程师做完知识转移后再上线。不是泼冷水而是我见过太多“把集群搭起来就开始跑业务出了问题所有人干瞪眼”的案例。4. 从初始化到节点加入DSC部署实操理论说了那么多接下来落到实操上。我以两节点DSC为样例写一下从零到能跑通的完整过程。4.1 环境准备清单假设操作系统已经装好共享存储已经映射给两个节点并且fdisk -l都能看到相同大小的共享LUN比如/dev/sdb、/dev/sdc。每个节点需要添加普通用户比如dmdba用户uid/gid保持一致便于集群内权限统一。然后创建安装目录、实例目录、归档目录并授权给dmdba。还需要配置环境变量DM_HOME指向软件安装路径LD_LIBRARY_PATH指向动态库路径PATH里加上bin目录。4.2 初始化共享磁盘上的数据文件这一步和单机数据库初始化很不一样。在单机环境下我们直接执行初始化工具生成一套数据文件到本地磁盘。在DSC下必须用特定的方式在共享盘上初始化集群数据库。我实际采用的流程是在其中任意一个节点作为初始节点上编辑一个初始化参数文件。文件里不仅包含数据库名、页大小、字符集最关键的是包含DSC特有的DCR和ASM相关的配置路径、节点信息。DCRDisk Control Region是达梦管理共享存储磁盘配置的核心区域我通常单独划出一个几百MB的LUN专门放DCR它保存整个集群所有节点能访问到的存储拓扑信息。初始化命令会生成控制文件、数据文件、日志文件这些文件全部落在共享盘路径。执行完成后再用另一个工具将DCR信息分发到其他节点的本地磁盘方便它们启动时快速找到共享存储上的集群信息。注意初始化只有一次机会字符集、页大小、数据库名这些一旦定了后续再改会非常痛苦。所以初始化前务必和业务方确认清楚。4.3 配置集群服务并启动所有节点初始化完成之后每个节点上都会生成一套本地配置文件比如dmdcr.ini、dmsv.ini等这些文件告诉本机实例集群里有多少节点、谁是节点0、节点1它们的心跳IP和端口是什么共享盘的盘符路径是什么。这组文件一定不要搞混节点0和节点1的配置内容是不一样的。然后按照约定顺序依次启动集群服务。一般的启动步骤是先启动集群监控服务DMCSS它负责监控集群内各节点的状态并执行故障恢复决策再启动ASM服务如果采用ASM存储方案用来管理共享磁盘的挂载和文件区分配最后启动数据库实例服务让它正常注册到集群中。启动后用集群管理命令查看状态。正常情况应该能看到两个节点都是健康状态且没有报网络、存储、表决相关的警告。这里有一个非常容易踩的坑先启动节点0等它完全变成Open状态后再启动节点1。不要同时启动两个节点以免初始建立集群关系时出现竞争。DMCSS起来之后后续节点重启就从容得多。4.4 验证集群工作状态部署不只是“能起来”还要验证“真的好用”。我一般做下面几步检查查看节点视图确认两个实例都处于正常打开状态连接到集群数据库执行一些DDL和DML确认两个节点对同一份数据的读写一致性进行故障切换演练手动停掉其中一个节点比如强制kill掉实例进程观察另一个节点是否能在短时间内接管业务查询是否还能继续检查节点自动恢复把停掉的节点拉起来确认它能自动加入集群并在完成恢复后重新开始服务。我在做故障切换演练时习惯同时开一个监控脚本持续向数据库发送查询请求用来观察业务中断窗口。第一次做这种演练通常会发现比自己预期的中断时间长原因多半是死锁检测、未完成事务回滚等机制在生效这都是正常的关键是判断这个窗口是否能被业务接受。5. 运维日常DSC集群的参数调优与监控DSC集群搭好后运维工作才真正开始。如果说部署是“生孩子”那运维就是“养孩子”而且是那种天天得盯着吃喝拉撒的孩子。5.1 关于资源管理视图与性能分析DSC下因为是多实例单机的动态性能视图已经不够用了。达梦提供了一套集群视图用于查看整个集群的资源使用情况——包括每个节点的会话数、活动事务数、锁等待、缓存命中率、集群内部通信流量等。我最常用的几个查询基本覆盖了日常巡检的80%需求查集群节点状态确认没有节点Failed按节点分组查活动会话数判断是否存在负载严重倾斜查全局锁阻塞尤其是长时间未提交事务导致的阻塞DSC环境下锁的粒度比单机更敏感一个节点上的未提交事务可能阻塞另一个节点访问同一条数据。5.2 几个常用参数的调整心得DSC集群运行过程中有几个参数值得特别关注它们直接影响集群的稳定性DSR相关参数达梦内部叫动态服务器资源管理包括运行时资源限制和转发机制。如果业务本身并发不高但节点间通信频繁可以考虑调整相关的缓冲阈值减少不必要的跨节点交互BUFFER每个节点都有自己独立的数据缓冲区。理论上缓冲区越大本地命中率越高跨节点直径读取就越少集群整体性能就越好。但内存是稀缺资源我的经验是节点数量越多每个节点的缓冲区越不需要过于激进因为性能瓶颈更多出现在网络和锁协调上故障检测超时时间这个参数决定了一个节点失联后集群等待多少秒才判定它真宕机。设得太短网络瞬断就会被误判触发节点驱逐设得太长故障切换窗口就变大。这个值的把握需要结合自己的网络稳定性去调整我一般不会直接用默认值。5.3 日常巡检应该看哪些东西巡检和监控我习惯做成一张固定的清单每次照单执行所有节点的集群状态是否正常有没有节点处于挂起或退出状态共享存储的使用率数据文件所在文件系统是否快满DCR区域是否有报警集群内部通信网络是否有大量重传或者延迟异常检查网卡错误计数各节点之间的事务量是否均衡有没有热点节点最近一次备份是否成功归档日志是否可以正常清理系统日志和数据库日志里有没有非预期的错误信息。这套巡检动作我通常一天至少做一次核心业务系统甚至建议做到小时级。不要觉得烦DSC集群下面问题爆发常常是一连串的巡检早发现处理成本就小得多。6. 故障场景全解析节点驱逐、存储故障与恢复流程这里聊的是运维DSC最硬核的部分故障处理。我会按几个典型案例展开每个案例都标明了“我是怎么判断的”和“我做了什么”。6.1 案例一节点被集群驱逐有一次线上两节点DSC晚上业务高峰期节点A因为网络瞬间抖动没有在超时时间内和节点B“握手”节点B通过DMCSS判定节点A失联触发了驱逐流程把节点A从集群里踢了出去。A上面的活动会话全部发生中断应用层报了大量连接错误。我的排查过程先看集群视图确认节点A已经从集群中摘除状态显示为失效看节点A的本地日志发现一段时间内网络接收超时但没有硬件报错检查交换机端口统计确认是否有丢包或流控触发。处理方式把节点A上的实例进程清理干净排查网络交换机上是否有广播风暴或带宽瓶颈调整交换机端口配置后重新拉起节点A的实例让它通过DMCSS自动重新加入集群。体会如果只是单纯的网络瞬断DSC的处理机制是可靠的不会损坏数据。但如果网络频繁抖动那就要认真排查网卡、交换机、绑定模式了根因不除被驱逐会反复发生对业务的影响一次比一次大。6.2 案例二共享存储链路故障这个案例比节点驱逐要棘手得多。某次存储交换机故障导致两个节点同时失去了对共享LUN的访问。DSC的设计原则在这种情况下是宁可终止服务也不允许数据损坏。所以当时DMCSS迅速做好了决策两个节点都进入了故障保护状态数据库服务对外不可用。处理步骤确认存储交换机故障范围将存储链路修复节点本地重新挂载共享LUN执行多路径命令确认路径已恢复检查磁盘状态确认数据文件、控制文件都完好按规范启动集群数据库恢复正常。这个案例说明了一个关键点DSC的高可用前提是共享存储本身的高可用。如果共享存储是单点那DSC再厉害也白搭。生产环境存储层面必须做冗余双控制器、双链路否则DSC的高可用意义会大打折扣。6.3 案例三意外宕机后的恢复顺序还有一次是机房掉电两个节点全部宕机共享存储由UPS供电没有损坏。恢复时我特意等两个节点硬件都起来、系统都恢复之后再依次启动本地服务。为什么这样做因为如果只启动了一个节点它可能会单节点先Open数据库此时另一个节点再启动加入时需要经历一个恢复数据的过程。处理得当没问题但如果在节点B还处于“失联”状态时节点A就做了大量写入那么节点B重新恢复时它的恢复过程会更耗时甚至需要从归档日志补数据。我个人的习惯是遇到整集群宕机不要急着拉起节点先确认所有节点都处于可启动状态再按统一策略启动。有时候抢时间反而会让事情变复杂。6.4 故障处理的基本原则经历多了之后我给自己定了几个故障处理铁律先确认共享存储的状态再看数据库的状态存储出问题数据库必然出问题不要同时对多个节点做“诊断性”重启先稳住一个节点让它接管服务再说任何故障处理操作前先拍下当时的视图和日志方便事后复盘如果一时判断不了根因优先恢复业务把故障影响降到最低再来慢慢查日志。7. 备份恢复与容灾延伸DSC之上再考虑一层DSC解决了实例故障的HA但解决不了数据中心级灾难。比如整个机房断电、存储阵列双控制器同时坏死这种情况就需要考虑延伸到容灾。我们的做法是在DSC集群基础上再挂一套独立的备库采用异步或实时归档方式同步数据到异地机房。一套典型的容灾方案是生产机房两节点DSC业务连续性由集群保证灾备机房单实例备库实时接收生产库的归档日志并恢复平时灾备库可以承担查询、报表等非核心负载发生生产机房整体故障时手动或半自动将业务切换到灾备库。备份策略上DSC环境因为数据文件都在共享盘备份可以在任意一个节点上执行。我的建议是轮换节点避免某个节点长期承担备份任务造成负载不均衡。还要特别提醒DSC环境下的备份最好在集群状态健康时执行备份过程中如果发生节点故障备份集本身不一定失效但恢复时可能遇到很多小程序上的麻烦。我在实际项目里遇到过一次“备份成功但恢复失败”的坑。起因是备份期间一个节点的redo日志归档出现了延迟备份集记录的时间点和归档日志之间存在空隙恢复时才暴露出问题。所以从那以后我对备份的验证动作变成了铁律每次备份完之后不能只看备份结果一定要试恢复。至少在测试环境验证一次备份集能被正常恢复才真正算数。8. DSC日常维护操作速查常用管理命令小结最后给一份我常用的DSC管理命令速查表。这些不是官方手册的全量罗列而是日常用得最多的部分整理出来方便查阅。操作命令方向说明查看集群视图DMCSS工具检查节点状态、在线离线情况启停数据库实例实例管理工具单节点启停最好从DMCSS统一管理查看集群日志日志目录定位节点驱逐、恢复等事件执行备份备份工具任选健康节点执行节点加入/退出集群DMCSS命令在线将节点纳入或隔离出集群查看锁等待动态视图定位跨节点阻塞查看重做日志归档归档视图检查归档连续性再强调一点管理命令在没有把握的情况下先查帮助别硬记。达梦的每条管理命令都有对应的帮助说明虽然命令行风格没那么时尚但条理很清楚。尤其是那些需要节点间协同的动作命令执行失败时大概率不是语法错了而是集群状态不允许这时候要看返回信息的最后一行它往往给出了最直接的原因。我现在的习惯是把常用的命令和应急处理步骤写进运维手册故障时照着手册来而不是靠临场记忆。DSC集群本身是个严肃的架构运维方式也必须是严肃的。这份手册我会根据每次故障处理后的复盘不断补充修改半年下来就是一份真正属于自己的运维资产。