MongoDB文檔(Document)全局唯一ID的設(shè)計思路
在MongoDB中,如果不特別指定,每個文檔都會生成一個唯一的ObjectId作為其主鍵_id的值。這個值是一個看似隨機的串。這個串到底是什么值?為什么MongoDB要使用這個值作為默認(rèn)主鍵?它內(nèi)部又包含了什么樣的信息?如果你還不了解,就請看下面文章吧。
感謝劉浩@人民搜索的投稿。
MongoDB中數(shù)據(jù)的基本單元稱為文檔(Document)。文檔是MongoDB的核心概念,多個鍵極其關(guān)聯(lián)的值有序的放置在一起便是文檔。
在一個特定集合內(nèi)部,需要唯一的標(biāo)識文檔。因此MongoDB中存儲的文檔都由一個”_id”鍵,用于完成此功能。這個鍵的值可以是任意類型的,默認(rèn)試ObjectId對象。ObjectId對象的生成思路是本文的主題,也是很多分布式系統(tǒng)可以借鑒的思路。
為了考慮分布式,“_id”要求不同的機器都能用全局唯一的同種方法方便的生成它。因此不能使用自增主鍵(需要多臺服務(wù)器進(jìn)行同步,既費時又費力),因此選用了生成ObjectId對象的方法。
ObjectId使用12字節(jié)的存儲空間,其生成方式如下:
0 1 2 3 4 5 6 7 8 9 10 11
時間戳 機器ID PID 計數(shù)器
前四個字節(jié)時間戳是從標(biāo)準(zhǔn)紀(jì)元開始的時間戳,單位為秒,有如下特性:
時間戳與后邊5個字節(jié)一塊,保證秒級別的唯一性;
保證插入順序大致按時間排序;
隱含了文檔創(chuàng)建時間;
機器ID是服務(wù)器主機標(biāo)識,通常是機器主機名的散列值。
同一臺機器上可以運行多個mongod實例,因此也需要加入進(jìn)程標(biāo)識符PID。
前9個字節(jié)保證了同一秒鐘不同機器不同進(jìn)程產(chǎn)生的ObjectId的唯一性。后三個字節(jié)是一個自動增加的計數(shù)器(一個mongod進(jìn)程需要一個全局 的計數(shù)器),保證同一秒的ObjectId是唯一的。同一秒鐘最多允許每個進(jìn)程擁有(256^3 = 16777216)個不同的ObjectId。
總結(jié)一下:時間戳保證秒級唯一,機器ID保證設(shè)計時考慮分布式,避免時鐘同步,PID保證同一臺服務(wù)器運行多個mongod實例時的唯一性,最后的計數(shù)器保證同一秒內(nèi)的唯一性(選用幾個字節(jié)既要考慮存儲的經(jīng)濟性,也要考慮并發(fā)性能的上限)。
“_id”既可以在服務(wù)器端生成也可以在客戶端生成,在客戶端生成可以降低服務(wù)器端的壓力。
|