壓縮列表(ziplist)是列表鍵和雜湊鍵的底層實現之一。當乙個列表鍵只包含少量列表鍵,並且每個列表項要麼就是小整數值,要麼就是長度比較短的字串,那麼redis就會使用壓縮列表來做列表鍵的底層實現。
另外,當乙個雜湊鍵只包含少量鍵值對,並且每個鍵值對的鍵和值要麼就是小整數值,要麼就是長度比較短的字串,那麼redis就會使用壓縮列表來做雜湊鍵的底層實現。
壓縮列表是redis為了節約記憶體而開發的,是由一系列特殊編碼的連續記憶體塊組成的順序性(sequential)資料結構。乙個壓縮列表可以包含任意多個節點(entry),每乙個節點可以儲存乙個位元組陣列或者乙個整數值。
圖7-2展示了乙個壓縮列表示例
每個壓縮列表節點可以儲存乙個位元組陣列或者乙個整數值,其中,位元組陣列是以下三種長度的其中一種:
而整數值則可以是以下六種長度的其中一種:
每個壓縮列表節點都由previous_entry_length,encoding,content三部分組成。
節點的privious_entry_length屬性以位元組為單位,記錄了壓縮列表中前乙個節點的長度。previous_entry_length屬性的長度可以是1位元組或者5位元組:
因為節點的previous_entry_length屬性記錄了前乙個節點的長度,所以程式可以通過指標運算,根據當前節點的起始位址來計算出前乙個節點的起始位址。
例如,有乙個指向當前節點起始位址的指標c,那麼我們只要用指標c減去當前節點previous_entry_length屬性的值,就可以得出乙個指向前乙個節點起始位址的指標p.
壓縮列表從表尾向表頭遍歷操作就是使用這一原理實現的,只要我們擁有了乙個指向某個節點起始位址的指標,那麼通過這個指標以及這個節點的previous_entry_length屬性,程式就可以一直向前乙個節點回溯,最終到達壓縮列表的表頭節點。
節點的encoding屬性記錄了節點的content屬性所儲存資料的型別及長度;
節點的content屬性負責儲存節點的值,節點值可以是乙個位元組陣列或者整數,值的型別和長度由節點的encoding屬性決定。
圖7-9展示了乙個儲存位元組陣列的節點示例,圖7-10展示了乙個儲存整數值的節點示例:
現在,考慮這樣一種情況:在乙個壓縮列表中,有多個連續的、長度介於250位元組到253位元組之間的節點e1至en,如圖7-11所示:
因為e1至en的所有節點的長度都小於254位元組,所以記錄這些節點的長度只需要1位元組長的previous_entry_length屬性,換句話說,e1至en的所有節點的previous_entry_length屬性都是1位元組長的。
這時,如果將乙個長度大於等於254位元組的新結點new設定為壓縮列表的表頭節點,那麼new將成為e1的前置節點,如圖7-12所示:
因為e1的previous_entry_length屬性僅長1位元組,它沒辦法儲存新結點new的長度,所以程式將對壓縮列表執行空間重分配操作,並將e1節點的previous_entry_length屬性從原來的1位元組擴充套件為5位元組長。e2,e3...也做同樣擴充套件。
redis將這種在特殊情況下產生的連續多次空間擴充套件操作稱之為:"連鎖更新"(cascade update),圖7-13展示了這一過程。
除了新增新節點可能會引發連鎖更新之外,刪除節點也可能會引發連鎖更新。
Chapter7 常量和字段
常量 constant 是乙個特殊的符號,它有乙個從不變化的值,定義常量符號時,它的值必須能在編譯時確定,確定之後,編譯器將常量的值儲存到程式集的元資料中。這意味著只能為編譯器認定的基元型別定義常量,也可以是非基元型別,但必須是null。所以 在引用乙個常量符號時,不需要為常量分配任何記憶體,編譯器...
Chapter7 模板方法模式
模板方法模式 定義乙個操作中的演算法的骨架,而將一些步驟延遲到子類中。模板方法使得子類可以不改變乙個演算法的結構即可重定義該演算法的某些特定步驟。既然用了繼承,並且肯定這個繼承有意義,就應該要成為子類的模板,所有重複的 都應該要上公升到父類去,而不是讓每個子類都去重複。當我們要完成在某一細節層次一致...
chapter7 管理使用者和性
第7章 管理使用者和安全性 目的 您必須建立使用者帳戶並授予那些帳戶相應的訪問許可權,以使使用者能夠訪問您的資料庫。某些使用者帳戶自動包括在預先配置的資料庫中,但是出於安全性的原因,這些帳戶中的大多數都是被鎖定的或過期的。在本章,您將學到如何建立和 管理使用者帳戶。您將使用enterpriseman...