筆記學習來源極客時間深入學習redis和自己總結
一.簡單的kv nosql基礎架構的構成
首先作者讓我們從一個基礎的nosql的架構讓我們認識一個kv結構的nosql的基礎架構,在基礎架構中分為訪問模式,基礎操作,索引模塊和存儲模式(分配器和持久化)。
一個簡單的kv nosql,在訪問模式中分為本地庫模式和網絡訪問模式(我認為的是client端口),基礎的操作分為增刪查,對應redis就是put delete get/scan,在redis中put和delete操作不但是更新和刪除,還做了資源的分配和釋放,索引模塊主要是為了快速查詢常見為b+樹和hash表,存儲模式這里是可以支持永久存儲和內存存儲還有分配內存和釋放內存的機制。
二.對於redis為什么查詢速度這么快的原因
在redis中主要的數據類型為String,set,list,hash,sortSet,在我看來這些數據類型都是比較節約內存的list和set都是因為是連續的內存無論在內存存儲還是在獲取到內存訪問都是效率比較高的,原因是可以對下標進行隨機訪問時間復雜度為O(1)這個是在於數據層面為何能快速拿去數據的一部份。
第二個原因是的索引查詢是用hash表進行搜索的,hash表中是一個list每個list中的一個單位為存儲entry的單位,entry中存儲了key和value,因為hash存儲的原因如果在存入大數據量的時候難免會出現hash沖突,為了避免這個情況redis在儲存相同hash時使用了hash鏈表進行存儲,然后通過rehash,就是增加hash表中hash桶(就是list中的一個單位),然后把沖突的值全部拷貝過去。
在拷貝的過程中會遇到一個問題,因為redis是單線程,如果全部拷貝的話這樣會產生阻塞這樣的話可能無法運行,那么redis使用的是漸進式拷貝,就是逐個分配這樣可以把沖突的hash分配到其他桶中這樣訪問效率可以更快,一下為redis底層數據類型。
作者給出4行口訣
單元素操作是基礎;范圍操作非常耗時;統計操作通常高效;例外情況只有幾個。
第一,單元素操作,是指每一種集合類型對單個數據實現的增刪改查操作。例如,Hash 類型的 HGET、HSET 和 HDEL,Set 類型的 SADD、SREM、SRANDMEMBER 等。這些操作的復雜度由集合采用的數據結構決定,例如,HGET、HSET 和 HDEL 是對哈希表做操作,所以它們的復雜度都是 O(1);Set 類型用哈希表作為底層數據結構時,它的 SADD、SREM、SRANDMEMBER 復雜度也是 O(1)。這里,有個地方你需要注意一下,集合類型支持同時對多個元素進行增刪改查,例如 Hash 類型的 HMGET 和 HMSET,Set 類型的 SADD 也支持同時增加多個元素。此時,這些操作的復雜度,就是由單個元素操作復雜度和元素個數決定的。例如,HMSET 增加 M 個元素時,復雜度就從 O(1) 變成 O(M) 了。
第二,范圍操作,是指集合類型中的遍歷操作,可以返回集合中的所有數據,比如 Hash 類型的 HGETALL 和 Set 類型的 SMEMBERS,或者返回一個范圍內的部分數據,比如 List 類型的 LRANGE 和 ZSet 類型的 ZRANGE。這類操作的復雜度一般是 O(N),比較耗時,我們應該盡量避免。不過,Redis 從 2.8 版本開始提供了 SCAN 系列操作(包括 HSCAN,SSCAN 和 ZSCAN),這類操作實現了漸進式遍歷,每次只返回有限數量的數據。這樣一來,相比於 HGETALL、SMEMBERS 這類操作來說,就避免了一次性返回所有元素而導致的 Redis 阻塞。
第三,統計操作,是指集合類型對集合中所有元素個數的記錄,例如 LLEN 和 SCARD。這類操作復雜度只有 O(1),這是因為當集合類型采用壓縮列表、雙向鏈表、整數數組這些數據結構時,這些結構中專門記錄了元素的個數統計,因此可以高效地完成相關操作。
第四,例外情況,是指某些數據結構的特殊記錄,例如壓縮列表和雙向鏈表都會記錄表頭和表尾的偏移量。這樣一來,對於 List 類型的 LPOP、RPOP、LPUSH、RPUSH 這四個操作來說,它們是在列表的頭尾增刪元素,這就可以通過偏移量直接定位,所以它們的復雜度也只有 O(1),可以實現快速操作。