網(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)存的頻繁分配。
如圖中所示,內(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ǔ)方式:
- 每次修改用戶的某個(gè)屬性,先反序列化改好后再序列化回去,開銷較大。
- 通過
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
相關(guān)推薦
- 2022-05-21 Python集合set()使用的方法詳解_python
- 2023-04-06 C語言中雙鏈表的基本操作_C 語言
- 2022-06-18 Qt?事件處理機(jī)制的深入理解_C 語言
- 2022-12-25 一文帶你熟悉Go語言中的for循環(huán)_Golang
- 2022-07-18 C++函數(shù)模板和類模板詳解
- 2022-08-01 Python?OpenCV基于HSV的顏色分割實(shí)現(xiàn)示例_python
- 2022-09-08 深入了解Go語言的基本語法與常用函數(shù)_Golang
- 2022-01-03 踩坑解決mongoose對(duì)已經(jīng)存在的集合查詢,查詢條件不起限制作用的問題
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲(chǔ)小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯(cuò)誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡(jiǎn)單動(dòng)態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對(duì)象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊(duì)列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支