Article
第一章:CouchDB 基础概念
1.1 什么是 CouchDB
| 名称 | 说明 | 注意事项 |
|---|---|---|
| CouchDB 定义 | Apache CouchDB 是一个开源的、面向文档的 NoSQL 数据库,使用 JSON 存储数据,通过 HTTP/REST API 提供访问接口,支持多主复制和离线优先架构。 | 不依赖传统 SQL,所有操作通过 HTTP 方法(GET/POST/PUT/DELETE)完成。 |
| 核心特性 | - 数据以 JSON 文档形式存储 - 每个文档有唯一 _id 和版本号 _rev- 内置 Web 管理界面 Fauxton - 支持 ACID 语义的本地事务 - 多主(multi-master)复制能力 | _rev 是 CouchDB 实现乐观并发控制的关键,不可忽略。 |
| 设计哲学 | ”Offline First”:优先支持设备离线使用,网络恢复后自动同步;强调数据一致性与可用性在分布式环境下的平衡。 | 适用于移动应用、IoT、边缘计算等弱网或断网场景。 |
1.2 文档模型与 JSON 结构
| 名称 | 说明 | 注意事项 |
|---|---|---|
| 文档(Document) | CouchDB 中的基本数据单元,是一个无模式(schema-less)的 JSON 对象,必须包含 _id 字段(可自动生成)。 | 用户不能直接修改 _id,但可指定;若未提供,CouchDB 自动生成 UUID。 |
| 系统字段 | - _id:文档唯一标识符(字符串)- _rev:修订版本号(如 "1-abc123"),用于版本控制和冲突检测 | _rev 在更新或删除文档时必须提供,否则操作失败。 |
| 用户字段 | 任意合法 JSON 键值对,如 { "name": "Alice", "age": 30, "tags": ["dev", "db"] } | 不支持嵌套事务或跨文档约束;不支持 JOIN。 |
| JSON 规范要求 | 必须是有效的 UTF-8 编码 JSON;不支持 undefined、函数、日期对象(需转为 ISO 8601 字符串) | 日期应存储为 "2025-01-01T00:00:00Z" 格式以便 Mango 查询识别。 |
1.3 数据库、文档、视图的基本关系
| 名称 | 说明 | 注意事项 |
|---|---|---|
| 数据库(Database) | 逻辑容器,用于组织一组文档;名称只能包含小写字母、数字、下划线、连字符(如 users_db)。 | 数据库名不能以 _ 开头(除非是系统数据库如 _users)。 |
| 文档(Document) | 存储在数据库中的独立 JSON 对象;每个数据库可包含任意数量文档。 | 同一数据库中文档彼此独立,无外键关联。 |
| 视图(View) | 通过设计文档(Design Document)定义的查询索引,基于 MapReduce 或 Mango 语法生成;用于高效检索和聚合数据。 | 视图是预计算的,写入时构建索引,读取时快速返回结果;首次访问可能较慢。 |
| 设计文档(Design Doc) | 特殊文档,_id 以 _design/ 开头(如 _design/users),包含 views、lists、shows 等定义。 | 修改设计文档会触发视图重建,影响性能。 |
1.4 CouchDB 与其他 NoSQL 数据库的对比
| 名称 | 说明 | 注意事项 |
|---|---|---|
| vs MongoDB | - MongoDB 使用 BSON,支持丰富查询和索引 - CouchDB 使用纯 JSON + HTTP,强调复制与离线同步 - MongoDB 更适合高吞吐 OLTP,CouchDB 更适合分布式同步场景 | MongoDB 有更复杂的权限模型和聚合管道;CouchDB 架构更简单、部署更轻量。 |
| vs Redis | - Redis 是内存键值存储,侧重缓存与高速读写 - CouchDB 是持久化文档数据库,侧重数据同步与一致性 | 两者用途不同,常互补使用(Redis 缓存 CouchDB 查询结果)。 |
| vs Cassandra | - Cassandra 为高写入吞吐、无单点故障设计,采用宽列模型 - CouchDB 采用文档模型,支持多主复制但扩展性弱于 Cassandra | Cassandra 适合海量日志、时序数据;CouchDB 适合用户数据、配置同步等结构化文档场景。 |
| vs Firebase/Firestore | - Firebase 提供实时监听、SDK 集成,托管服务 - CouchDB 自托管,协议开放(HTTP+JSON),可私有部署 | CouchDB 更适合对数据主权、隐私合规要求高的企业环境。 |
第二章:安装与配置
2.1 在 Linux / macOS / Windows 上安装 CouchDB
| 名称 | 说明 | 注意事项 |
|---|---|---|
| Linux(Ubuntu/Debian)安装 | 使用官方 APT 源:bash<br>sudo apt update<br>sudo apt install -y apt-transport-https<br>echo "deb https://apache.jfrog.io/artifactory/couchdb-deb $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/couchdb.list<br>wget -qO - https://couchdb.apache.org/repo/keys.asc | gpg --dearmor | sudo tee /usr/share/keyrings/couchdb-archive-keyring.gpg > /dev/null<br>sudo apt update<br>sudo apt install couchdb<br> | 安装过程中会提示选择单节点或集群模式;建议初学者选”standalone”。 |
| Linux(CentOS/RHEL)安装 | 使用 YUM/DNF:bash<br>sudo tee /etc/yum.repos.d/couchdb.repo <<EOF<br>[couchdb]<br>name=CouchDB Apache Repo<br>baseurl=https://apache.jfrog.io/artifactory/couchdb-rpm/el\$releasever/\$basearch/<br>gpgcheck=1<br>gpgkey=https://couchdb.apache.org/repo/keys.asc<br>enabled=1<br>EOF<br>sudo dnf install couchdb<br> | 需启用 EPEL 源;防火墙需开放 5984 端口。 |
| macOS 安装 | 使用 Homebrew:bash<br>brew install couchdb<br>brew services start couchdb<br>默认绑定 127.0.0.1:5984;可通过 brew services list 查看状态。 | — |
| Windows 安装 | 从官网下载 .exe 安装包(https://couchdb.apache.org/),运行图形化安装向导;或使用 Scoop:powershell<br>scoop install couchdb<br> | 安装后自动注册为 Windows 服务;可通过服务管理器启停。 |
2.2 单节点与集群模式配置
| 名称 | 说明 | 注意事项 |
|---|---|---|
| 单节点模式(Standalone) | 默认模式,适用于开发、测试或小型生产环境;所有数据存储在单一实例中。 | 安装时选择”single node”即启用;无需额外配置节点发现。 |
| 集群模式(Cluster) | 多节点部署,支持自动分片(sharding)和高可用;需至少 3 节点以实现容错。 | 所有节点必须能通过主机名或 IP 互相访问;时间需同步(建议 NTP)。 |
| 集群初始化命令 | 在首节点执行:bash<br>curl -X POST http://admin:password@127.0.0.1:5984/_cluster_setup \<br> -d '{"action": "enable_cluster", "bind_address":"0.0.0.0", "username":"admin", "password":"password", "node_count":"3"}' \<br> -H "Content-Type: application/json"<br>其他节点加入: bash<br>curl -X POST http://admin:password@leader:5984/_cluster_setup \<br> -d '{"action": "add_node", "host":"new_node_ip", "port":5984, "username":"admin", "password":"password"}' \<br> -H "Content-Type: application/json"<br> | 首次启用集群后需调用 finish_cluster 完成设置;节点密码必须一致。 |
| 验证集群状态 | bash<br>curl http://admin:password@127.0.0.1:5984/_membership<br> | 返回 all_nodes 和 cluster_nodes 列表;两者应一致表示集群健康。 |
2.3 配置文件详解(local.ini / default.ini)
| 名称 | 说明 | 注意事项 |
|---|---|---|
| default.ini | 默认配置文件,位于 /opt/couchdb/etc/default.ini(Linux)或安装目录下;包含 CouchDB 所有默认参数。 | 禁止直接修改;升级时会被覆盖。 |
| local.ini | 用户自定义配置文件,路径同上;优先级高于 default.ini,用于覆盖默认设置。 | 所有自定义配置(如 bind_address、admin 用户)应写入此文件。 |
| 常用配置项 | - [chttpd] bind_address = 0.0.0.0:允许外部访问- [admins] admin = -pbkdf2-...:添加管理员(首次启动后自动生成哈希)- [couchdb] uuid = xxx:集群唯一标识- [httpd] enable_cors = true:启用 CORS | 修改后需重启 CouchDB 生效;密码字段首次设置后自动转为 PBKDF2 哈希。 |
| 配置热加载 | 部分参数(如日志级别)支持运行时更新:bash<br>curl -X PUT http://admin:password@localhost:5984/_config/log/level \<br> -d '"debug"' -H "Content-Type: application/json"<br> | 并非所有配置都支持热更新;持久化配置仍需写入 local.ini。 |
2.4 启动、停止与状态检查(命令行操作)
| 名称 | 说明 | 注意事项 |
|---|---|---|
| 启动 CouchDB(Linux/macOS) | bash<br>sudo systemctl start couchdb # systemd 系统<br>或 bash<br>couchdb # 前台运行(调试用)<br> | 前台运行便于查看日志;生产环境应使用服务方式。 |
| 停止 CouchDB | bash<br>sudo systemctl stop couchdb<br> | 强制 kill 可能导致索引损坏;建议正常停止。 |
| 重启 CouchDB | bash<br>sudo systemctl restart couchdb<br> | 修改 local.ini 后必须重启生效。 |
| 检查服务状态 | bash<br>sudo systemctl status couchdb<br> | 查看是否 active (running)。 |
| 检查 HTTP API 是否就绪 | bash<br>curl http://127.0.0.1:5984/<br>预期返回: json<br>{"couchdb":"Welcome","version":"3.x.x",...}<br> | 若返回 connection refused,检查端口监听和防火墙。 |
| 查看监听端口 | bash<br>ss -tuln | grep 5984<br>或 netstat -tuln | grep 5984 | 确保 bind_address 配置正确(默认仅 127.0.0.1)。 |
| 日志查看 | bash<br>journalctl -u couchdb -f # systemd<br>tail -f /opt/couchdb/var/log/couchdb.log # 直接日志文件<br> | 错误日志对排查启动失败至关重要。 |
第三章:数据库与文档操作(命令行)
3.1 创建与删除数据库
| 方法名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|---|---|---|---|
| 创建数据库 | PUT /{db_name} | 创建一个新数据库,名称需符合命名规则 | curl -X PUT http://admin:password@127.0.0.1:5984/myapp_db | 数据库名只能包含小写字母、数字、下划线、连字符;不能以 _ 开头(除非是系统库如 _users);重复创建返回 412 错误 |
| 删除数据库 | DELETE /{db_name} | 永久删除整个数据库及其所有文档 | curl -X DELETE http://admin:password@127.0.0.1:5984/myapp_db | 删除不可逆;若数据库不存在,返回 404;需管理员权限或数据库所有者权限 |
| 检查数据库是否存在 | HEAD /{db_name} | 验证数据库是否已存在(轻量级) | curl -I http://127.0.0.1:5984/myapp_db | 成功返回 200,不存在返回 404;不返回响应体,节省带宽 |
| 列出所有数据库 | GET /_all_dbs | 获取当前 CouchDB 实例中所有数据库名称列表 | curl http://127.0.0.1:5984/_all_dbs | 返回 JSON 数组,如 ["myapp_db", "_users"];需适当权限(默认允许) |
3.2 插入、更新与删除文档
| 方法名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|---|---|---|---|
插入新文档(指定 _id) | PUT /{db}/{doc_id} | 创建一个具有指定 ID 的文档 | curl -X PUT http://admin:password@127.0.0.1:5984/myapp_db/user123 -d '{"name":"Alice","role":"admin"}' -H "Content-Type: application/json" | 若 _id 已存在且未提供 _rev,返回 409 冲突错误 |
插入新文档(自动生成 _id) | POST /{db} | 让 CouchDB 自动生成 UUID 作为 _id | curl -X POST http://admin:password@127.0.0.1:5984/myapp_db -d '{"name":"Bob"}' -H "Content-Type: application/json" | 响应中包含生成的 _id 和 _rev;适用于无需预知 ID 的场景 |
| 更新文档 | PUT /{db}/{doc_id}?rev={current_rev} | 修改现有文档,必须提供当前 _rev | curl -X PUT http://admin:password@127.0.0.1:5984/myapp_db/user123?rev=1-abc123 -d '{"name":"Alice","role":"superuser","_rev":"1-abc123"}' -H "Content-Type: application/json" | _rev 必须匹配最新版本;否则返回 409;建议从 GET 响应中提取 _rev |
| 删除文档 | DELETE /{db}/{doc_id}?rev={current_rev} | 逻辑删除文档(标记为 deleted) | curl -X DELETE http://admin:password@127.0.0.1:5984/myapp_db/user123?rev=2-def456 | 文档仍存在于磁盘(用于复制同步),但查询时默认不可见;需 _rev 参数 |
3.3 获取文档与修订历史(_rev)
| 方法名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|---|---|---|---|
| 获取文档最新版本 | GET /{db}/{doc_id} | 返回文档当前内容及 _rev | curl http://127.0.0.1:5984/myapp_db/user123 | 返回完整 JSON,含 _id 和 _rev;若文档被删除,返回 404 |
| 获取文档特定修订版 | GET /{db}/{doc_id}?rev={rev_id} | 查看历史版本(需启用 revision tracking) | curl http://127.0.0.1:5984/myapp_db/user123?rev=1-abc123 | 默认保留最近若干修订;旧版本可能被 compaction 清除 |
| 获取文档元数据(不含正文) | HEAD /{db}/{doc_id} | 仅检查文档是否存在并获取 _rev | curl -I http://127.0.0.1:5984/myapp_db/user123 | 响应头包含 ETag(即 _rev),无响应体,高效 |
| 获取所有修订历史 | GET /{db}/{doc_id}?revs_info=true | 返回该文档所有已知修订的状态列表 | curl http://127.0.0.1:5984/myapp_db/user123?revs_info=true | 返回 "_revs_info": [{"rev":"2-def456","status":"available"}, {"rev":"1-abc123","status":"missing"}];missing 表示已被 compact |
| 获取冲突修订(仅在复制冲突时) | GET /{db}/{doc_id}?conflicts=true | 显示当前存在的冲突版本 | curl http://127.0.0.1:5984/myapp_db/user123?conflicts=true | 仅当多主复制产生冲突时返回 "_conflicts" 字段;应用需自行解决 |
3.4 批量文档操作(_bulk_docs)
| 方法名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|---|---|---|---|
| 批量插入/更新/删除 | POST /{db}/_bulk_docs | 一次请求处理多个文档操作,提升效率 | curl -X POST http://admin:password@127.0.0.1:5984/myapp_db/_bulk_docs -d '{"docs": [{"_id":"doc1","name":"X"},{"_id":"doc2","_deleted":true,"_rev":"1-old"}]}' -H "Content-Type: application/json" | 请求体为 {"docs": [...]};每个文档可独立指定 _id、_rev、_deleted |
| 批量获取文档 | POST /{db}/_all_docs?include_docs=true | 根据 _id 列表批量获取完整文档 | curl -X POST http://127.0.0.1:5984/myapp_db/_all_docs?include_docs=true -d '{"keys":["doc1","doc2"]}' -H "Content-Type: application/json" | 返回 rows 数组,每个元素含 doc 字段;缺失 ID 返回 error: “not_found” |
| 批量操作响应格式 | — | 成功时返回每个文档的操作结果 | — | 即使部分失败,其他操作仍可能成功;需逐条检查结果 |
| 批量操作原子性 | — | 非事务性:不保证全部成功或全部失败 | — | 每个文档独立处理;网络中断可能导致部分写入 |
| 使用 new_edits 控制修订 | POST /{db}/_bulk_docs?new_edits=false | 导入已有修订历史(用于复制或迁移) | curl -X POST ... -d '{"new_edits":false, "docs":[{"_id":"x","_rev":"3-abc", ...}]}' | 仅限高级用法;需确保 _rev 合法,否则破坏一致性 |
第四章:视图与查询(MapReduce 与 Mango 查询)
4.1 设计文档(Design Document)结构
| 名称 | 说明 | 注意事项 |
|---|---|---|
| 设计文档定义 | 特殊 JSON 文档,_id 以 _design/ 开头(如 _design/users),用于存储视图、索引、验证函数等逻辑。 | 不能通过普通文档 API 直接查询其内容(需用 GET /db/_design/name);修改后可能触发视图重建。 |
| 基本结构 | 参考以下结构:json<br>{<br> "_id": "_design/report",<br> "views": { ... },<br> "language": "javascript",<br> "validate_doc_update": "function(newDoc, oldDoc, userCtx) { ... }"<br>}<br> | language 默认为 “javascript”;CouchDB 3.x+ 支持 Mango 索引无需指定 language。 |
| views 字段 | 包含一个或多个视图定义,每个视图有 map(必选)和 reduce(可选)函数。 | map 函数必须调用 emit(key, value);reduce 用于聚合(如 _sum, _count 或自定义)。 |
| indexes 字段(Mango) | 用于定义 Mango 查询的 JSON 索引:json<br>"indexes": {<br> "email_idx": {<br> "index": {"fields": ["email"]}<br> }<br>}<br> | 仅在使用 Mango 查询且需加速时使用;自动索引对简单查询已足够。 |
| 权限与部署 | 设计文档受数据库权限控制;通常由管理员或应用初始化脚本创建。 | 避免频繁更新设计文档,因其会清空并重建对应视图索引,影响性能。 |
4.2 使用 MapReduce 创建自定义视图
| 方法名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|---|---|---|---|
| 定义 Map 函数 | 在设计文档的 views.view_name.map 中编写 JavaScript 函数 | 提取文档字段作为索引键值对 | 参考以下结构:json<br>"views": {<br> "by_status": {<br> "map": "function(doc) { if (doc.status) emit(doc.status, doc.name); }"<br> }<br>}<br> | emit() 可多次调用;未 emit 的文档不进入视图;函数体必须是字符串 |
| 定义 Reduce 函数 | 在 views.view_name.reduce 中编写 JS 函数,或使用内置函数 | 对 map 输出进行聚合 | 内置 reduce:"_count"自定义: "function(keys, values) { return sum(values); }" | 内置 reduce:_sum, _count, _stats;自定义 reduce 必须满足 associative & commutative |
| 查询视图 | GET /{db}/_design/{ddoc}/_view/{view} | 获取视图结果 | curl http://127.0.0.1:5984/myapp_db/_design/report/_view/by_status | 首次查询会构建索引,较慢;后续查询从 B-tree 快速读取 |
| 视图查询参数 | 支持 ?key=..., ?startkey=..., ?endkey=..., ?group=true, ?reduce=false 等 | 控制返回结果范围与格式 | curl ".../by_status?startkey=\"active\"&endkey=\"active\"&include_docs=true" | include_docs=true 可附带完整文档;reduce=false 强制返回 map 结果 |
| 更新视图索引 | 自动在文档写入时增量更新;也可手动触发 | 确保视图与数据一致 | 访问视图 URL 即触发构建;无显式”刷新”命令 | 大量写入后首次查询可能延迟高;可后台预热 |
4.3 使用 Mango 查询语言进行富查询
| 方法名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|---|---|---|---|
| 基本 Mango 查询 | POST /{db}/_find + JSON 查询体 | 类 MongoDB 的声明式查询 | curl -X POST http://127.0.0.1:5984/myapp_db/_find -d '{"selector":{"age":{"$gt":25}}}' -H "Content-Type: application/json" | 默认使用主索引(全表扫描);复杂查询需建索引 |
| 常用选择器操作符 | $eq, $ne, $lt, $lte, $gt, $gte, $in, $nin, $exists, $regex | 构建条件表达式 | {"selector": {"name": {"$regex": "^A"}}} | $regex 不区分大小写需额外处理;不支持全文搜索 |
| 逻辑操作符 | $and, $or, $not | 组合多个条件 | {"selector": {"$and": [{"age": {"$gte": 18}}, {"role": "user"}]}} | $or 性能较差,建议配合索引使用 |
| 投影(选择字段) | "fields": ["name", "email"] | 限制返回字段 | {"selector": {...}, "fields": ["name", "email"]} | 默认返回完整文档;_id 始终包含 |
| 分页与排序 | "sort": [{"age": "desc"}], "limit": 10, "skip": 20 | 控制结果顺序与分页 | {"selector": {...}, "sort": [{"created_at": "desc"}], "limit": 5} | sort 字段必须有索引;否则报错;skip 在大数据集下效率低 |
| 创建 Mango 索引 | POST /{db}/_index | 加速特定查询 | curl -X POST ... -d '{"index": {"fields": ["age"]}, "name": "age_idx", "type": "json"}' | 索引类型:“json”(默认)或 “text”(全文);重复创建返回已存在信息 |
4.4 索引管理与性能优化
| 名称 | 说明 | 注意事项 |
|---|---|---|
| 查看所有索引 | GET /{db}/_index | 列出当前数据库所有 Mango 和文本索引 |
| 删除 Mango 索引 | DELETE /{db}/_index/{ddoc}/{type}/{name} | 清理不再需要的索引 |
| 视图 vs Mango 性能 | - 视图:写时构建,读极快,适合固定报表 - Mango:读时动态索引(若无预建),灵活但可能慢 | 高频查询应优先使用视图;探索性查询可用 Mango + 索引 |
| 索引选择建议 | - 等值查询 → 单字段索引 - 范围查询 → 排序字段索引 - 复合查询 → 覆盖所有 sort 和 selector 字段的复合索引 | 例如:{"selector": {"a":1, "b":{"$gt":5}}, "sort": [{"b":"asc"}]} → 索引 ["a", "b"] |
| 监控查询性能 | 启用 execution_stats:{"selector":..., "execution_stats": true} | 返回 total_keys_examined, total_docs_examined 等指标 |
| 避免全表扫描 | 确保 selector 中至少有一个字段有索引;避免 $not, $ne, $regex 开头通配 | 全表扫描在大库中极慢且消耗内存 |
第五章:复制与同步机制
5.1 数据库复制原理
| 名称 | 说明 | 注意事项 |
|---|---|---|
| 复制定义 | CouchDB 的复制是基于文档修订(_rev)的增量同步机制,通过 HTTP(S) 在两个数据库之间拷贝文档及其历史。 | 复制是主从无关的(multi-master),任意两个 CouchDB 实例均可互相同步。 |
| 乐观复制模型 | 每个文档维护 _rev 版本树;冲突在读取时检测,由应用层解决。 | 写入时不加锁;冲突表现为多个 leaf revision,需通过 ?conflicts=true 发现。 |
| 复制过程 | 1. 源库列出所有文档 ID 和当前 _rev2. 目标库比对本地 _rev3. 仅传输缺失或更新的文档 4. 目标库写入并生成新 _rev(若本地有修改则产生冲突) | 复制是幂等的:重复执行不会破坏数据一致性。 |
| 复制类型 | - Pull:目标主动拉取源 - Push:源主动推送至目标 实际效果相同,仅发起方不同 | 命令行中通过指定 source 和 target 决定方向。 |
| 系统要求 | 源和目标数据库必须可通过 HTTP 访问;认证凭据需具备读(源)和写(目标)权限。 | 若使用 HTTPS,需处理证书信任(如 -k 跳过验证仅用于测试)。 |
5.2 单向与双向复制配置(命令行)
| 方法名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|---|---|---|---|
| 单向复制(Push) | POST /_replicate + { "source": "db1", "target": "http://user:pass@remote:5984/db2" } | 将本地数据库推送到远程 | curl -X POST http://admin:password@127.0.0.1:5984/_replicate -d '{"source":"local_db","target":"http://admin:password@remote_host:5984/remote_db"}' -H "Content-Type: application/json" | source 可为本地名或 URL;target 必须为完整 URL(含认证) |
| 单向复制(Pull) | 同上,交换 source 与 target | 从远程拉取到本地 | curl -X POST ... -d '{"source":"http://.../remote_db","target":"local_db"}' | 本地数据库需预先存在;否则返回 404 |
| 双向复制 | 分别配置两次单向复制(A→B 和 B→A) | 实现多主同步 | bash<br># A → B<br>curl -X POST A/_replicate -d '{"source":"db","target":"B/db"}'<br># B → A<br>curl -X POST B/_replicate -d '{"source":"db","target":"A/db"}'<br> | 需确保两端时间同步;避免高频循环写入导致冲突风暴 |
| 复制响应 | 成功返回 {"ok":true,"session_id":"...","replication_id_version":...} | 确认复制任务已接受 | — | 若返回 {"error":"db_not_found"},检查数据库是否存在及权限;复制是异步后台任务,响应快不代表数据已同步完成 |
| 查看活动复制 | GET /_active_tasks | 列出当前运行的复制任务 | curl http://127.0.0.1:5984/_active_tasks | 返回包含 type:"replication", progress, source, target 的列表 |
5.3 连续复制与过滤复制
| 方法名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|---|---|---|---|
| 连续复制 | 在复制请求中添加 "continuous":true | 启动长期监听,自动同步后续变更 | curl -X POST ... -d '{"source":"db1","target":"db2","continuous":true}' | 返回 _local/... ID;任务持续运行直至显式取消 |
| 取消连续复制 | POST /_replicate + {"replication_id":"...", "cancel":true} | 终止已启动的连续复制 | curl -X POST ... -d '{"replication_id":"abcdefg","cancel":true}' | replication_id 来自 _active_tasks 或初始响应中的 _local/... 字段 |
| 过滤复制(文档级) | 定义设计文档中的 filter 函数,并在复制时引用 | 仅同步满足条件的文档 | 设计文档:json<br>{"_id":"_design/filters","filters":{"active_only":"function(doc, req) { return doc.status === 'active'; }"}}<br>复制请求: {"source":"db","target":"db2","filter":"filters/active_only"} | filter 函数必须返回 true/false;req 包含查询参数(可用于动态过滤) |
| 过滤复制(查询参数) | 在复制 URL 中附加 ?param=value,在 filter 中通过 req.query 获取 | 动态控制过滤逻辑 | filter 函数:function(doc, req) { return doc.tenant === req.query.tenant; }复制请求: {"source":"db?tenant=acme","target":"db2","filter":"filters/by_tenant"} | 查询参数需 URL 编码;适用于多租户场景 |
| 视图过滤(旧版) | 使用 query_params + map 函数(已不推荐) | 兼容旧系统 | — | 新项目应使用标准 filter 函数 |
5.4 多设备离线同步场景应用
| 名称 | 说明 | 注意事项 |
|---|---|---|
| 典型架构 | 中央服务器(CouchDB) + 多个边缘设备(PouchDB 或 CouchDB 移动版) | PouchDB 是浏览器/Node.js 的 CouchDB 兼容客户端,支持本地存储与同步 |
| 同步流程 | 1. 设备离线创建/修改文档 2. 网络恢复后调用 replicate()3. 服务端合并变更,冲突由应用处理 | 应用需监听 docs 事件并处理 doc._conflicts |
| 冲突解决策略 | - 客户端最后写入胜出(LWW) - 手动合并 UI - 自定义 merge 函数 | CouchDB 不自动解决冲突;仅标记存在冲突;应用必须读取并提交最终版本 |
| 增量同步优势 | 仅传输变更部分,节省带宽;支持断点续传 | 即使设备长时间离线,也能完整同步历史 |
| 安全考虑 | 每个设备应使用独立用户账号;通过 _users 和 DB 权限隔离数据 | 避免使用共享 admin 凭据;建议结合 SSL/TLS 加密传输 |
| 性能优化 | - 限制单次同步文档数 - 使用 filtered replication 按用户/区域分片 - 定期 compact 数据库 | 移动设备资源有限;避免一次性同步海量数据 |
第六章:安全与权限管理
6.1 用户数据库(_users)机制
| 名称 | 说明 | 注意事项 |
|---|---|---|
_users 数据库 | CouchDB 内置的特殊数据库,用于存储用户账号信息;文档 _id 格式为 org.couchdb.user:username。 | 普通用户只能读写自己的用户文档;管理员可管理所有用户。 |
| 用户文档结构 | json<br>{<br> "_id": "org.couchdb.user:alice",<br> "name": "alice",<br> "password": "secret",<br> "roles": ["developer"],<br> "type": "user"<br>}<br> | 首次创建时提供明文 password,CouchDB 自动哈希并移除明文字段;type 必须为 “user”。 |
| 创建用户 | 向 _users POST 用户文档 | curl -X POST http://admin:password@127.0.0.1:5984/_users -d '{"name":"bob","password":"123","roles":[],"type":"user"}' -H "Content-Type: application/json" |
| 更新用户密码 | PUT 用户文档并提供当前 _rev 和新 password | curl -X PUT .../_users/org.couchdb.user:bob?rev=1-abc -d '{"name":"bob","password":"newpass","roles":[],"type":"user","_rev":"1-abc"}' |
| 用户认证流程 | 客户端通过 Basic Auth 或 Cookie Auth 提供凭据 → CouchDB 验证 _users 中哈希匹配 | 认证成功后返回 AuthSession cookie(Cookie Auth)或允许请求继续(Basic Auth) |
6.2 角色与权限控制
| 名称 | 说明 | 注意事项 |
|---|---|---|
| 角色(Roles) | 字符串数组,附加于用户文档中(如 ["admin", "editor"]),用于批量授权。 | 角色名可自定义;_admin 是保留角色,拥有全局管理员权限。 |
| 权限层级 | - 服务器级:由 [admins] 配置或 _admin 角色控制- 数据库级:由数据库安全对象(security object)控制 | 普通用户默认无权创建数据库;需管理员授权或启用 require_valid_user = false(不推荐) |
| 权限检查顺序 | 1. 是否为服务器管理员(_admin 或 [admins])→ 允许2. 检查目标数据库的 security 对象 → 匹配用户/角色权限 | 管理员绕过所有数据库级权限限制 |
| 动态角色分配 | 应用可通过更新用户文档的 roles 字段修改权限 | 修改后下次认证生效;已有会话可能仍保留旧权限(取决于会话缓存) |
| 最小权限原则 | 建议为应用用户分配最小必要角色(如仅 reader 或 writer),避免使用 _admin | 过度授权增加安全风险;尤其在多租户环境中 |
6.3 数据库级读写权限设置
| 方法名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|---|---|---|---|
| 查看数据库安全对象 | GET /{db}/_security | 获取当前数据库的权限配置 | curl http://admin:password@127.0.0.1:5984/myapp_db/_security | 返回 {"admins":{"names":[],"roles":[]},"members":{"names":[],"roles":[]}} |
| 设置读写权限 | PUT /{db}/_security + JSON 安全对象 | 控制谁可读(members)和谁可写(admins) | curl -X PUT .../myapp_db/_security -d '{"admins":{"roles":["editor"]},"members":{"names":["alice"]}}' -H "Content-Type: application/json" | admins 可读写;members 仅可读;空列表表示”任何人”(危险!) |
| 权限字段说明 | - members.names:允许读取的用户名列表 - members.roles:允许读取的角色列表 - admins.names/roles:允许读写的用户/角色 | 若 members 为空,则所有认证用户可读;若完全省略,则所有人(含匿名)可读 | 默认新建数据库允许任何人读写(开发模式);生产环境必须显式设置 | |
| 匿名访问控制 | 在 local.ini 中设置 [couch_httpd_auth] require_valid_user = true | 禁止未认证用户访问任何数据库 | — | 需重启生效;覆盖数据库级设置;启用后,即使数据库 security 为空,匿名用户也无法访问 |
| 权限继承 | 安全对象仅作用于当前数据库;不跨库继承 | 每个数据库需独立配置 | _users 和 _replicator 有特殊默认权限,通常无需修改 |
6.4 HTTPS 与认证配置(Basic Auth / Cookie Auth)
| 名称 | 说明 | 注意事项 |
|---|---|---|
| 启用 HTTPS | 在 local.ini 中配置 SSL:ini<br>[ssl]<br>enable = true<br>cert_file = /path/to/server.crt<br>key_file = /path/to/server.key<br> | 证书需 PEM 格式;私钥不可加密(或 CouchDB 无法启动) |
| Basic Auth | HTTP 请求头携带 Authorization: Basic base64(username:password) | 所有 API 支持;简单但每次需传密码;必须配合 HTTPS 使用 |
| Cookie Auth | 1. POST /_session 登录获取 AuthSession cookie2. 后续请求携带该 cookie | 适合 Web 应用;会话有效期默认 10 分钟(可配置) |
| 会话有效期配置 | local.ini 中设置:ini<br>[couch_httpd_auth]<br>timeout = 3600 ; 秒<br> | 超时后需重新登录;值过大会增加会话劫持风险 |
| 强制 HTTPS 重定向 | 配置反向代理(如 Nginx)处理 HTTP→HTTPS 跳转 | CouchDB 本身不支持自动重定向 |
| 安全加固建议 | - 禁用匿名访问 - 使用强密码策略 - 定期轮换管理员密码 - 限制绑定地址( bind_address = 127.0.0.1 + 反向代理) | 避免将 CouchDB 直接暴露公网;始终通过 TLS 加密通信 |
第七章:运维与监控
7.1 日志查看与分析
| 名称 | 语法 / 说明 | 用途 | 代码示例 | 注意事项 |
|---|---|---|---|---|
| 日志文件位置 | 默认路径:/opt/couchdb/var/log/couchdb.log(Linux)macOS (Homebrew): $(brew --prefix)/var/log/couchdb.log | 查看 CouchDB 运行日志 | tail -f /opt/couchdb/var/log/couchdb.log | 需确保运行用户有读权限;日志轮转由系统 logrotate 或 CouchDB 内部管理 |
| 动态调整日志级别 | PUT /_config/log/level | 临时切换日志详细程度(无需重启) | curl -X PUT http://admin:pass@127.0.0.1:5984/_config/log/level -d '"debug"' -H "Content-Type: application/json" | 可选值:“info”(默认)、“debug”、“error”、“none”;生产环境避免长期使用 debug |
| 日志内容结构 | 每行格式:[日期] [模块] [级别] 消息例如: [2026-02-02 13:50:01] [httpd] [error] ... | 快速定位错误来源 | — | 常见模块:httpd(HTTP 请求)、couch_db(数据库操作)、couch_replicator(复制) |
| 启用请求日志 | 在 local.ini 中设置:ini<br>[log]<br>include_sasl = true<br> | 记录 SASL 认证和详细 HTTP 请求 | — | 会显著增加日志量;仅用于调试认证问题 |
| 日志轮转配置 | 使用系统 logrotate 或 CouchDB 内置轮转(CouchDB ≥ 3.0) | 防止日志文件无限增长 | logrotate 配置示例:text<br>/opt/couchdb/var/log/couchdb.log {<br> daily<br> rotate 7<br> compress<br> missingok<br>}<br> | 若使用 systemd,也可通过 journalctl 管理日志 |
7.2 监控活跃任务与复制状态
| 方法名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|---|---|---|---|
| 查看活跃任务 | GET /_active_tasks | 列出当前运行的复制、视图构建、压缩等后台任务 | curl http://admin:password@127.0.0.1:5984/_active_tasks | 返回 JSON 数组,每项含 type, database, progress, pid 等字段 |
| 复制任务详情 | 从 _active_tasks 中筛选 type == "replication" | 监控同步进度与状态 | bash<br>curl .../_active_tasks | jq '.[] | select(.type=="replication")'<br> | progress 字段为百分比(0–100);continuous 字段标识是否为连续复制 |
| 查看集群成员状态 | GET /_membership | 检查集群节点健康状况 | curl http://admin:password@127.0.0.1:5984/_membership | 返回 all_nodes(已知节点)和 cluster_nodes(参与分片的节点);两者应一致 |
| 数据库统计信息 | GET /{db} | 获取文档数、磁盘大小、更新序列等元数据 | curl http://127.0.0.1:5984/myapp_db | 返回 doc_count, disk_size, update_seq;可用于容量规划 |
| 监控 HTTP 状态 | GET / | 检查服务是否就绪 | curl -s http://127.0.0.1:5984/ | grep '"version"' | 返回欢迎信息表示服务正常;结合健康检查脚本使用 |
7.3 数据备份与恢复(命令行)
| 方法名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|---|---|---|---|
| 全库备份(单数据库) | GET /{db}/_all_docs?include_docs=true | 导出所有文档为 JSON | curl "http://admin:pass@127.0.0.1:5984/myapp_db/_all_docs?include_docs=true" > myapp_db_backup.json | 不包含设计文档的 _rev 历史;附件需单独处理 |
| 备份含附件 | 使用 _bulk_get 或逐个获取 _attachments | 完整导出文档及二进制附件 | 需解析 _attachments 并对每个附件调用 GET /db/doc/attach | 附件以 base64 编码存储于 JSON,体积膨胀约 33% |
| 使用 couchup 工具(推荐) | couchup dump {db} > backup.couch | 官方支持的二进制级备份工具(CouchDB ≥ 3.2) | couchup dump myapp_db --output myapp_db.couch | 保留完整修订历史、附件、索引元数据;需安装 couchup |
| 恢复数据库 | 1. 创建空数据库 2. 批量插入文档( _bulk_docs) | 从 JSON 备份还原数据 | bash<br>curl -X PUT .../myapp_db_restored<br>curl -X POST .../myapp_db_restored/_bulk_docs -d @myapp_db_backup.json<br> | 恢复后 _rev 会变化;原冲突历史丢失 |
| 恢复 couchup 备份 | couchup load backup.couch {new_db} | 从二进制备份完整还原 | couchup load myapp_db.couch myapp_db_restored | 最接近原始状态;适用于灾难恢复 |
| 自动化备份脚本 | 结合 cron + curl/couchup | 定期执行备份 | 示例 cron:text<br>0 2 * * * /usr/bin/couchup dump myapp_db -o /backups/myapp_$(date +%F).couch<br> | 备份前建议执行 compaction 减小体积;保留多版本防误删 |
7.4 性能调优建议
| 名称 | 说明 | 注意事项 |
|---|---|---|
| 视图预热 | 首次查询后缓存 B-tree;可启动时预访问关键视图 | 避免用户首次访问慢;可在部署后脚本中触发 |
| 合理使用索引 | - Mango 查询必须有对应索引 - 复合索引字段顺序影响性能 - 避免高基数字段(如 UUID)作索引首字段 | 使用 _find + execution_stats: true 验证索引命中 |
| 数据库压缩(Compaction) | POST /{db}/_compact | 回收被删除文档和旧修订占用的空间 |
| 调整内存与文件句柄 | 在 local.ini 中设置:ini<br>[couchdb]<br>max_dbs_open = 500<br>[mem3]<br>shard_cache_size = 1000<br> | 高并发场景需增大 max_dbs_open;避免”too many open files”错误 |
| 避免大文档与大附件 | 单文档建议 < 1MB;附件建议 < 10MB | 大对象影响复制效率和内存使用;可考虑外部存储(如 S3)+ URL 引用 |
| 监控资源使用 | 使用 top, htop, iostat 观察 CPU、内存、I/O | CouchDB 是 I/O 密集型;SSD 显著提升性能 |
| 网络优化 | - 启用 Gzip 压缩(反向代理层) - 复制使用内网地址 - 避免跨地域高频同步 | CouchDB 本身不支持 Gzip;需 Nginx/Apache 启用 |
第八章:高级特性与集成
8.1 附件(Attachments)管理
| 方法名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|---|---|---|---|
| 上传附件(新文档) | PUT /{db}/{doc_id}/{attachment_name}?rev={rev} + 文件内容 | 将文件作为附件附加到新文档 | bash<br>echo "Hello" > hello.txt<br>curl -X PUT http://admin:pass@127.0.0.1:5984/mydb/doc1/hello.txt --data-binary @hello.txt -H "Content-Type: text/plain"<br> | 若文档不存在,需先创建空文档获取 _rev;否则返回 404 |
| 上传附件(现有文档) | 同上,但需提供当前 _rev | 更新已有文档并添加/替换附件 | bash<br># 先获取 _rev<br>REV=$(curl -s .../mydb/doc1 | jq -r ._rev)<br>curl -X PUT .../mydb/doc1/logo.png?rev=$REV --data-binary @logo.png -H "Content-Type: image/png"<br> | 每次修改附件都会生成新 _rev;旧附件版本仍保留(用于复制) |
| 获取附件 | GET /{db}/{doc_id}/{attachment_name} | 下载附件原始内容 | curl http://127.0.0.1:5984/mydb/doc1/hello.txt | 返回原始字节流;不包含 JSON 包装 |
| 列出文档附件 | GET /{db}/{doc_id} | 查看文档的 _attachments 元数据 | curl .../mydb/doc1 → 返回 "_attachments": {"hello.txt": {"content_type":"text/plain","length":6}} | length 为字节大小;digest 为 SHA1 哈希(用于去重) |
| 批量上传附件(含文档) | PUT /{db}/{doc_id} + JSON 文档内嵌 _attachments(base64 编码) | 一次性创建带附件的文档 | json<br>{<br> "_id": "doc2",<br> "title": "Report",<br> "_attachments": {<br> "data.csv": {<br> "content_type": "text/csv",<br> "data": "IkEiLCJCIgoxLDI="<br> }<br> }<br>}<br> | data 必须是 base64 字符串;适合小文件;大文件建议用二进制 PUT |
| 删除附件 | DELETE /{db}/{doc_id}/{attachment_name}?rev={current_rev} | 移除指定附件 | curl -X DELETE .../mydb/doc1/hello.txt?rev=2-abc | 删除后文档 _rev 更新;附件内容标记为 deleted,但可能仍占磁盘空间直至 compaction |
8.2 变更流(_changes)监听
| 方法名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|---|---|---|---|
| 获取变更列表(普通) | GET /{db}/_changes | 获取数据库自某序列号以来的文档变更 | curl "http://127.0.0.1:5984/mydb/_changes?since=123&limit=10" | 返回 {"results":[...],"last_seq":456};seq 用于增量同步 |
| 长轮询(Longpoll) | GET /{db}/_changes?feed=longpoll&timeout=60000 | 等待新变更到达后返回 | curl ".../_changes?feed=longpoll&since=456" | 连接保持打开,直到有变更或超时;适合低频更新场景 |
| 连续流(Continuous) | GET /{db}/_changes?feed=continuous | 持续输出变更(每行一个 JSON) | curl ".../_changes?feed=continuous&since=456" | 返回 newline-delimited JSON 流;客户端需持续读取;网络中断需重连 |
| 过滤变更 | GET /{db}/_changes?filter=design/filter_name | 仅返回匹配 filter 函数的变更 | 设计文档中定义:"filters": {"by_type": "function(doc, req) { return doc.type === req.query.type; }"}请求: .../_changes?filter=app/by_type&type=user | filter 函数逻辑同复制过滤;可结合 req.query 动态控制 |
| 包含文档内容 | ?include_docs=true | 在变更结果中附带完整文档 | curl ".../_changes?include_docs=true" | 增加响应体积;避免在高频变更流中使用 |
| 应用场景 | - 实时 UI 更新 - CDC(变更数据捕获) - 自定义同步代理 | 构建事件驱动架构 | 需处理重复变更(幂等消费);seq 应持久化以便断点续传 | 变更顺序按写入时间,但不保证全局一致(多节点场景) |
8.3 与外部系统集成(如 Node.js、Python)
| 名称 | 说明 | 注意事项 |
|---|---|---|
| Node.js 集成(nano) | 使用 nano 库(官方推荐):js<br>const nano = require('nano')('http://admin:pass@localhost:5984');<br>const db = nano.db.use('mydb');<br>await db.insert({name: 'Alice'}, 'user1');<br> | 支持 Promise/async;自动处理 _rev;内置 attachment、replication API |
| Python 集成(cloudant / requests) | 使用 requests 直接调用 REST API:python<br>import requests<br>resp = requests.put(<br> 'http://localhost:5984/mydb/doc1',<br> json={'name': 'Bob'},<br> auth=('admin', 'pass')<br>)<br> | 轻量级;无需专用 SDK;适合脚本或简单应用 |
| 认证方式 | - Basic Auth(简单) - Cookie Auth(会话) - API Key(通过 _users 模拟) | 外部系统通常使用 Basic Auth 或预共享凭证 |
| 错误处理 | HTTP 状态码: - 409:冲突(需处理 _rev)- 401/403:认证/权限失败 - 500:服务器内部错误 | 必须检查响应状态;重试策略对 409/500 有效 |
| 批量与流式处理 | - _bulk_docs 提升写入吞吐- _changes?feed=continuous 实现流式消费 | 适用于 ETL、日志收集等场景 |
8.4 使用 Fauxton Web 管理界面
| 名称 | 说明 | 注意事项 |
|---|---|---|
| 访问地址 | http://127.0.0.1:5984/_utils | 内置 Web UI,无需额外安装 |
| 核心功能 | - 数据库创建/删除 - 文档浏览与编辑 - 视图设计(MapReduce) - Mango 查询构建器 - 复制任务配置 - 用户与权限管理 | 图形化替代命令行;适合开发调试 |
| 视图调试 | 在 “Design Documents” 中编写 map/reduce 函数并实时测试 | 自动高亮语法错误;支持预览结果 |
| Mango 查询构建器 | 可视化拖拽字段生成 _find 查询 | 自动生成 JSON 查询体;支持分页、排序 |
| 安全提示 | Fauxton 具备完整数据库操作权限 | 默认绑定 127.0.0.1;若改为 0.0.0.0,务必配合 HTTPS 和强密码 |