Ceph 對象存儲網關允許你通過 Swift 及 S3 API 訪問 Ceph 。它將這些 API 請求轉化為 librados 請求。Librados 是一個非常出色的對象存儲(庫)但是它無法高效的列舉對象。對象存儲網關維護自有索引來提升列舉對象的響應性能並維護了其他的一些元信息。有關對象存儲網關索引工作原理的文章很少,所以我寫了這篇博文,權當拋磚迎玉。
我們先來看看一個已存在的 bucket

這個 bucket 的對象列表存儲在一個單獨的 rados 對象中。這個對象的名字是 .dir. 加上 bucket id 。索引對象存儲在一個名為 .rgw.buckets.index 的獨立存儲池中。所以本例中,mybucket 的索引應該是 .dir.default.14113.1(譯者注:原文中是.dir.default.2529250.167, 基於原理和實踐,確定此處有誤,特此更正)。
找到 bucket 索引
# rados -p .rgw.buckets.index ls - | grep "default.14113.1"
.dir.default.14113.1
你可以看到從 .rgw.buckets.index 存儲池返回的索引對象。
查看索引對象的內容
# rados -p rados -p .rgw.buckets.index get .dir.default.14113.1 indexfile
# wc -c indexfile
0 indexfile
對象為 0 字節,怎么回事呢?秘密是:索引信息實際上存儲在 Ceph 的鍵/值數據庫中。每個 OSD 都有一個本地 leveldb 鍵/值數據庫。因此索引對象實際上只是一個占位符,Ceph 通過它找到那個包含索引信息的 OSD 鍵/值數據庫。
查看鍵/值數據庫的內容
先來看看索引鍵
# rados -p .rgw.buckets.index listomapkeys
.dir.default.14113.1myobject
所以索引鍵就是對象名(情理之中)。
再來看看索引值

現在比較對頭了!本例中索引占了 175 字節,從上面的十六進制轉儲信息可以看到一些信息片段。如果你用上面的轉儲信息與 radosgw-admin 輸出的對象元信息對比,你就會知道索引中存儲的是什么。
對象元信息

我們可以確定索引包含如下信息:
-
name -
owner -
owner_display_name -
etag -
tag
需要注意的是 owner 既是鍵也是值。我認為這樣做是在出現數據損壞時能通過掃描索引值來恢復索引鍵。
owner_display_name 在這里是為了兼容 S3。顯然是一個讀寫妥協。
etag(實體標簽)是對象的 MD5 值,也是為了兼容 S3。這有點得不償失,因為我可以肯定如果每次創建一個對象就要計算 MD5 值,這將會損害寫性能。
我懷疑 radosgw-admin 顯示的其他元信息也包含在索引中(或者為空或者不可見)。
找到鍵值數據庫
計算出包含索引對象的 OSD
# ceph osd map .rgw.buckets.index .rgw.buckets.index .dir.default.14113.24
osdmap e60 pool '.rgw.buckets.index' (11) object '.dir.default.14113.24/.rgw.buckets.index' -> pg 11.e6c72a3f (11.3f) -> up ([3,5], p3) acting ([3,5], p3)
我們看到鍵值數據庫在 OSD 3 及 5 上,其中 3 是主 OSD(第一個)。
找到 OSD 3 上的鍵值數據庫

可以看到 osd.3 在主機 ceph-osd1 上

這就是包含索引的鍵值數據庫 leveldb。
