账户收割者¶
账户收割者在后台删除已删除账户的数据。
账户通过经销商向账户的存储 URL 发出 DELETE 请求来标记为删除。这只是将 DELETED 值放入账户数据库(及其副本)的 account_stat 表中的 status 列,表明该账户的数据应稍后删除。
通常没有固定的保留时间,也没有撤销删除的功能;假设经销商将实现这些功能,并且仅在真正希望删除账户数据时才调用 DELETE。但是,为了保护 Swift 集群免受不当或错误的删除请求的影响,您可以设置 account-server.conf 的 [account-reaper] 部分中的 delay_reaping 值,以延迟实际删除数据。目前,没有用于撤销删除账户的工具;必须直接更新账户数据库副本,将 status 列设置为空字符串,并将 put_timestamp 更新为大于 delete_timestamp。 (TODO 列表中包含编写一个工具来执行此任务,最好是通过 REST 调用。)
账户收割者在每个账户服务器上运行,并偶尔扫描服务器以查找标记为删除的账户数据库。它只会对服务器是主节点 的账户触发,这样多个账户服务器就不会同时尝试执行相同的工作。使用多个服务器删除一个账户可能会提高删除速度,但需要协调,以避免重复工作。速度并不是数据删除的主要问题,而且大型账户也不是经常被删除的。
账户本身的删除过程非常简单。对于账户中的每个容器,都会删除每个对象,然后删除容器。任何失败的删除请求都不会停止整个过程,但最终会导致整个过程失败(例如,如果对象删除超时,则以后无法删除容器,因此也无法删除账户)。整个过程即使在发生故障时也会继续,这样就不会因为一个棘手的问题而导致无法回收集群空间。账户收割者会一直尝试删除一个账户,直到它最终变为空,此时 db_replicator 内部的数据库回收过程最终会删除数据库文件。
有时,持久的错误状态可能会阻止某些对象或容器被删除。如果发生这种情况,您将在日志中看到类似“账户 <name> 自 <date> 以来尚未被收割”的消息。您可以使用 account-server.conf 文件中 [account-reaper] 部分的 reap_warn_after 值来控制何时记录此消息。默认值为 30 天。
历史¶
最初,考虑了一种完全通过外部调用删除账户的简单方法,因为它不需要对系统进行任何更改。所有数据都将以与实际用户相同的方式删除,通过公共 REST API。但是,缺点是它会使用代理资源并记录所有内容,而实际上并不需要这样做。此外,它可能需要一台或两台专用的服务器,仅用于发出删除请求。
还考虑了一种完全自下而上的方法,其中对象和容器服务器会偶尔扫描它们持有的数据,并检查账户是否已删除,如果是,则删除数据。优点是回收速度快,对代理或日志没有影响,但缺点是几乎 100% 的扫描都不会产生任何操作,从而造成大量的 I/O 负载而没有任何理由。
还考虑了一种更以容器服务器为中心的方法,其中账户服务器将所有容器标记为删除,然后容器服务器删除每个容器中的对象,然后删除自身。这具有仍然可以快速回收大量容器账户的好处,但缺点是负载峰值很大。可以减慢该过程以减轻负载峰值的可能性,但随后就失去了快速回收的好处,剩下的只是一个更复杂的过程。此外,扫描所有容器以查找那些标记为删除的容器,而大多数容器不会被标记,似乎是一种浪费。db_replicator 可以在执行其复制扫描时执行此工作,但它必须生成和跟踪删除过程,这似乎过于复杂。
最终,如上所述,以账户服务器为中心的方法似乎是最好的。