5.1. 压缩

“压缩”操作是一种通过从数据库或视图索引文件中删除未使用的和旧数据来减少磁盘空间使用量的方法。此操作与其他数据库管理系统提供的“真空”(例如 SQLite)操作非常相似。

在压缩过程中,CouchDB 会使用 .compact 扩展名在新的文件中重新创建数据库或视图。由于这大约需要两倍的磁盘存储空间,因此 CouchDB 会在继续之前先检查是否有可用的磁盘空间。

当所有实际数据成功传输到新压缩的文件后,CouchDB 会透明地将压缩文件交换到服务中,并删除旧的数据库或视图文件。

从 CouchDB 2.1.1 开始,默认情况下启用自动压缩,并在下一节中进行了描述。如果需要,仍然可以触发手动压缩。这将在后续部分中进行描述。

5.1.1. 自动压缩

CouchDB 的自动压缩守护进程(在内部称为“smoosh”)将根据文件稀疏性和可恢复的总空间量的可配置阈值,触发数据库和视图的压缩作业。

5.1.1.1. 通道

Smoosh 使用通道的概念工作。通道本质上是待处理压缩的队列。数据库和视图有独立的活动通道集。每个通道都分配了一个配置,该配置定义了压缩是否最终进入通道的队列以及如何在该队列中对压缩进行优先级排序。

Smoosh 获取每个通道,并按优先级顺序处理每个通道中排队的压缩。每个通道都是并发处理的,因此优先级级别只在给定通道内起作用。每个通道都分配了指定数量的活动压缩,这定义了该通道并行进行多少次压缩。例如,一个具有大量数据库 churn 但很少有视图的集群可能需要在数据库通道中进行更多活动压缩。

重要的是要记住,通道是 CouchDB 节点的本地通道;也就是说,每个节点都维护和处理一组独立的压缩。通道定义为“比率”通道或“松弛”通道,具体取决于用于优先级排序的算法类型。

  • 比率:使用 sizes.file / sizes.active 的比率作为其驱动计算。结果 X 必须大于某个可配置值 Y,压缩才能添加到队列中。然后,对于 X 的更高值,对压缩进行优先级排序。

  • 松弛:使用 sizes.file - sizes.active 的差值作为其驱动计算。结果 X 必须大于某个可配置值 Y,压缩才能添加到队列中。对于 X 的更高值,对压缩进行优先级排序。

在这两种情况下,Y 都使用 min_priority 配置变量设置。CouchDB 附带四个预配置的通道:每个类型一个通道用于数据库,另一个通道用于视图。

5.1.1.2. 通道配置

通道使用 [smoosh.<channel_name>] 配置块定义,并通过在 [smoosh] 块中的 db_channelsview_channels 配置设置中命名通道来激活。默认配置为

[smoosh]
db_channels = upgrade_dbs,ratio_dbs,slack_dbs
view_channels = upgrade_views,ratio_views,slack_views
cleanup_channels = index_cleanup

[smoosh.ratio_dbs]
priority = ratio
min_priority = 2.0

[smoosh.ratio_views]
priority = ratio
min_priority = 2.0

[smoosh.slack_dbs]
priority = slack
min_priority = 536870912

[smoosh.slack_views]
priority = slack
min_priority = 536870912

“升级”和“清理通道”是特殊的系统通道。“升级”通道检查文件的 disk_format_version 是否与当前版本匹配,如果与当前版本不匹配,则将文件排队以进行压缩(这会产生升级文件格式的副作用)。除此之外,upgrade_views 会在升级整理(libicu)库后将视图排队以进行压缩。“index_cleanup”通道用于安排用于删除陈旧索引文件和在更新设计文档后清除 _local 检查点文档的作业。

以下是可以为每个通道配置的几个其他属性;这些属性在 配置 API 中有记录。

5.1.1.3. 调度窗口

每个压缩通道都可以配置为仅在一天中的特定时间运行。特定于通道的 fromtostrict_window 配置设置控制此行为。例如

[smoosh.overnight_channel]
from = 20:00
to = 06:00
strict_window = true

其中 overnight_channel 是要配置的通道的名称。

注意:CouchDB 通过 UTC(GMT)时区确定时间,因此这些设置必须用 UTC(GMT)表示。

如果 strict_window 设置为其默认值 false,则允许活动压缩完成,但不会启动新的压缩。

注意

创建通道时,会启动一个 60 秒的计时器,以检查通道是否应根据配置中定义的时间窗口处理任何压缩。

通道被设置为挂起,60 秒后,它会检查它是否应该运行,如果未运行,则将其设置为暂停。在检查结束时,会启动另一个 60 秒的计时器以安排另一个检查。

最终,在时间窗口内,它开始处理压缩。但由于它会每 60 秒继续运行一次检查,因此在退出时间窗口时,正在运行的压缩进程将被暂停,并在重新进入时间窗口时恢复。

这意味着在退出时间窗口后的前 60 秒,或者在创建通道并且您不在时间窗口内时,压缩会运行长达 60 秒。这与旧压缩守护进程的行为不同,旧压缩守护进程会直接取消压缩。

5.1.1.4. 迁移指南

以前的 CouchDB 版本附带了一个更简单的压缩守护进程。新守护进程的配置系统与旧系统不兼容,因此使用自定义压缩配置的用户需要将它们移植到新设置。旧守护进程的压缩规则配置如下所示

[compaction_daemon]
min_file_size = 131072
check_interval = 3600
snooze_period_ms = 3000

[compactions]
mydb = [{db_fragmentation, "70%"}, {view_fragmentation, "60%"}, {parallel_view_compaction, true}]
_default = [{db_fragmentation, "50%"}, {view_fragmentation, "55%"}, {from, "20:00"}, {to, "06:00"}, {strict_window, true}]

此配置的许多元素可以移植到新系统。详细检查每个元素

  • min_file_size 现在使用 min_size 配置设置在每个通道的基础上进行配置。

  • db_fragmentation 等效于配置一个优先级 = 比率通道,其 min_priority 设置为 1.0 / (1 - db_fragmentation/100),然后在 [smoosh] db_channels 配置设置中列出该通道。

  • view_fragmention 同样等效于配置一个优先级 = 比率通道,其 min_priority 设置为 1.0 / (1 - view_fragmentation/100),然后在 [smoosh] view_channels 配置设置中列出该通道。

  • from / to / strict_window:这些设置中的每一个都可以在新守护进程中按每个通道的基础上应用。唯一的行为变化是,新守护进程将在退出允许的窗口时暂停压缩,而不是直接取消压缩,并在重新进入时恢复压缩。

  • parallel_view_compaction:每个压缩通道都有一个并发设置,控制在该通道中并行执行多少次压缩。总并行度是所有活动通道的并发设置的总和。这与以前的行为不同,在以前的行为中,守护进程一次只关注一个数据库及其视图(取决于此标志的值)。

check_intervalsnooze_period_ms 设置在新守护进程的事件驱动设计中已过时。新守护进程不支持设置数据库特定的阈值,如上面的 mydb 设置。相反,可以配置通道以关注特定类别的文件:大型数据库、小型视图索引等。大多数命名数据库压缩规则的情况可以使用这些数据库及其关联视图的属性来表达。

5.1.2. 手动数据库压缩

数据库压缩通过删除更新期间创建的未使用的文件部分来压缩数据库文件。旧的文档修订版将被少量称为 tombstone 的元数据替换,这些元数据用于复制期间的冲突解决。存储的修订版数量(及其 tombstones)可以通过使用 _revs_limit URL 端点进行配置。

压缩可以手动触发,针对每个数据库运行,并作为后台任务执行。要为特定数据库启动压缩,需要发送 HTTP POST /{db}/_compact 到目标数据库的子资源。

curl -H "Content-Type: application/json" -X POST http://localhost:5984/my_db/_compact

成功后,HTTP 状态 202 Accepted 会立即返回。

HTTP/1.1 202 Accepted
Cache-Control: must-revalidate
Content-Length: 12
Content-Type: text/plain; charset=utf-8
Date: Wed, 19 Jun 2013 09:43:52 GMT
Server: CouchDB (Erlang/OTP)
{"ok":true}

虽然请求体没有被使用,但您仍然需要指定 Content-Type 头部,值为 application/json。如果您没有指定,您将收到 HTTP 状态 415 Unsupported Media Type 的响应。

HTTP/1.1 415 Unsupported Media Type
Cache-Control: must-revalidate
Content-Length: 78
Content-Type: application/json
Date: Wed, 19 Jun 2013 09:43:44 GMT
Server: CouchDB (Erlang/OTP)

{"error":"bad_content_type","reason":"Content-Type must be application/json"}

当压缩成功启动并运行时,您可以通过 数据库信息资源 获取有关它的信息。

curl http://localhost:5984/my_db
HTTP/1.1 200 OK
Cache-Control: must-revalidate
Content-Length: 246
Content-Type: application/json
Date: Wed, 19 Jun 2013 16:51:20 GMT
Server: CouchDB (Erlang/OTP)

{
    "committed_update_seq": 76215,
    "compact_running": true,
    "db_name": "my_db",
    "disk_format_version": 6,
    "doc_count": 5091,
    "doc_del_count": 0,
    "instance_start_time": "0",
    "purge_seq": 0,
    "sizes": {
      "active": 3787996,
      "disk": 17703025,
      "external": 4763321
    },
    "update_seq": 76215
}

请注意,compact_running 字段为 true,表示压缩正在运行。要跟踪压缩进度,您可以查询 _active_tasks 资源。

curl http://localhost:5984/_active_tasks
HTTP/1.1 200 OK
Cache-Control: must-revalidate
Content-Length: 175
Content-Type: application/json
Date: Wed, 19 Jun 2013 16:27:23 GMT
Server: CouchDB (Erlang/OTP)

[
    {
        "changes_done": 44461,
        "database": "my_db",
        "pid": "<0.218.0>",
        "progress": 58,
        "started_on": 1371659228,
        "total_changes": 76215,
        "type": "database_compaction",
        "updated_on": 1371659241
    }
]

5.1.3. 手动视图压缩

视图也需要压缩。与数据库不同,视图按 设计文档 分组进行压缩。要启动它们的压缩,请发送 HTTP POST /{db}/_compact/{ddoc} 请求。

curl -H "Content-Type: application/json" -X POST http://localhost:5984/dbname/_compact/designname
{"ok":true}

这将压缩指定设计文档当前版本的视图索引。HTTP 响应代码为 202 Accepted(与 数据库压缩 相同),并将创建一个压缩后台任务。

5.1.3.1. 视图清理

磁盘上的视图索引以其视图定义的 MD5 哈希命名。当您更改视图时,旧索引会保留在磁盘上。要清理所有过时的视图索引(以视图的 MD5 表示命名的文件,这些文件不再存在),您可以触发 视图清理

curl -H "Content-Type: application/json" -X POST http://localhost:5984/dbname/_view_cleanup
{"ok":true}