日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學(xué)無先后,達(dá)者為師

網(wǎng)站首頁 編程語言 正文

Redis五大常用數(shù)據(jù)結(jié)構(gòu)-string、list、set、hash、zset(筆記)

作者:whoami_ZQ 更新時間: 2022-11-29 編程語言

String

簡介

String是 Redis 最基本的類型,你可以理解成與Memcached 一模一樣的類型,一個 key 對應(yīng)一個 value。
String 類型是二進制安全的。意味著 Redis 的 string 可以包含任何數(shù)據(jù)。比如:jpg圖像或者序列化的對象。
String 類型是 Redis 最基本的數(shù)據(jù)類型,一個 Redis中字符串value最多可以是512M。

常用命令

set <key> <value> 添加鍵值對。

  • NX:當(dāng)數(shù)據(jù)庫中key不存在時,可以將 key-value 添加數(shù)據(jù)庫。setnx key value
  • XX:當(dāng)數(shù)據(jù)庫中key存在時,可以將 key-value 添加數(shù)據(jù)庫,與NX參數(shù)互斥。
  • EX:key 的超時秒數(shù)。
  • PX:key 的超時毫秒數(shù),與EX互斥。

get <key> 查詢對應(yīng)鍵值。
append <key> <value> 將給定的<value>追加到原值的末尾。
strlen <key> 獲得值得長度。
setnx <key> <value> 只有在 key 不存在時,設(shè)置 key 的值。
incr <key> 將 key 中存儲的數(shù)字值增1。
decr <key> 將key 中存儲的數(shù)字值減1,只能對數(shù)字值操作,如果為空,新增值為-1。
incrby或者decrby <key> <步長> 將key 中存儲的數(shù)字值遞增或遞減。自定義步長。
mset <key1> <value1> <key2> <value2> ... 同時獲取一個或多個 value。
msetnx <key1> <value1> <key2> <value2> ... 同時設(shè)置一個或多個 key-value 對,當(dāng)且僅當(dāng)所有給定 key 都不存在。
原子性,有一個失敗則都失敗。
getrange <key> <起始位置> <結(jié)束位置> 獲得值的范圍,類型java中的substring,前包,后包。
setrange <key> <起始位置> <value> 用<value> 覆蓋<key>所存儲的字符串值,從<起始位置>開始(索引從0開始)。
setex <key> <過期時間> <value> 設(shè)置鍵值的同時,設(shè)置過期時間,單位秒。
getset <key> <value> 以新?lián)Q舊,設(shè)置新值的同時獲得舊值。

數(shù)據(jù)結(jié)構(gòu)

String 的數(shù)據(jù)結(jié)構(gòu)為簡單動態(tài)字符串(Simple Dynamic String,縮寫SDS)。是可以修改的字符串,內(nèi)部結(jié)構(gòu)是實現(xiàn)上類似于Java的ArrayList,采用預(yù)分配冗余空間的方式來減少內(nèi)存的頻繁分配。
0
如圖中所示,內(nèi)部為當(dāng)前字符串實際分配的空間 capacity 一般要高于實際字符串長度len。當(dāng)字符串長度小于1M時,擴容都是加倍現(xiàn)有的空間,如果超過 1M,擴容時一次只會擴 1M 的空間。需要注意的時字符串最大長度為 512M。

List

簡介

單鍵多值
Redis 列表是簡單的字符串列表,按照插入順序排序。你可以添加一個元素到列表的頭部(左邊)或者尾部(右邊)。
它的底層實際是個雙向鏈表,對兩端的操作性能很高,通過索引下標(biāo)的操作中間的節(jié)點性能會較差。
雙向鏈表示意圖

常用命令

lpush/rpush <key> <value1> <value2> ...... 從左邊/右邊插入一個或多個值。
lpop/rpop <key> 從左邊/右邊取出一個值,并刪除。值在鍵在
rpoplpush <key1> <key2> 從<key1>列表取出一個值,插在<key2>列表的左邊。
lrange <key1> <start> <stop> 按照索引下標(biāo)獲得元素(從左到右)。
lrange mylist 0 -1 0左邊第一個,-1右邊第一個,(0 -1表示獲取所有)。
lindex <key> <index> 按照索引下標(biāo)獲得元素(從左到右)。
llen <key> 獲得列表長度。
linsert <key> before <value> <newvalue> 在<value>后面插入<newvalue>值。
lrem <key> <n> <value> 從左邊刪除n個value(從左到右)。
lset <key> <index> <value> 將列表key下標(biāo)為index的值替換成value。

數(shù)據(jù)結(jié)構(gòu)

List的數(shù)據(jù)結(jié)構(gòu)為快速鏈表quickList
首先在列表元素較少的情況下會使用一塊連續(xù)的內(nèi)存存儲,這個結(jié)構(gòu)是ziplist,也即是壓縮列表。

它將所有的元素緊挨著一起存儲,分配的是一塊連續(xù)的內(nèi)存。
當(dāng)數(shù)據(jù)量比較多的時候才會改成quicklist。

因為普通的鏈表需要的的附加指針空間太大,會比較浪費空間。比如:列表里存的只是int類型的數(shù)據(jù),結(jié)構(gòu)上還需要兩個額外的指針prev和next。
指針

Redis將鏈表和ziplist結(jié)合起來組成了quicklist。也就是將多個ziplist使用雙向指針串起來使用。這樣既滿足了快速的插入刪除性能,又不會出現(xiàn)太大的空間冗余。

Set

簡介

Redis set 對外提供的功能與list類似是一個列表的功能,特殊之處在于set是可以自動排重的,當(dāng)你需要存儲一個列表數(shù)據(jù),又不希望出現(xiàn)重復(fù)數(shù)據(jù)時,set 是一個很好的選擇,并且 set 提供了判斷某個成員是否在一個 set集合內(nèi)的重要接口,這也是 list 所不能提供的。
Redis 的 set 時string類型的無序集合。它底層其實是一個value為null的hash表,所以添加、刪除、查找的復(fù)雜度都是 O(1)
一個算法,隨著數(shù)據(jù)的增加,執(zhí)行時間的長短,如果是 O(1),數(shù)據(jù)增加,查找數(shù)據(jù)的時間不變。

常用命令

sadd <key> <value1> <value2> ...... 將一個或多個member元素加入到集合key中,已經(jīng)存在的member元素將被忽略。
smembers <key> 取出該集合的所有值。
sismember <key> <value> 判斷集合<key>是否為含有該<value>值,有則為1,無則0。
scard <key> 返回該集合的元素個數(shù)。
srem <key> <value1> <value2> ... 刪除集合中的某個元素。
spop <key> 隨機從該集合中取出一個值,并刪除。
srandmember <key> <n> 隨機從該集合中取出n個值。不會從集合中刪除。
smove <source> <destination> value 把集合中一個值從一個集合移動到另一個集合。
sinter <key1> <key2> 返回兩個集合的交集。
sunion <key1> <key2> 返回兩個集合的并集。
sdiff <key1> <key2> 返回兩個集合的差集(key1中的,不包含key2中的)。

數(shù)據(jù)結(jié)構(gòu)

Set 數(shù)據(jù)結(jié)構(gòu)是dict字典,字典使用哈希表實現(xiàn)的。
Java中 HashSet 的內(nèi)部實現(xiàn)使用的是 HashMap,只不過所有的 value 都指向同一個對象。
Redis的 set 結(jié)構(gòu)也是一樣,它的內(nèi)部也使用 hash 結(jié)構(gòu),所有的 value 都指向同一個內(nèi)部值。

Hash

簡介

Redis Hash是一個鍵值對集合。
Redis Hash 是一個string類型的 field 和 value 的映射表,hash 特別適合用于存儲對象。
類似 Java 里面的Map<String,Object>
用戶ID為查找的 Key,存儲的 value 用戶對象包含姓名,年齡,生日等信息,如果用普通的 key/value 結(jié)構(gòu)來存儲,主要有以下2種存儲方式:

  1. 每次修改用戶的某個屬性,先反序列化改好后再序列化回去,開銷較大。
    第一種
  2. 通過key(用戶ID)+field(屬性標(biāo)簽)就可以操作對應(yīng)屬性數(shù)據(jù)了,既不需要重復(fù)存儲數(shù)據(jù),也不會帶來序列化和并發(fā)修改控制的問題。
    第二種

常用命令

hset <key> <field> <value> 給<key>集合種的<field>鍵賦值<value>。
hget <key1> <field> 從<key1>集合<field>取出 value。
hmset <key1> <field1> <value1> <field2> <value2>... 批量設(shè)置 hash 的值。
hexists <key1> <field> 查看哈希表 key 中,給定域 field 是否存在。
hkeys <key> 列出該 hash 集合的所有 field。
hvals <key> 列出該 hash 集合的所有 value。
hincrby <key> <field> <increment> 為哈希表 key 中的域 field的值加上增量 1 -1。
hsetnx <key> <field> <value> 將哈希表 key 中的域 field 的值設(shè)置為value,當(dāng)且僅當(dāng)域 field 不存在。

數(shù)據(jù)結(jié)構(gòu)

Hash類型對應(yīng)的數(shù)據(jù)結(jié)構(gòu)是兩種:ziplist(壓縮列表),hashtable(哈希表)。當(dāng) field-value 長度較短且個數(shù)較少時,使用ziplist,否則使用hashtable。

ZSet有序集合(sorted set)

簡介

Redis有序集合 zset 與普通集合 set 非常相似,是一個沒有重復(fù)元素的字符串集合。

不同之處是有序集合的每個成員都關(guān)聯(lián)了一個評分(score),這個評分(score)被用來按照最低分到最高分的方式排序集合中的成員。集合的成員是唯一的,但是評分可以是重復(fù)的
因為元素是有序的,所以可以很快的根據(jù)評分(score)或者次序(position)來獲取一個范圍的元素。
訪問有序集合的中間元素也是非常快的,因此你能夠使用有序集合作為一個沒有重復(fù)成員的智能列表。

常用命令

zadd <key> <score1> <value1> <score2> <value2>... 將一個或多個member元素及其score值加入到有序集合key當(dāng)中。
zrange <key> <start> <stop> [WITHSCORES] 返回有序集key中,下標(biāo)在<strat> <stop>之間的元素。帶WITHSCORES,可以讓分?jǐn)?shù)一起和值返回到結(jié)果集。
zrangebyscore key min max [withscores] [limit offset count] 返回有序集key中,所有score值介于min和max之間(包括等于min或max)的成員,有序集成員按score值遞增(從小到大)次序排列。
zrevrangebyscore key min max [withscores] [limit offset count] 同上,改為從大到小排列。
zincrby <key> <increment> <value> 為元素的score加上增量。
zrem <key> <value> 刪除該集合下,指定值的元素。
zcount <key> <min> <max> 統(tǒng)計該集合,分?jǐn)?shù)區(qū)間內(nèi)的元素個數(shù)。
zrank <key> <value> 返回該值在集合中的排名,從0開始。

數(shù)據(jù)結(jié)構(gòu)

Sorted Set(zset) 是Redis提供的一個非常特別的數(shù)據(jù)結(jié)構(gòu),一方面它等價于Java的數(shù)據(jù)結(jié)構(gòu)Map<String,Double>,可以給每一個元素value賦予一個權(quán)重score,另一方面它又類似于TreeSet,內(nèi)部元素會按照權(quán)重score進行排序,可以得到每個元素的名詞,還可以通過score的范圍來獲取元素的列表。
zset底層使用了兩個數(shù)據(jù)結(jié)構(gòu)。
(1) hash,hash的作用就是關(guān)聯(lián)元素value和權(quán)重score,保障元素value的唯一性,可以通過元素value找到相應(yīng)的score值。
(2) 跳躍表,跳躍表的目的在于給元素value排序,根據(jù)score的范圍獲取元素列表。

跳躍表(跳表)

簡介

有序集合在生活中比較常見,例如根據(jù)成績對學(xué)生排名,根據(jù)得分對玩家排名等。對于有序集合的底層實現(xiàn),可以用數(shù)組、平衡樹、鏈表等。數(shù)組不便元素的插入、刪除;平衡樹或紅黑樹雖然效率搞但結(jié)構(gòu)復(fù)雜;鏈表查詢需要遍歷所有,效率低。Redis采用的是跳躍表。跳躍表效率堪比紅黑樹,實現(xiàn)遠(yuǎn)比紅黑樹簡單。

實例

對比有序鏈表和跳躍表,從鏈表種查詢出51
(1)有序鏈表
在這里插入圖片描述
要查找值為51的元素,需要從第一個元素開始一次查找、比較才能找到。共需要6次比較。
(2)跳躍表
在這里插入圖片描述
從第2層開始,1節(jié)點比51節(jié)點小,向后比較。
21節(jié)點比51節(jié)點小,繼續(xù)向后比較,后面就是null了,所以從21節(jié)點向下到第1層。
在第1層,41節(jié)點比51節(jié)點小,繼續(xù)向后,61節(jié)點比51節(jié)點大,所以從41向下。
在第0層,51節(jié)點為要查找的節(jié)點,節(jié)點被找到,共查找4次。

從此可以看出跳躍表比有序鏈表效率要高。

原文鏈接:https://blog.csdn.net/weixin_43712786/article/details/127785561

欄目分類
最近更新