CouchDB 集群节点管理实战:通过 `_membership` 与 `_nodes` 数据库安全地添加和移除节点
数据库文档数据库后端【免费下载链接】couchdbSeamless multi-primary syncing database with an intuitive HTTP/JSON API, designed for reliability项目地址https://gitcode.com/gh_mirrors/co/couchdb点击查看免费下载导读本文基于 CouchDB 官方集群文档src/docs/src/cluster/nodes.rst系统讲解集群节点的添加与移除全流程如何通过/_membership端点查看节点视图、如何通过节点本地node-localAPI 向_nodes系统数据库写入或删除节点文档以及移除节点前必须完成的分片shard迁移步骤。读完本文你将掌握使用纯 HTTP 命令完成节点生命周期管理的能力并能理解这些操作背后的mem3模块实现原理。一、认识集群节点视图GET /_membership节点管理的第一步是准确掌握当前集群中知道哪些节点和连接了哪些节点。CouchDB 提供了GET /_membership端点来回答这个问题curl -X GET http://xxx.xxx.xxx.xxx:5984/_membership --user admin-user响应示例{ all_nodes:[ node1xxx.xxx.xxx.xxx], cluster_nodes:[ node1xxx.xxx.xxx.xxx] }两个字段的含义有本质区别all_nodes当前节点知道的所有节点。从源码看它由lists:sort([node() | nodes()])构成src/mem3/src/mem3_httpd.erl即本节点加上 Erlang 分布式层面已建立连接的所有节点无论它们是否已是集群正式成员。cluster_nodes已正式加入集群、出现在_nodes系统数据库中的节点列表。它来自mem3:nodes()即mem3_nodes:get_nodelist()src/mem3/src/mem3.erl而该列表最终由每个节点维护的 ETS 表提供。该端点在代码中注册为顶层 URL handlersrc/mem3/src/mem3_httpd_handlers.erl并只接受GET方法其他方法会返回405 Method Not Allowedsrc/mem3/src/mem3_httpd.erl。由于涉及集群成员信息该端点需要管理员权限访问。在集群初始搭建完成执行_cluster_setup的finish_cluster动作后官方集群设置文档同样建议用_membership验证所有节点是否已连接src/docs/src/setup/cluster.rstcurl http://admin:passwordsetup-coordination-node:5984/_membership{ all_nodes: [ couchdbcouch1.test.com, couchdbcouch2.test.com, couchdbcouch3.test.com, ], cluster_nodes: [ couchdbcouch1.test.com, couchdbcouch2.test.com, couchdbcouch3.test.com, ] }运维提示如果all_nodes与cluster_nodes两个列表不一致说明有节点已建立 Erlang 连接但尚未正式入群或反过来需要按下文的方法手动补齐或清理节点文档。二、添加节点一条 PUT 命令完成入群2.1 标准操作流程当新节点例如node2yyy.yyy.yyy.yyy已经启动并运行 CouchDB 后在任意一个已入群的节点上执行curl -X PUT http://xxx.xxx.xxx.xxx/_node/_local/_nodes/node2yyy.yyy.yyy.yyy -d {}这条命令的本质是通过xxx.xxx.xxx.xxx节点上的node-local API向该节点本地的_nodes系统数据库写入一个以节点名称为_id的文档空 body 表示不携带额外属性。再次查看_membership两个列表都将同时出现两个节点{ all_nodes:[ node1xxx.xxx.xxx.xxx, node2yyy.yyy.yyy.yyy ], cluster_nodes:[ node1xxx.xxx.xxx.xxx, node2yyy.yyy.yyy.yyy ] }此时一个 2 节点的集群便已形成。2.2 为什么只需要添加一次原文档特别强调在http://yyy.yyy.yyy.yyy:5984/_membership上查看也会得到相同结果因此只需添加一次。其原理隐藏在mem3模块的复制机制中_nodes与_dbs、_users等是 CouchDB 的系统数据库会被自动复制到所有集群节点。mem3_sync的local_dbs()会把这些数据库列为需要同步的对象src/mem3/src/mem3_sync.erl数据库名称可通过[mem3] nodes_db配置项覆盖默认即为_nodessrc/mem3/src/mem3_sync.erl。每个节点的mem3_nodes进程都会对_nodes数据库开启continuous changes feed监听src/mem3/src/mem3_nodes.erl文档新增时触发add_node事件并更新本地 ETS 节点表文档被删除时触发remove_node事件。mem3_sync_event收到{add_node, Node}事件后会尝试建立分布式连接并调用mem3_sync_nodes:add([Node])执行初始数据同步src/mem3/src/mem3_sync_event.erl把本地的分片元数据等信息推送/复制到新节点从而让新节点成为名副其实的集群成员。因此_nodes数据库是全集群节点视图的单一事实来源source of truth改一处、同步全网。2.3 节点命名的工程约定节点名采用nodehost形式其中后的部分必须是集群内可路由的主机名或 IP 地址集群设置文档明确要求使用couchdbreachable-ip-address|fully-qualified-domain-namesrc/docs/src/setup/cluster.rst。同时setup应用创建节点文档时使用的也正是NameHost格式src/setup/src/setup.erl。这一点对后续集群通信至关重要——CouchDB 依赖 Erlang 分布式协议在节点间直接互联节点名必须彼此可解析、可直连。三、移除节点先迁分片再删文档3.1 前置条件把所有分片从该节点移走原文档明确要求在移除节点之前必须先把该节点上的全部分片shards迁移走参见 分片移动章节。这一要求不是文档建议而是集群数据安全的前提——如果不迁移分片就删除节点文档这些分片上的数据将失去归属集群可能因此丢失副本或返回不一致结果。完整的分片移动流程详见 src/docs/src/cluster/sharding.rst大致为确保目标节点已加入集群即本文第二节的操作。将分片文件与二级索引分片文件复制到目标节点数据库分片位于data/shards/视图/Mango 索引分片位于data/.shards/可用cp、rsync、scp等命令搬运注意先移动视图文件再移动数据库文件否则视图索引可能被重建。通过配置端点PUT /_node/{node-name}/_config/couchdb/maintenance_mode将目标节点置为true维护模式使其在/_up上返回 404配合负载均衡器如 HAProxy 的http-check disable-on-404暂时下线。更新_dbs系统数据库中的分片映射元数据通过 node-local 端点/_node/_local/_dbs/{name}读取、修改changelog、by_node、by_range三个字段后PUT回去把目标节点加入分片副本列表。调用POST /{db}/_sync_shards强制同步分片并通过/_node/{node-name}/_system的internal_replication_jobs指标确认副本已追平。清除维护模式再从_dbs元数据中移除源节点[remove, {range}, {node-name}]changelog 条目最后删除源节点上的分片与索引文件。分片移动过程涉及_dbs元数据的手工编辑官方文档对此有明确警告操作失误可能不可修复地损坏集群务必谨慎src/docs/src/cluster/sharding.rst。3.2 获取节点文档的修订号_rev_nodes数据库与其他 CouchDB 数据库一样采用 MVCC 修订模型。删除节点文档必须携带其当前修订号因此先查询curl http://xxx.xxx.xxx.xxx/_node/_local/_nodes/node2yyy.yyy.yyy.yyy {_id:node2yyy.yyy.yyy.yyy,_rev:1-967a00dff5e02add41820138abb3284d}响应中的_rev形如1-967a00dff5e02add41820138abb3284d即该节点文档的最新修订。若期间有并发的元数据修改例如为节点添加了zone属性_rev会变化需要重新查询后再删除。3.3 执行删除携带上一步获得的_rev通过查询参数rev提交删除curl -X DELETE http://xxx.xxx.xxx.xxx/_node/_local/_nodes/node2yyy.yyy.yyy.yyy?rev1-967a00dff5e02add41820138abb3284d删除完成后_nodes数据库的 changes feed 会向全集群广播该变更mem3_nodes的 changes 回调检测到文档已删除调用remove_node事件并从 ETS 节点表中移除该节点src/mem3/src/mem3_nodes.erlmem3_sync_event随之触发mem3_sync:remove_node(Node)清理相关状态src/mem3/src/mem3_sync_event.erl。此后该节点不再属于集群_membership的cluster_nodes中也不会再出现它。四、节点文档不只是存在性标记节点文档_nodes数据库中以nodehost为_id的文档并不仅仅标记某节点存在它还可以携带自定义属性被mem3用于更精细的集群策略zone可用区属性配合[cluster] placement配置可以在建库时强制分片副本落在指定可用区节点上例如placement {zone-name-1}:2,{zone-name-2}:1表示两个副本落在 zone-1、一个副本落在 zone-2。给某节点设置一个未出现在 placement 字符串中的 zone 值还可以让该节点不承接任何新建库的分片src/docs/src/cluster/sharding.rst。设置方式同样是编辑节点文档curl -X PUT http://adm:passlocalhost:5984/_node/_local/_nodes/{node-name} \ -d { _id: {node-name}, _rev: {rev}, zone: {zone-name} }decom退役标记mem3的allowed_nodes()会过滤掉decom属性为true的节点使其不再参与新分片的放置src/mem3/src/mem3.erl。对应的 eunit 测试也验证了这一行为src/mem3/src/mem3.erl。由此可见_nodes节点文档是全集群元数据的核心载体所有针对它的写操作添加、属性修改、删除都应通过 node-local API/_node/_local/_nodes/{node-name}在单节点上完成再由mem3的复制与 changes 监听机制传播到全集群。五、常见问题与操作注意事项all_nodes与cluster_nodes不一致通常意味着节点文档与 Erlang 连接状态不同步。若cluster_nodes缺少某节点按第二节执行 PUT 补齐若cluster_nodes出现了不应存在的节点且该节点已下线按第三节执行 DELETE 清理。_membership返回 405该端点仅支持GET确认请求方法无误。删除节点前务必完成分片迁移跳过该步骤会直接导致数据副本丢失或集群分片视图不一致这是节点管理中风险最高的操作。_rev过期节点文档被并发修改后如添加zone属性旧_rev的 DELETE 会失败需重新 GET 获取最新修订。节点名必须可路由之后的主机名/IP 必须在所有节点间互相可达否则新节点虽写入_nodes也无法参与集群通信。六、总结CouchDB 的集群节点管理由两大部分构成GET /_membership提供全集群统一的节点视图all_nodes表示已连接的节点、cluster_nodes表示已入群的节点node-local API/_node/_local/_nodes/{node-name}则是对_nodes系统数据库的唯一合法读写入口。添加节点只需一次 PUT删除节点则必须在完成全部分片迁移后携带最新_rev执行 DELETE。所有操作都由mem3应用src/mem3/src/mem3_nodes.erl、src/mem3/src/mem3_sync.erl通过系统数据库复制与 continuous changes feed 同步到整个集群实现了一次写入、全网生效的成员管理模型。如需深入分片迁移细节可继续阅读 分片管理文档节点视图的完整 API 规范见 API 参考文档。赞分享数据库文档数据库后端【免费下载链接】couchdbSeamless multi-primary syncing database with an intuitive HTTP/JSON API, designed for reliability项目地址https://gitcode.com/gh_mirrors/co/couchdb点击查看免费下载相关推荐Proxmox VE Helper-Scripts集群节点添加与移除指南Proxmox VE Helper Scripts集群节点添加与移除指南 在使用Proxmox VE构建虚拟化环境时集群Cluster功能能够将多台物理服运维虚拟化DevOps10分钟上手PretendYoureXyzzy快速搭建与配置全攻略10分钟上手PretendYoureXyzzy快速搭建与配置全攻略 PretendYoureXyzzy是一个功能强大的随机信息生成工具专为编程练习、测试和数无缝扩展TiKV集群节点添加与移除全攻略无缝扩展TiKV集群节点添加与移除全攻略 你是否遇到过业务增长导致TiKV集群存储不足或者需要下线老旧服务器却担心影响服务可用性本文将详细介绍TiKV集群数据库KV存储分布式数据库云原生上一篇免费开源AMD Ryzen调试神器5个核心技巧彻底释放处理器潜能下一篇Salt rest_cherrypy 实战指南用 CherryPy 为 Salt Master 构建生产级 REST API创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考