集群管理
理論
在etc/fefault.ini
文件中有以下部分:
[cluster]
q=8
n=3
- q - 分片的數量
- n - 每一份文檔的拷貝數量(加上原文檔一共幾份副本)
創建數據庫時可以通過覆蓋該值修改為自己的值。
在集群操作中,獲取操作中CouchDB返回狀態碼200或者是寫操作返回狀態碼201即為大多數成員達成一致。大多數成員定義為相關拷貝的數量的一半。對於“讀寫”操作,“相關副本”的定義稍有不同。
對於讀操作,相關副本的數量是保存請求數據的當前可訪問分片的數量,這意味着在發生故障或網絡分區的情況下,相關副本的數量可能少於集群中的副本數量。 可以使用r參數設置讀取份數。
對於寫操作,相關副本的數量始終為n,即集群中的副本數量。 對於寫操作,可以使用w參數設置份數。 如果少於此數量的可用節點,則返回202。
節點管理
查看所有節點
curl -u admin:adminpw -X GET http://localhost:5984/_membership
{
"all_nodes":[ # 當前節點所知道的節點
"node1@xxx.xxx.xxx.xxx"],
"cluster_nodes":[ #當前節點所連接的節點
"node1@xxx.xxx.xxx.xxx"],
}
添加一個節點
curl -u admin:adminpw -X PUT http://localhost:5986/_nodes/node2@yyy.yyy.yyy.yyy -d {}
刪除一個節點
#首先獲取關於文檔的revision
curl -u admin:adminpw -X GET "http://xxx.xxx.xxx.xxx:5986/_nodes/node2@yyy.yyy.yyy.yyy"
{"_id":"node2@yyy.yyy.yyy.yyy","_rev":"1-967a00dff5e02add41820138abb3284d"}
#刪除節點
curl -u admin:adminpw -X DELETE http://localhost:5986/_nodes/node2@yyy.yyy.yyy.yyy?rev=1-967a00dff5e02add41820138abb3284d
數據庫管理
創建數據庫
數據庫名字不支持大寫字符,只支持[a-z],[0-9],以及特殊字符:_ $ ( ) + - /
#創建一個數據庫名字為db_name
curl -u admin:adminpw -X PUT http://localhost:5984/db_name?q=4&n=2
刪除數據庫
curl -u admin:adminpw -X DELETE http://localhost:5984/db_name
在一個具體的節點放置數據庫
在CouchDB 2.0群集功能的前身BigCouch中,存在區域的概念。 CouchDB 2.0通過集群放置規則來實現這一目標。
使用placement
參數將覆蓋分片副本基數的標准邏輯(由[cluster] n
指定)。
首先,每個節點必須標記有zone屬性。 這定義了每個節點所在的區域。您可以通過編輯/nodes
數據庫中的節點文檔來實現,該文檔可通過“后門”(5986)端口進行訪問。 添加以下形式的鍵值對:
"zone":"metro-dc-a"
在集群上所有節點上操作。
在每一個節點的配置文件local.ini
或者default.ini
中,定義相同的集群設置:
[cluster]
placement = metro-dc-a:2,metro-dc-b:1
在此示例中,它將確保將一個分區的兩個副本托管在將zone
屬性設置為metro-dc-a
的節點上,並將一個副本副本托管在一個將zone
屬性設置為metro-dc-b
的新副本上。
請注意,您還可以使用該系統,通過為群集中的某些節點提供不出現在[cluster]放置字符串中的zone屬性,來確保它們不承載新創建的數據庫的任何副本。
分片管理
介紹
本文檔討論了分片在CouchDB中的工作方式,以及如何安全地添加,移動,刪除和創建分片和分片副本的放置規則。
分片是數據庫中數據的水平分區。將數據划分為多個碎片,並將每個碎片的副本(稱為“碎片副本”或簡稱為“副本”)分布到群集中的不同節點,可以提高數據的持久性,防止節點丟失。CouchDB群集自動分片數據庫,並在節點之間分配組成每個分片的文檔子集。 修改群集成員身份和分片行為必須手動完成。
分片和復制
可以在全局級別或每個數據庫的基礎上設置每個數據庫有多少個分片和副本。 相關參數是q
和n
。
q
是要維護的數據庫分片數。n
是要分發的每個文檔的副本數。n
的默認值為3,q
的默認值為8。當q
= 8時,數據庫分為8個分片。在n
=3的情況下,群集分發每個分片的三個副本。總共,一個數據庫有24個分片副本。在默認的3節點群集中,每個節點將接收8個分片。在4節點群集中,每個節點將接收6個分片。 在一般情況下,我們建議群集中的節點數應為n的倍數,以使碎片均勻分布。
CouchDB節點的etc/local.ini
文件中的cluster
部分:
[cluster]
q=8
n=3
可以修改這些設置以設置所有數據庫的分片默認值,或者可以在創建數據庫時通過指定q和n查詢參數來針對每個數據庫進行設置。 例如:
curl -X PUT "http://localhost:5984/database-name?q=4&n=2"
這將創建一個數據庫,該數據庫分為4個分片和2個副本,從而產生8個分片副本分布在整個數據庫中
的集群上。
Quorum
取決於集群的大小,每個數據庫的分片數量以及分片副本的數量,並非每個節點都可以訪問每個分片,但是每個節點都知道可以通過CouchDB的內部分片在哪里找到每個分片的所有副本。
進入CouchDB集群的每個請求均由任意一個隨機協調節點處理。該協調節點將請求代理給其他具有相關數據的節點,這些數據可能包含也可能不包含自身。一旦達到法定數量的數據庫節點響應,協調節點就會向客戶端發送響應。2 默認情況下,默認的法定仲裁大小等於r=w=((n+1)/2)
,其中r
表示讀取仲裁的大小,w
表示寫入仲裁的大小,n
表示數字每個分片的副本。在n為3的默認群集中,((n+1)/2)
將為2。
集群中的每個節點都可以作為任何請求的協調節點。集群內部沒有專門的節點角色。
可以在請求時通過設置文檔和視圖讀取的r
參數以及文檔寫入的w
參數來配置所需仲裁的大小。例如,這是一個請求,一旦至少兩個節點已響應,該請求便指示協調節點發送響應:
curl "$COUCH_URL:5984/<db>/<doc>?r=2"
這是寫文檔的類似示例:
curl -X PUT "$COUCH_URL:5984/<db>/<doc>?w=2" -d '{...}'
將r
或w
設置為等於n(副本數)意味着只有在所有具有相關分片的節點都響應或超時后,您才會收到響應,因此這種方法不能保證ACID
的一致性。 將r
或w
設置為1意味着僅一個相關節點響應后,您將收到響應。
數據庫分片測試
有一些API端點可以幫助您了解如何分片數據庫。 首先,在集群上創建一個新數據庫,然后將幾個文檔放入其中:
$ curl -X PUT $COUCH_URL:5984/mydb
{"ok":true}
$ curl -X PUT $COUCH_URL:5984/mydb/joan -d '{"loves":"cats"}'
{"ok":true,"id":"joan","rev":"1-cc240d66a894a7ee7ad3160e69f9051f"}
$ curl -X PUT $COUCH_URL:5984/mydb/robert -d '{"loves":"dogs"}'
{"ok":true,"id":"robert","rev":"1-4032b428c7574a85bc04f1f271be446e"}
首先,/db
將告訴您數據庫的分片參數:
curl -s $COUCH_URL:5984/db | jq .
{
"db_name": "mydb",
...
"cluster": {
"q": 8,
"n": 3,
"w": 2,
"r": 2
}, ...
}
因此,我們知道此數據庫是由8個分片(q
=8)建的,每個分片具有3個副本(n
=3),集群中節點之間總共有24個分片副本。
現在,讓我們看一下這些分片副本如何通過/db/_shards
端點放置在集群上:
curl -s $COUCH_URL:5984/mydb/_shards | jq .
{
"shards": {
"00000000-1fffffff": [
"node1@127.0.0.1",
"node2@127.0.0.1",
"node4@127.0.0.1"
],
"20000000-3fffffff": [
"node1@127.0.0.1",
"node2@127.0.0.1",
"node3@127.0.0.1"
],
...
}
}
現在我們看到該集群中實際上有4個節點,並且CouchDB已將這24個分片副本均勻地分布在所有4個節點上。
我們還可以確切地看到哪個分片包含具有/db/_shards/doc
端點的給定文檔:
curl -s $COUCH_URL:5984/mydb/_shards/joan | jq .
{
"range": "e0000000-ffffffff",
"nodes": [
"node1@127.0.0.1",
"node3@127.0.0.1",
"node4@127.0.0.1"
] }
$ curl -s $COUCH_URL:5984/mydb/_shards/robert | jq .
{
"range": "60000000-7fffffff",
"nodes": [
"node1@127.0.0.1",
"node3@127.0.0.1",
"node4@127.0.0.1"
]
}
CouchDB向我們展示了兩個示例文檔中每個映射到的特定分片。
移動一個分片
本節介紹如何手動放置和更換碎片。 當您確定群集太大或太小,並且想要成功調整其大小,或者從服務器指標中注意到數據庫/碎片布局不是最佳的,並且您需要一些“熱點”時,這些活動是至關重要的步驟 解決。
考慮一個q
=8和n
=3的三節點群集。每個數據庫有24個分片,分布在三個節點上。如果將第四個節點添加到集群,則CouchDB不會將現有數據庫分片重新分配給該集群。 這將導致負載不平衡,因為新節點將僅托管其加入集群后創建的數據庫的分片。 為了平衡現有數據庫中的分片分布,必須手動移動它們。
在集群中的節點上移動分片涉及以下幾個步驟:
- 確保目標節點已經加入集群
- 將分片和任何輔助索引分片復制到目標節點上。
- 設置目標節點為維護模式。
- 更新集群元數據反映新的目標分片。
- 監視內部復制以確保最新的分片。
- 清除目標節點的維護模式。
- 再次更新集群元數據移除原分片。
- 移除原節點的分片和任何輔助索引分片.
拷貝分片文件
從技術上講,復制數據庫和輔助索引碎片是可選的。 如果在不執行此數據副本的情況下繼續進行下一步,則CouchDB將使用內部復制來填充新添加的分片副本。 但是,復制文件的速度比內部復制快,尤其是在繁忙的群集上,這就是為什么我們建議首先執行此手動數據復制的原因。
碎片文件位於CouchDB安裝目錄的data/shards
目錄中。這些子目錄中包含分片文件本身。例如,對於一個名為abc
的q
=8數據庫,這是其數據庫分片文件:
data/shards/00000000-1fffffff/abc.1529362187.couch
data/shards/20000000-3fffffff/abc.1529362187.couch
data/shards/40000000-5fffffff/abc.1529362187.couch
...
輔助索引(包括JavaScript
視圖,Erlang
視圖和Mango
索引)也被分片,並且應移動它們的分片以節省新節點重建視圖的工作量。查看data/.
中的分片。例如:
data/.shards
data/.shards/e0000000-ffffffff/_replicator.1518451591_design
data/.shards/e0000000-ffffffff/_replicator.1518451591_design/mrview
data/.shards/e0000000-ffffffff/_replicator.1518451591_design/mrview/3e823c2a4383ac0c18d4e574135a5b08.view
...
由於它們是文件,因此可以使用cp
,rsync
,scp
或其他文件復制命令將它們從一個節點復制到另一個節點。 例如:
# 1主機
$ mkdir -p data/.shards/<range>
$ mkdir -p data/shards/<range>
# 2主機
$ scp <couch-dir>/data/.shards/<range>/<database>.<datecode>* \
<node>:<couch-dir>/data/.shards/<range>/
$ scp <couch-dir>/data/shards/<range>/<database>.<datecode>.couch \
<node>:<couch-dir>/data/shards/<range>/
先移動視圖文件再移動數據庫文件! 如果視圖索引在其數據庫之前,則數據庫將從頭開始重建它。
設置目標節點為維護模式
在告訴CouchDB節點上的這些新分片之前,必須將節點置於維護模式。維護模式指示CouchDB返回404 Not Found
響應在/_up
端點,並確保其不參與其分片的常規交互式集群請求。使用GET/_up
檢查節點的運行狀況的正確配置的負載均衡器將檢測到此404並將該節點從循環中刪除,從而阻止將請求發送到該節點。 例如,要將HAProxy配置為使用/_up
端點,請使用:
http-check disable-on-404
option httpchk GET /_up
如果未設置維護模式,或者負載平衡器忽略了此維護模式狀態,則在執行下一步之后,群集在咨詢相關節點時可能會返回錯誤的響應。不要這樣做!在接下來的步驟中,我們將確保此分片是最新的,然后再允許其參與最終用戶的請求。
啟用維護模式:
curl -X PUT -H "Content-type: application/json" \ $COUCH_URL:5984/_node/<nodename>/_config/couchdb/maintenance_mode \ -d "\"true\""
然后,通過在該節點的單個端點上執行GET/_up
來驗證該節點是否處於維護模式:
curl -v $COUCH_URL/_up
...
< HTTP/1.1 404 Object Not Found
...
{"status":"maintenance_mode"}
最后,檢查負載均衡器是否已從可用后端節點池中刪除了該節點。
更新集群元數據反映新的目標分片。
現在我們需要告訴CouchDB,目標節點(必須已經加入集群)應該為給定數據庫托管碎片副本。
要更新群集元數據,請使用特殊的/_dbs
數據庫,該數據庫是內部CouchDB數據庫,它將數據庫映射到分片和節點。該數據庫在節點之間復制。它只能通過節點本地端口(通常是端口5986)進行訪問。默認情況下,出於安全目的,此端口僅在localhost接口上可用。
首先,檢索數據庫的當前元數據:
curl http://localhost:5986/_dbs/{name}
{
"_id": "{name}",
"_rev": "1-e13fb7e79af3b3107ed62925058bfa3a",
"shard_suffix": [46, 49, 53, 51, 48, 50, 51, 50, 53, 50, 54],
"changelog": [
["add", "00000000-1fffffff", "node1@xxx.xxx.xxx.xxx"],
["add", "00000000-1fffffff", "node2@xxx.xxx.xxx.xxx"],
["add", "00000000-1fffffff", "node3@xxx.xxx.xxx.xxx"],
...
],
"by_node": {
"node1@xxx.xxx.xxx.xxx": [
"00000000-1fffffff",
...
],
...
},
"by_range": {
"00000000-1fffffff": [
"node1@xxx.xxx.xxx.xxx",
"node2@xxx.xxx.xxx.xxx",
"node3@xxx.xxx.xxx.xxx"
],
...
}
}
這是該文檔的簡要剖析:
_id
:數據庫的名字_rev
:元數據的當前版本shard_suffix
:數據庫創建時的時間戳,在Unix時期映射到ASCII數字的代碼點后的秒。changelog
:數據庫分片的歷史by_node
:每個節點的分片列表by_range
:每個分片由哪些節點持有。
要反映元數據中的分片移動,請執行以下三個步驟:
- 添加合適的
changelog
實體。 - 更新
by_node
實體。 - 更新
by_range
實體。
在修改時,此過程必須手動完成。
要將分片添加到節點,請將以下條目添加到數據庫元數據的changelog
屬性中:
["add", "<range>", "<node-name>"]
<range>
是特定的硬范圍設置。<node-name>
應該與集群中GET/_membership
中顯示的節點的名稱和地址匹配。
如果從節點移除一個分片,簡單地將add
替換為remove
。
找到新的變更日志條目后,將需要更新by_node
和by_range
以反映誰在存儲哪些分片。 更改日志條目中的數據和這些屬性必須匹配。 否則,數據庫可能會損壞。
繼續我們的示例,這是上面的元數據的更新版本,該版本將分片添加到名為node4的其他節點中:
{
"_id": "{name}",
"_rev": "1-e13fb7e79af3b3107ed62925058bfa3a",
"shard_suffix": [46, 49, 53, 51, 48, 50, 51, 50, 53, 50, 54],
"changelog": [
["add", "00000000-1fffffff", "node1@xxx.xxx.xxx.xxx"],
["add", "00000000-1fffffff", "node2@xxx.xxx.xxx.xxx"],
["add", "00000000-1fffffff", "node3@xxx.xxx.xxx.xxx"],
...
["add", "00000000-1fffffff", "node4@xxx.xxx.xxx.xxx"]
],
"by_node": {
"node1@xxx.xxx.xxx.xxx": [
"00000000-1fffffff",
...
],
...
"node4@xxx.xxx.xxx.xxx": [
"00000000-1fffffff"
]
},
"by_range": {
"00000000-1fffffff": [
"node1@xxx.xxx.xxx.xxx",
"node2@xxx.xxx.xxx.xxx",
"node3@xxx.xxx.xxx.xxx",
"node4@xxx.xxx.xxx.xxx"
],
...
}
}
現在可以PUT
新元數據:
curl -X PUT http://localhost:5986/_dbs/{name} -d '{...}'
強制同步分片
無論您是否將分片預先復制到新節點,都可以強制CouchDB同步所有分片的所有副本。
具有/db/_sync_shards
端點的數據庫中的分片:
curl -X POST $COUCH_URL:5984/{dbname}/_sync_shards
{"ok":true}
這將啟動同步過程。 請注意,這將給群集增加額外的負載,這可能會影響性能。
通過寫入存儲在該分片中的文檔,也可以在每個分片的基礎上強制進行同步。
監視內部復制以確保最新的分片
完成上一步后,CouchDB將開始同步分片。可以通過監視/_node/<nodename>/_system
端點(包括internal_replication_jobs
指標)來觀察這種情況。
一旦此指標從開始分片同步之前返回到基線,或者為0,分片副本就可以提供數據了,我們可以使節點退出維護模式。
清除目標節點的維護模式
現在,可以像在步驟2中一樣,通過在維護模式配置端點上放置false
,使節點開始為數據請求提供服務。
通過在該節點的單個端點上執行GET/_up
來驗證該節點是否不在維護模式下。最后,檢查負載均衡器是否已將該節點返回到可用后端節點池中。
再次更新集群元數據移除原分片
現在,以與在步驟2中將新目標分片添加到分片圖中相同的方式,從分片圖中刪除源分片。確保將[“ remove”,<range>,<source-shard>]
條目添加到 更改日志的末尾,以及修改數據庫元數據文檔的by_node
和by_range
部分。
移除原節點的分片和任何輔助索引分片
最后,可以通過從源主機上的命令行中刪除源碎片副本的文件以及任何視圖碎片副本來刪除源碎片副本:
rm <couch-dir>/data/shards/<range>/<dbname>.<datecode>.couch
rm -r <couch-dir>/data/.shards/<range>/<dbname>.<datecode>*
恭喜你! 您已經移動了數據庫分片副本。通過以這種方式添加和刪除數據庫分片副本,您可以更改集群的分片布局,也稱為分片映射。
指定數據庫放置位置
您可以配置CouchDB,以使用放置規則在數據庫創建時將碎片副本放置在某些節點上。
首先,每個節點必須標記有zone屬性。 這定義了每個節點所在的區域。您可以通過編輯/_nodes
數據庫中的節點文檔來實現,該文檔可通過本地節點端口進行訪問。 添加以下形式的鍵值對:
"zone": "{zone-name}"
在集群中的每一個節點都這樣做:
curl -X PUT http://localhost:5986/_nodes/<node-name> \ -d '{ \
"_id": "<node-name>",
"_rev": "<rev>",
"zone": "<zone-name>"
}'
在每個節點的本地配置文件(local.ini)中,定義一個一致的群集范圍設置,例如:
[cluster]
placement = <zone-name-1>:2,<zone-name-2>:1
在此示例中,CouchDB將確保將分區的兩個副本托管在區域屬性設置為<zone-name-1>
的節點上,並將一個副本托管在新的區域屬性設置為<zone-name-2>
的節點上。
這種方法非常靈活,因為您還可以在創建數據庫時使用與ini文件相同的語法,通過將放置設置指定為查詢參數來基於每個數據庫指定區域:
curl -X PUT $COUCH_URL:5984/<dbname>?zone=<zone>
也可以指定放置參數。 請注意,這將覆蓋確定已創建副本的數量!
請注意,您還可以使用此系統來確保群集中的某些節點不為新主機托管任何副本。
通過為它們提供一個不會出現在[cluster]
放置字符串中的zone
屬性,來創建數據庫。
修改數據庫到一個新的q
值
數據庫的q值只能在創建數據庫時設置,不能進行實時重新分片。 相反,要重新分片數據庫,必須重新生成它。 步驟如下:
- 通過在PUT操作期間將
q
值指定為查詢參數來創建具有所需分片設置的臨時數據庫。 - 停止客戶端訪問數據庫
- 將主數據庫復制到臨時數據庫。 如果主數據庫正在使用中,則可能需要多次復制。
- 刪除主數據庫,確保沒有人在使用!
- 使用所需的分片設置重新創建主數據庫。
- 客戶端現在可以再次訪問數據庫。
- 將臨時數據庫復制回主數據庫。
- 刪除臨時數據庫.
一旦完成所有步驟,即可再次使用該數據庫。 集群將根據放置規則自動創建並分發其碎片。
如果可以指示客戶端應用程序使用新數據庫而不是舊數據庫,並且可以在非常短暫的中斷窗口內進行切換,則可以避免生產中的停機時間。
集群清除
群集清除的主要目的是清除具有多個刪除的邏輯刪除或包含大量沖突的單個文檔的數據庫。 但是,它也可以用於清除具有任何修訂版本的任何文檔(已刪除或未刪除)。
群集清除旨在維護最終的一致性並防止不必要的二級索引無效。 為此,每個數據庫都會跟蹤數據庫中請求的一定數量的歷史清除以及其當前的purge_seq
。 內部復制和二級索引處理數據庫的清除,並定期更新其相應的清除檢查點文檔以報告由其處理的purge_seq
。 為了確保最終的一致性,數據庫將僅在內部復制作業和二級索引處理了存儲的歷史清除請求之后,才刪除它們。
內部結構
為了在節點和二級索引之間實現內部清除信息的復制,將兩個內部清除樹添加到數據庫文件中以跟蹤歷史清除。
purge_tree: UUID -> {PurgeSeq, DocId, Revs}
purge_seq_tree: PurgeSeq -> {UUID, DocId, Revs}
每次對_purge API
的交互式請求,都會在增加purge_seq
和purge_request
時創建成對的有序集合,其中purge_request
是一個包含docid
和修訂列表的元組。 對於每個purge_request
都會生成uuid
。清除請求將添加到內部清除樹:將元組{UUID-> {PurgeSeq,DocId,Revs}}
添加到purge_tree
,元組 {PurgeSeq-> {UUID,DocId,Revs}}
添加到purge_seq_tree
。
壓縮清除
在數據庫壓縮期間,最舊的清除請求將被刪除,以僅在數據庫中存儲purged_infos_limit
個清除數目。 但是,為了使數據庫與索引和其他副本保持一致,我們只能刪除索引和內部復制作業已處理的清除請求。因此,有時清除樹可能存儲的數據超過purged_infos_limit
清除數目。 如果數據庫中存儲的清除數量超出purged_infos_limit
某個閾值,則日志中會產生警告,表明數據庫的清除與索引和其他副本的同步問題。
本地清除檢查點文檔
具有清除的數據庫索引和內部復制會創建並定期更新本地檢查點清除文檔:_local/purge-$type-$hash
。 這些文檔報告了它們最后處理的purge_seq
以及最后處理的時間戳。 本地檢查點清除文檔的示例:
{
"_id": "_local/purge-mrview-86cacdfbaf6968d4ebbc324dd3723fe7", "type": "mrview",
"purge_seq": 10,
"updated_on": 1540541874,
"ddoc_id": "_design/foo",
"signature": "5d10247925f826ae3e00966ec24b7bf6"
}
內部復制
清除請求將以最終一致的方式在所有節點上重播。 清除的內部復制包括兩個步驟:
1.拉取復制。內部復制首先要從目標中清除並將其應用於源,以確保我們不會重新引入目標中已清除的源文檔/修訂版。 在這一步中,我們使用存儲在目標上的清除檢查點文檔來跟蹤源處理的最后一個目標的purge_seq
。 我們發現清除請求在此purge_seq
之后發生,並在源上重播它們。 通過使用最新進程purge_seq
和時間戳更新目標的檢查點清除文檔來完成此步驟。
2.推送復制。 然后,內部復制將照常進行,並插入一個額外的步驟以將源的清除請求推送到目標。 在此步驟中,我們使用本地內部復制檢查點文檔,這些文檔在目標和源上均已更新。
在正常情況下,交互式清除請求已發送到包含數據庫碎片副本的每個節點,並應用於每個副本。節點之間清除的內部復制只是確保副本之間一致性的一個額外步驟,在此副本上,一個節點上的所有清除請求都會在另一個節點上重播。為了不在副本上重播相同的清除請求,每個交互式清除請求都用唯一的uuid
標記。內部復制會過濾出副本的purge_tree
中已存在的UUID
的清除請求,並僅應用purge_tree
中不存在的UUID
的清除請求。 這就是為什么我們需要有兩個內部清除樹的原因:1)purge_tree:{UUID-> {PurgeSeq,DocId,Revs}}
可以快速找到帶有已存在的UUID
的purge requests
存在的副本; 2)purge_seq_tree:{PurgeSeq-> {UUID,DocId,Revs }}
允許從給定的purge_seq
進行迭代,以收集在此purge_seq
之后發生的所有清除請求。
索引
每個清除請求將增加數據庫的update_seq
,以便還更新每個輔助索引,以便應用清除請求以維護主數據庫內的一致性。
配置設置
這些設置可以在default.ini
或local.ini
中進行更新:
字段 | 描述 | 默認值 |
---|---|---|
max_document_id_number | 一個清除請求中允許的最大文檔數 | 100 |
max_revisions_number | 一項清除請求中允許的最大累積修訂版本數 | 1000 |
allowed_purge_seq_lag | 除了purged_infos_limit 外,還允許其他緩沖區存儲清除請求 |
100 |
index_lag_warn_seconds | 本地清除檢查點文檔的索引未更新時的允許持續時間 | 86400 |
在數據庫壓縮期間,我們檢查所有檢查點清除文檔。 允許客戶端(索引或內部復制作業)的上一次報告的purge_seq
小於當前數據庫碎片的purge_seq
的值(purged_infos_limit + allowed_purge_seq_lag
)。如果客戶端的purge_seq
甚至更小,並且客戶端未在index_lag_warn_seconds
內設置檢查點,則它會阻止清除清除樹,因此我們必須對此客戶端發出以下日志警告:
Purge checkpoint '_local/purge-mrview-9152d15c12011288629bcffba7693fd4’
not updated in 86400 seconds in
<<"shards/00000000-1fffffff/testdb12.1491979089">>
如果發生這種類型的日志警告,請檢查客戶端以查看為什么清除請求的處理停滯在其中。
索引的設計文檔和本地檢查點文檔之間存在映射關系。 如果更新或刪除了索引的設計文檔,則也應自動刪除相應的本地檢查點文檔。 但是在意外情況下,當設計文檔被更新/刪除但其檢查點文檔仍然存在於數據庫中時,將發出以下警告:
"Invalid purge doc '<<"_design/bar">>' on database
<<"shards/00000000-1fffffff/testdb12.1491979089">>
with purge_seq '50'"
如果發生這種類型的日志警告,請從數據庫中刪除本地清除文檔。