数据库选型这件事我这些年被问得最多的一个问题不是该不该用分布式数据库而是用了之后半夜三点出问题我能不能自己救回来。OceanBase 2.2 这个版本恰好就是回答这个问题的分水岭——它把高压缩比、Paxos 三副本强一致、在线扩缩容这几件原本互相打架的事情做到了同一套可以自己动手部署、自己动手运维的形态里。这篇内容我按特性为什么这么设计 参数为什么这么定 命令怎么敲的顺序拆开讲把你真正会踩到的坑写清楚目标是让你照着能在一个下午把一套三副本集群跑起来而不是看完只知道有几个功能点。适合谁看手上有 MySQL 迁移需求的后端开发、要评估或落地分布式数据库的 DBA、需要做技术选型判断的架构同学。零基础也能看懂前置概念有经验的可以直接跳到第四章的配置文件部分。1. 先搞清楚 2.2 在整个产品线上的坐标1.1 分布式数据库真正的门槛不在能分片很多人对分布式数据库的第一印象是数据能拆到多台机器上这个理解太浅了。真正的门槛是三件事同时成立数据拆开之后事务还得是强一致的某台机器挂了业务不能停加机器的时候不用停机重分布。三条里做到两条的产品不少三条同时做到的在 2.2 那个时间点上是硬门槛。OceanBase 2.2 的价值就在于它把这三条收敛成了一组可以运维的实体分区表负责拆Paxos 多副本负责不丢不停Unit 和资源池负责加和减。理解了这个骨架后面所有的参数和命令你都能找到它挂在哪根骨头上。我见过不少团队上来就问你们支持多少并发、能存多少数据其实这类问题没有意义。真正该问的是我的业务写入是不是有热点、我的主键是不是单调递增、我的查询是不是大部分能命中分区键。这三个问题的答案直接决定了你在 2.2 上会过得舒服还是难受。1.2 2.2 这个版本解决了哪些必须解决的问题把功能清单摊开看容易眼花。我按解决什么现实问题重新归一下类这张表是我自己做选型评估时用的比官网功能列表好用。现实问题2.2 的对应能力关键约束单表几亿行删除历史数据要跑一整夜分区表 分区裁剪 分区级 DDL分区键必须出现在高频查询条件里主库挂了要人工切换业务有损Paxos 三副本多数派提交自动选主至少三副本副本分布要跨物理机存储成本高压缩后还占地方LSM-Tree 存储 行列混合压缩压缩在合并时生效写入侧有放大多业务共用一个集群互相影响多租户 Unit 资源隔离CPU 是软隔离内存是硬隔离业务代码里有大量 MySQL 语法MySQL 模式兼容协议层兼容少数函数、隐式类型转换行为有差异扩容要停机导数据分区副本在线迁移、Unit 迁移迁移期有网络和 IO 开销要控速需要说明的是这张表里的关键约束一列是我在实际项目中总结的不是文档原文。文档告诉你有什么约束告诉你能不能用得顺手后者往往更值钱。1.3 什么样的业务适合上什么样的趁早别碰这一段我想说得直白一点因为选型失误的代价远大于技术细节踩坑。适合的场景单表数据量过亿且增长看不到头、有明显的时间或业务维度可以做分区键、读写比例偏高且能接受最终读一致性在秒级内收敛、对存储成本敏感压缩比这块确实是它的强项、有多业务共用集群的诉求。这类业务上来之后普遍能在两到三周内跑稳。要谨慎的场景全表随便查、没有明显分区键、大量跨分区 JOIN 和聚合、单条 SQL 要扫几千万行、强依赖 MySQL 特有语法和存储过程。这些不是不能跑而是你会发现自己花在改写 SQL 和调优上的时间远超省下来的运维成本。还有一种情况要提前说清楚如果你的数据量其实只有几百万行、单机 MySQL 完全扛得住那真的没必要上分布式。分布式带来的复杂度是实打实的——多一层路由、多一套元数据、多一组需要监控的进程。技术在合适的规模上才叫优势用错地方就是负债。2. 核心特性逐条拆别只背功能名2.1 分区表分区键选错后面全是补救分区表是整个体系的入口。2.2 支持 Range、List、Hash 以及它们的两级组合分区语法上贴着 MySQL 的分区语法走迁移时改造成本不高。但语法像不等于行为像这一点必须说透。在单机 MySQL 上分区更多是个物理组织方式查询规划器对分区的依赖没那么强。在 OceanBase 上分区是数据分布和副本调度的基本单位——一个分区就是一个 Paxos 副本组它的 Leader 落在哪个 Zone 是独立选举的。也就是说分区键的选择直接决定了你的写入会不会全压在一个 Zone 上。举个具体的例子。假设一张订单表按create_time做 Range 分区按月切。这个设计看起来很合理因为业务查询基本都是查最近一个月。但写入侧就有问题了所有新订单都写进当月那一个分区等价于所有写入压在这一个分区的 Leader 上集群其他节点的写入能力完全闲置。正确的做法通常是两级分区一级按时间 Range二级按user_id或order_idHash 打散把写入摊到几十个分区上去。分区裁剪这块也要有预期。只有当查询条件里出现分区键、并且是编译期能确定的常量或简单表达式时裁剪才会生效。where create_time now() - interval 30 day这种写法通常是能裁的但如果你在分区键上套了函数比如where date_format(create_time,%Y%m) 202401裁剪大概率失效变成全分区扫描。这一点跟 MySQL 的行为逻辑一致但代价被放大了因为扫描会打到多个节点上。分区键的取舍原则优先选查询必带、写入能打散的列。如果这两个条件冲突写入打散优先因为查询侧还能靠索引和分区裁剪兜底写入热点几乎无解。2.2 Paxos 多副本三副本到底保证了什么三副本这件事很多人理解成数据存了三份坏了还有。这个理解漏掉了最关键的一半多数派提交。写入必须落到多数派三副本中的两个的日志里才算成功这样一来任何一个副本挂了剩余两个仍然构成多数派集群可以继续写。如果只剩一个副本多数派不成立集群会停止写入而不是降级写入——这个设计选择很重要它把数据可能不一致的选项直接划掉了。副本落位是另一件容易忽视的事。三个副本必须分布在不同的故障域上通常是三台物理机、三个机架或者三个可用区。如果你图省事把两个副本放在同一台机器上那这台机器一挂你就只剩一个副本集群直接停写。我见过有团队在测试环境这么干压测一切正常上了生产才发现容灾等级是零。日志这块2.2 的 redo 日志clog是独立目录存放的默认写入非常频繁。clog 目录的容量规划经常被低估实际经验是按memory_limit的 3 到 4 倍来预留如果业务写入峰值很高这个倍数还要往上走。clog 目录写满的后果很严重集群会直接 hang 住这时候除了扩容和清理没有别的办法。关于选主和切主需要建立一个预期切主不是瞬时的。Leader 失效到新 Leader 选出中间的时长取决于心跳超时配置和网络状况通常是秒级到十几秒。这个窗口内相关分区的读写会阻塞。如果你的业务对这段窗口完全不能接受那就需要在应用层做重试和超时控制而不是指望数据库做到零感知。2.3 LSM-Tree 与合并写放大从哪来磁盘什么时候会满存储引擎用的是 LSM-Tree 变体数据分两层内存里的 MemTable增量数据和磁盘上的 SSTable基线数据。写入先进内存内存到水位后冻结转储成 SSTable再由每日合并major freeze把多个 SSTable 和基线数据归并成新的基线。这个机制带来的第一个好处是写入快——顺序写不随机更新。第二个好处是压缩比高因为合并时数据是排好序、按块组织的压缩算法能发挥得很好。实测下来普通业务表的压缩比做到 3 到 5 倍很正常日志类表甚至更高。代价是写放大和合并压力。一条记录从写入到最终落到基线至少要经历内存 → 转储 SSTable → 合并写入新基线这两次落盘。合并期间磁盘 IO 会明显上升如果数据量大而合并窗口又短就会和业务写入抢 IO。几个关键参数得心里有数。memstore_limit_percentage控制租户内存中可用于 MemTable 的比例默认 50freeze_trigger_percentage是触发冻结的水位默认 20占 memstore 的比例。这两个值调大能让写入更顺但会挤占缓存读性能下降。我的经验是写入密集型的租户可以把 freeze 触发水位适当调高读写混合的保持默认更稳。磁盘水位是最需要盯的。合并过程中需要额外的临时空间如果磁盘已经用到 85% 以上再触发合并很容易因为空间不足失败。建议把告警线设在 75%处置线设在 80%。这一点在第六章会展开说。2.4 多租户与资源隔离CPU 是软的内存是硬的多租户的模型是三层Unit Config 定义规格CPU、内存、IOPS、连接数、磁盘Resource Pool 是 Unit 的集合Tenant 绑定 Resource Pool。这个抽象初看绕其实很清晰——规格是模板池子是配额租户是使用者。这里必须讲清楚隔离强度。内存是硬隔离租户的max_memory是多少就最多用多少超了会报内存不足不会去抢别人的。CPU 是软隔离max_cpu是上限、min_cpu是保底中间部分靠调度器按负载分配也就是说空闲时可以互相借繁忙时会互相挤。IOPS 类似是配额性质而非物理隔离。理解了这个差异你的容量规划思路就清楚了内存要按峰值算足CPU 可以按均值规划再加一定冗余。我见过把内存算成均值的结果一到业务高峰就疯狂报错。租户的副本数也需要显式指定。生产环境至少三副本测试环境可以单副本省资源但这个差异要在环境文档里写死避免有人拿测试配置上生产。2.5 OBProxy 与 MySQL 兼容连接串里那个 和 # 是什么意思OBProxy 是反向代理层负责把 SQL 路由到正确的 OBServer。客户端连的是 OBProxy 的 2883 端口而不是 OBServer 的 2881。代理层负责解析 SQL、识别分区键、定位 Leader 所在节点然后转发。它还承担连接管理、失败节点摘除、限流这些职责。连接串的格式是很多人第一次上手会卡住的地方。系统租户是rootsys业务租户是root租户名#集群名。那个#后面的集群名是 OBProxy 用来区分后端集群的如果你只部署了一套集群也要写全否则连不上。MySQL 兼容这块协议层、驱动层基本都是兼容的用 MySQL 的客户端和 ORM 框架大多能直接连。但有两个差异要提前知道一是默认事务隔离级别是读已提交Read Committed而原生 MySQL 默认是可重复读如果你的业务依赖可重复读的间隙锁行为迁移后语义会变。二是部分函数、隐式类型转换、ON DUPLICATE KEY UPDATE的边界行为有细微差异。上线前一定要跑一遍完整的 SQL 回归别指望兼容两个字能覆盖所有情况。3. 部署前的硬性准备这几步省了后面一定返工3.1 硬件与内核参数先把地基砸实起步配置我给一个我自己常用的基准三台机器每台 16 核 64G 内存SSD 盘万兆内网。这个规格足够支撑中等规模的业务验证和小流量生产。再往上加主要加内存和磁盘因为内存决定 MemTable 和缓存磁盘决定基线数据容量。内存怎么分这是个必算的账。假设单机 64Gmemory_limit不要设成 64G操作系统和其他进程要留余量设成 48G 到 52G 比较稳妥。memory_limit里面还要划出system_memory系统内部使用比如元数据、日志缓冲建议 5G 到 10G。剩下的才是租户可用内存。所以你能分给业务租户的总内存大概是memory_limit减去system_memory再留一点余量。磁盘怎么分至少要分两个目录数据目录和 clog 目录。数据目录的datafile_size建议设为磁盘可用空间的 80%留 20% 给合并临时空间和系统文件。clog 目录按memory_limit的 3 到 4 倍预留如果内存 48Gclog 就准备 150G 到 200G。三台机器同规格这是三副本的前提。内核参数这块一份可以直接抄的清单# /etc/sysctl.conf fs.aio-max-nr 1048576 net.core.somaxconn 2048 net.core.netdev_max_backlog 10000 net.ipv4.tcp_max_syn_backlog 16384 net.ipv4.tcp_tw_reuse 1 net.ipv4.tcp_slow_start_after_idle 0 vm.max_map_count 655360 vm.swappiness 0 vm.overcommit_memory 0 vm.min_free_kbytes 2097152vm.swappiness0和vm.min_free_kbytes这两条尤其重要。前者避免内存页被换出导致延迟抖动后者保证系统始终有足够的空闲页应对突发分配。vm.max_map_count调大是因为服务进程会映射大量内存区域默认值不够用会导致启动失败。用户限制也要改/etc/security/limits.conf里admin soft nofile 655350 admin hard nofile 655350 admin soft stack unlimited admin hard stack unlimited admin soft core unlimited admin hard core unlimited注意limits.conf改完之后必须重新登录才会生效。而且如果你是靠 systemd 启动服务systemd 有自己的限制配置limits.conf对它无效需要另外在 unit 文件里设LimitNOFILE。这个坑我踩过明明改了配置进程起来还是报 too many open files。3.2 时钟同步最容易忽视也最容易致命Paxos 的日志排序依赖时间戳如果三台机器之间时钟偏差过大选举会出问题严重的会导致集群起不来或者反复切主。一般要求偏差控制在 100ms 以内实际部署时最好做到 10ms 级别。配置好时间同步之后一定要在三台机器上分别执行date对比或者用chronyc sources看同步状态确认偏差在可接受范围内再往下走。我见过最典型的一次部署失败就是一台机器的时区设错了看起来时间差了几小时bootstrap 直接卡死日志里只有一堆看不懂的选举超时。3.3 容量估算用一张表算清楚要买多少盘估算这件事光拍脑袋不行我给一个可复现的算法。假设业务原始数据 2TB主要是一张日志表和几张业务表。第一步看压缩比日志类数据压缩比通常能到 5 倍以上业务表 3 倍左右混合按 3.5 倍算落盘后约 570GB。第二步算副本三副本意味着每个 Zone 都要存一份完整的 570GB所以每个 Zone 需要 570GB 的数据空间。第三步加余量考虑到合并临时空间、索引、系统表按 1.6 倍预留每个 Zone 需要约 900GB。第四步是 clog按内存的 3 倍算假设单机内存 128Gclog 需要约 380GB。加起来每台机器至少要 900GB 数据盘 380GB 日志盘。买盘的时候向上取整别按理论值买因为磁盘可用容量永远小于标称容量。计算项数值说明原始数据量2TB业务侧统计混合压缩比3.5日志 5 倍、业务表 3 倍加权单副本落盘约 570GB原始量除以压缩比数据盘需求约 900GB570GB 乘 1.6 余量日志盘需求约 380GB内存 128G 乘 3单机磁盘合计约 1.3TB数据盘与日志盘分开挂载这个算法不精确但它能让你在采购前一分钟内给出一个有理有据的数字而不是先买两台试试。4. 从单节点到三副本集群的完整部署流程4.1 环境初始化目录、用户、权限三台机器上都执行同样的初始化。创建admin用户禁止它登录 shell 以外的东西没必要但一定要把家目录设对。然后建目录sudo useradd -U admin -s /bin/bash -m /home/admin sudo passwd admin sudo mkdir -p /data/1 /data/log1 sudo chown -R admin:admin /data /home/admin/data/1是数据目录/data/log1是 clog 目录。这两个目录最好在不同的物理盘上如果只有一块盘至少分成不同分区避免日志写入和合并 IO 直接竞争。目录权限这块要特别注意整个目录树必须归属admin用户中间任何一级目录权限不对服务启动都会失败而且报错信息不一定明确指向权限问题。我的习惯是初始化完就ls -ld挨个确认一遍。4.2 部署工具选型命令行还是图形化平台2.2 这个时期主流的部署方式有两种命令行的部署工具和图形化的管理平台。我的建议是先用命令行工具把集群跑起来把每一步理解透再上管理平台做日常运维。命令行的好处是过程透明每一步做了什么你都清楚出问题能定位。图形化平台的好处是省事批量运维、监控告警、备份恢复都有现成界面。但如果你连命令行怎么部署都不清楚平台报错的时候你只能干瞪眼。命令行工具的安装很简单下载对应的包用包管理器装好然后把安装包上传到本地仓库。这里有个细节三台机器都要能被工具访问到通常是通过 SSH 免密这一点在配置文件里会体现。# 安装部署工具 sudo rpm -ivh oceanbase-deployer-x.x.x.x.x-1.el7.x86_64.rpm # 上传安装包到本地镜像仓库 obd mirror clone oceanbase-x.x.x.x-xxxx.el7.x86_64.rpm obd mirror list localobd mirror list local能看到包名和版本说明仓库就绪了。这一步如果看不到包说明上传路径不对或者包架构不匹配。4.3 配置文件怎么写每一行都有讲究配置文件是整个部署的核心我用一个三 Zone 的完整例子来讲。oceanbase-ce: servers: - name: server1 ip: 10.0.0.11 - name: server2 ip: 10.0.0.12 - name: server3 ip: 10.0.0.13 global: devname: eth0 memory_limit: 48G system_memory: 10G datafile_size: 800G datafile_disk_percentage: 0 syslog_level: INFO enable_syslog_recycle: true max_syslog_file_count: 4 appname: obcluster root_password: 具体密码自己定 proxy_id: 1 server1: zone: zone1 server2: zone: zone2 server3: zone: zone3逐行解释几个关键项。devname是网卡名写错会导致服务绑定到错误网卡集群内通信失败这是最常见的部署失败原因之一一定要用ip addr确认。memory_limit和system_memory前面已经算过48G 和 10G 是对应关系剩下约 38G 分给租户。datafile_size是数据文件大小设成 800G 对应前面算的 900GB 需求。datafile_disk_percentage设为 0 表示不使用百分比自动计算而是用datafile_size的绝对值这样更可控。appname是集群名后面连接串里的#后面就是它起名要短、要有辨识度、不能带特殊字符。root_password是系统租户的密码生产环境必须设强密码别图省事。注意appname一旦定下来后面改起来很麻烦因为涉及元数据和连接串。部署前想好别用test、ob这种一看就是临时环境的词。4.4 部署与启动从命令到验证配置文件准备好两条命令搞定部署和启动。obd cluster deploy obcluster -c config.yaml obd cluster start obcluster第一条命令做的是分发安装包、初始化目录、写配置不会启动进程。第二条才真正拉起服务、完成 bootstrap。第一次启动耗时比较长因为要初始化数据文件、建立元数据三台机器之间还要完成一次选主正常三到五分钟。如果超过十分钟还没起来大概率是卡住了直接去看日志。验证这一步不能省必须确认三个节点都是 active 状态-- 用系统租户连进去 obclient -h10.0.0.11 -P2881 -urootsys -p -c -A oceanbase -- 查看节点状态 SELECT zone, svr_ip, status, with_rootserver FROM oceanbase.__all_server;status必须是active三个 Zone 都要有记录。如果某个节点是inactive看它的日志通常是网络不通或者时钟偏差。with_rootserver为 1 的那个是 RootService 所在节点负责元数据管理和调度。顺便看一眼资源SELECT zone, svr_ip, cpu_total, cpu_assigned, mem_total, mem_assigned FROM oceanbase.__all_virtual_server_stat;cpu_assigned和mem_assigned不能接近总量否则后面建租户会失败。4.5 部署代理层并建第一个业务租户代理层单独部署配置文件里指定后端集群和监听端口。obproxy: servers: - name: proxy1 ip: 10.0.0.21 global: listen_port: 2883 prometheus_listen_port: 2884 rs_list: 10.0.0.11:2881;10.0.0.12:2881;10.0.0.13:2881 cluster_name: obcluster obproxy_sys_password: 自己定 skip_proxy_sys_tenant_auth: truers_list是三个 OBServer 的地址代理靠它发现后端集群。cluster_name必须和appname完全一致少一个字母都连不上。代理起来之后用系统租户建规格、建资源池、建租户三步走-- 1. 建规格 CREATE RESOURCE UNIT unit_biz MAX_CPU 12, MAX_MEMORY 32G, MAX_IOPS 10000, MAX_DISK_SIZE 500G, MAX_SESSION_NUM 2000; -- 2. 建资源池 CREATE RESOURCE POOL pool_biz UNIT unit_biz, UNIT_NUM 1, ZONE_LIST (zone1,zone2,zone3); -- 3. 建租户 CREATE TENANT biz_t1 RESOURCE_POOL_LIST (pool_biz), REPLICA_NUM 3, ZONE_LIST (zone1,zone2,zone3), PRIMARY_ZONE zone1;zone2,zone3, CHARSET utf8mb4;UNIT_NUM 1表示每个 Zone 一个 Unit配合三副本刚好形成标准的三副本租户。PRIMARY_ZONE的写法是有顺序的分号前是首选逗号是备选主副本会优先落在首选 Zone 上。如果你想让写入压力分摊到多个 Zone可以把它设成RANDOM但要注意这会带来跨 Zone 的分布式事务变多。这里最容易出错的点是内存。MAX_MEMORY的数值乘以 Zone 数不能超过集群总可用内存也就是(memory_limit - system_memory)再留 10% 余量。12 核 32G 这个规格在 48G / 10G 的配置下是安全的。4.6 连接测试与建表验证租户建好之后通过代理连业务租户obclient -h10.0.0.21 -P2883 -urootbiz_t1#obcluster -p -c -A biz_db注意用户名格式后面是租户名#后面是集群名两个都不能省。密码是建租户时设的如果没设需要先改。连上之后建库建表验一下分区表能不能正常创建CREATE DATABASE biz_db DEFAULT CHARSET utf8mb4; USE biz_db; CREATE TABLE t_order ( id BIGINT NOT NULL, user_id BIGINT NOT NULL, create_time DATETIME NOT NULL, amount DECIMAL(12,2), PRIMARY KEY (id, create_time) ) PARTITION BY RANGE(create_time) SUBPARTITION BY HASH(user_id) SUBPARTITIONS 8 ( PARTITION p202401 VALUES LESS THAN (2024-02-01), PARTITION p202402 VALUES LESS THAN (2024-03-01), PARTITION p202403 VALUES LESS THAN (2024-04-01) );这个表结构体现了两级分区一级按时间切方便按月度归档删除二级按user_id打散避免当月分区成为写入热点。主键必须包含分区键这是分区表的硬性要求很多人第一次建表会在这里报错。验证分区裁剪有没有生效用EXPLAIN看执行计划里扫描的分区数量EXPLAIN SELECT * FROM t_order WHERE create_time 2024-02-01 AND create_time 2024-03-01;执行计划里应该只出现p202402出现多个说明裁剪没生效回去检查条件写法。5. 上线后最容易翻车的地方5.1 部署期的高频故障与排查路径部署阶段的问题相对集中我按发生概率排了个序。时钟偏差是头号杀手表现是 bootstrap 卡住或者节点反复inactive日志里是选举超时或者日志回放失败。排查方式就是三台机器date对比或者看时间同步服务的偏移量。网卡名写错是第二高发问题。表现是服务起来了但集群连不通__all_server里只有部分节点。用ip addr确认实际网卡改配置重新部署。内存不足排在第三。表现是启动过程中进程退出日志明确提示内存分配失败。原因是memory_limit设得比物理内存还大或者system_memory占得太少导致租户内存不够初始化。改配置重来别硬扛。目录权限问题容易被忽视。服务能起来但写不了数据日志里一堆 IO 错误。ls -ld逐级确认把整棵目录树的属主都改成部署用户。5.2 运行期的典型故障合并卡住与磁盘水位上线之后最典型的问题是合并失败。表现是监控里合并任务持续运行超过预期时间或者直接失败磁盘使用率持续上涨不下降。合并失败的原因基本就两个磁盘空间不够或者 IO 被打满。磁盘不够很好判断看df -h。IO 问题看监控里的磁盘 util 和 await如果持续在 90% 以上说明合并在和业务抢资源。处理方式分两步。短期把合并窗口调到业务低峰期2.2 支持配置合并的开始时间避开高峰。长期看是不是数据量增长太快需要扩容或者检查是不是有超大分区需要拆分。参数字面上可以调大合并并发但那是透支 IO治标不治本。磁盘水位这块我把自己的监控阈值整理成表可以直接拿去配告警水位状态处置动作70%正常无需动作关注增长趋势75%关注检查是否有异常大表或未清理的历史分区80%预警停止大批量导入安排清理或扩容85%危险立即清理历史分区禁止写入大事务90%紧急合并随时可能失败准备紧急扩容5.3 连接类报错速查连接问题是最费时间的因为报错信息往往不指向真实原因。这张表是我这些年攒下来的经验对照。现象可能原因排查方式连不上 2883代理进程没起或端口被占代理机器上netstat -lntp看端口报租户不存在连接串少了#集群名确认格式为用户租户#集群名提示认证失败密码错或用了错误的租户先用rootsys确认租户存在连上后查询报超时分区 Leader 在切主中查__all_virtual_leader看 Leader 分布偶发连接断开代理层超时或后端节点被摘除看代理日志和节点状态大批量写入报内存不足租户内存不够或有超大事务查租户内存使用率拆分事务5.4 一个真实的排查案例说个具体的。有次测试环境集群突然只读业务报写入失败。第一反应是磁盘满查了发现还有 40% 空间。第二反应是某个节点挂了查__all_server三个都是 active。继续查看 Leader 分布发现大量分区的 Leader 集中在同一个 Zone而那个 Zone 的一个节点刚重启过。原因是重启后 Leader 选举集中到了同机房的另一个节点上负载不均导致该节点写入排队最终触发保护性限流。处理方式是手工触发 Leader 均衡把压力打散。这类问题的根因是 Leader 分布不均而分布不均的常见诱因是节点重启。所以后续我们的运维规范里加了一条任何节点重启后必须检查一次 Leader 分布。6. 运维期的几个关键动作6.1 监控该看什么别被指标淹没监控指标成百上千真正需要盯的就那么几个。第一梯队是节点状态和 Leader 分布。节点掉线是最高优先级告警Leader 分布不均是性能问题的先兆。第二梯队是磁盘水位和合并状态这两个直接决定集群能不能稳定运行。第三梯队是租户级别的 QPS、慢查询数、连接数用于定位业务侧问题。我的建议是先把这三类做成看板每个看板不超过十个指标。指标太多会导致告警疲劳最后所有告警都被忽略。6.2 备份策略别等到出事才想起验证2.2 的备份是集群级物理备份需要先配置备份目录和日志归档目录。配置好之后可以发起全量备份配合日志归档能做到时间点恢复。这里我要强调一件被无数人忽略的事备份一定要定期做恢复演练。我见过太多团队备份任务天天成功真出事的时候发现备份文件恢复不了因为备份期间某个节点异常导致备份集不完整。恢复演练不用太频繁一个季度一次在隔离环境里恢复一个租户出来验证数据完整性这个动作能救命。备份目录的容量也要算。全量备份的数据量约等于单副本落盘数据量如果保留三份全量需要三倍的容量。加上日志归档建议按数据量的四倍预留。6.3 扩容怎么做才不影响业务扩容分两种加机器和加 Zone。加机器简单把新节点加入集群然后迁移部分 Unit 过去迁移过程是在线的但会占用网络和 IO建议限速并在低峰期做。加 Zone 更复杂因为涉及副本重新分布。流程是先加 Zone再调整租户的ZONE_LIST和副本数然后等数据自动补齐。整个过程集群可读写但补齐期间 IO 压力较大。数据量大的话补齐可能要跑几个小时甚至一天这段时间要密切监控磁盘和网络。扩容前一定要确认目标机器的时钟已经同步、内核参数已经调好、目录权限已经配好。我见过扩容到一半失败原因是新机器的时钟没配补数据的过程反复中断。6.4 升级前必须做的三件事升级这件事版本跨度小风险低跨度大就要谨慎。升级前必做三件事一是完整备份并验证可恢复二是在预发环境跑一遍完整升级流程记录耗时和每一步的输出三是准备好回滚方案并且确认回滚方案真的能执行不是写在文档里好看。升级窗口要留足别按预发环境的耗时乘以一个系数就完事生产数据量大合并和元数据变更的耗时会显著增加。宁可在窗口里多等一会儿也不要在业务高峰手忙脚乱。最后分享一个我自己一直在用的小习惯每次部署完一套新集群我会写一份这集群我是怎么搭起来的的备忘录记录所有偏离默认配置的地方和原因以及当时踩过的坑。这份备忘录在半年后排查问题时比任何官方文档都管用因为它是针对这套具体环境的。技术细节会忘但记录不会。
阅读完成 · 觉得有帮助?