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

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

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

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

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

String

簡(jiǎn)介

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

常用命令

set <key> <value> 添加鍵值對(duì)。

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

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

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

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

List

簡(jiǎn)介

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

常用命令

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

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

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

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

因?yàn)槠胀ǖ逆湵硇枰牡母郊又羔樋臻g太大,會(huì)比較浪費(fèi)空間。比如:列表里存的只是int類型的數(shù)據(jù),結(jié)構(gòu)上還需要兩個(gè)額外的指針prev和next。
指針

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

Set

簡(jiǎn)介

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

常用命令

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

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

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

Hash

簡(jiǎn)介

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

  1. 每次修改用戶的某個(gè)屬性,先反序列化改好后再序列化回去,開銷較大。
    第一種
  2. 通過key(用戶ID)+field(屬性標(biāo)簽)就可以操作對(duì)應(yīng)屬性數(shù)據(jù)了,既不需要重復(fù)存儲(chǔ)數(shù)據(jù),也不會(huì)帶來序列化和并發(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類型對(duì)應(yīng)的數(shù)據(jù)結(jié)構(gòu)是兩種:ziplist(壓縮列表),hashtable(哈希表)。當(dāng) field-value 長(zhǎng)度較短且個(gè)數(shù)較少時(shí),使用ziplist,否則使用hashtable。

ZSet有序集合(sorted set)

簡(jiǎn)介

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

不同之處是有序集合的每個(gè)成員都關(guān)聯(lián)了一個(gè)評(píng)分(score),這個(gè)評(píng)分(score)被用來按照最低分到最高分的方式排序集合中的成員。集合的成員是唯一的,但是評(píng)分可以是重復(fù)的。
因?yàn)樵厥怯行虻模钥梢院芸斓母鶕?jù)評(píng)分(score)或者次序(position)來獲取一個(gè)范圍的元素。
訪問有序集合的中間元素也是非常快的,因此你能夠使用有序集合作為一個(gè)沒有重復(fù)成員的智能列表。

常用命令

zadd <key> <score1> <value1> <score2> <value2>... 將一個(gè)或多個(gè)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ì)該集合,分?jǐn)?shù)區(qū)間內(nèi)的元素個(gè)數(shù)。
zrank <key> <value> 返回該值在集合中的排名,從0開始。

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

Sorted Set(zset) 是Redis提供的一個(gè)非常特別的數(shù)據(jù)結(jié)構(gòu),一方面它等價(jià)于Java的數(shù)據(jù)結(jié)構(gòu)Map<String,Double>,可以給每一個(gè)元素value賦予一個(gè)權(quán)重score,另一方面它又類似于TreeSet,內(nèi)部元素會(huì)按照權(quán)重score進(jìn)行排序,可以得到每個(gè)元素的名詞,還可以通過score的范圍來獲取元素的列表。
zset底層使用了兩個(gè)數(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的范圍獲取元素列表。

跳躍表(跳表)

簡(jiǎn)介

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

實(shí)例

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

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

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

欄目分類
最近更新