日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

Redis 之(二) Redis的基本数据结构以及一些常用的操作

發布時間:2025/3/20 数据库 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Redis 之(二) Redis的基本数据结构以及一些常用的操作 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

本篇內容是Redis最簡單最容易掌握的知識,如果你已經熟知了,就可以選擇跳過啦!

要體驗Redis,那么首先你得安裝Redis,這邊的話我就只講一下Windows環境下的安裝與操作:

Window 下安裝

下載地址:https://github.com/MSOpenTech/redis/releases。

Redis 支持 32 位和 64 位。這個需要根據你系統平臺的實際情況選擇,這里我們下載?Redis-x64-xxx.zip壓縮包到 C 盤,解壓后,將文件夾重新命名為?redis

打開一個?cmd?窗口 使用cd命令切換目錄到?C:\redis?運行?redis-server.exe redis.windows.conf?。

如果想方便的話,可以把 redis 的路徑加到系統的環境變量里,這樣就省得再輸路徑了,后面的那個 redis.windows.conf 可以省略,如果省略,會啟用默認的。輸入之后,會顯示如下界面:

這時候另啟一個cmd窗口,原來的不要關閉,不然就無法訪問服務端了。

切換到redis目錄下運行?redis-cli.exe -h 127.0.0.1 -p 6379?。

設置鍵值對?set myKey abc

取出鍵值對?get myKey

到這里,安裝就結束啦!同樣的Linux和Mac環境下的同學們可以在菜鳥教程上找到自己需要的,我就不搬磚了!

?

Redis 基礎數據結構

? ? ? ?Redis常見的數據結構一共有五種,分別是:string(字符串)、List(列表)、set(集合)、zset(有序集合)、hash(哈希)

? ? ? ?這五種基本數據結構需要我們熟練掌握!在Redis中,所有的數據結構都是以唯一的Key字符串作為名稱,然后通過這個唯一Key值來獲取相應的value數據。不同類型的數據結構的差異就在于value的結構不一樣。

? ? ? ?string(字符串)

? ? ? ?字符串string是Redis最簡單的數據結構。

? ? ? ?字符串結構的使用非常廣泛,常見的用途就是緩存用戶信息,我們將用戶信息結構體使用JSON序列化成字符串,然后將序列化后的字符串塞進Redis來緩存,當我們取得用戶信息時會經過一次反序列化的過程。

? ? ? ?Redis的字符串是動態字符串,也就是說可修改的字符串,結構上類似于Java中的ArrayList,采用了預分配冗余空間的方式減少內存的頻繁分配。上圖中,字符串實際分配的空間capacity一般是>字符串的長度len的。在Redis中,字符串的長度小于1M時,擴容都是加倍現有的空間,如果超過了1M,那么擴容則只會增加1M的空間。而字符串的最大長度為512M。

? ? ? ?鍵值對

> set name codehole //設置指定key的值 OK > get name //獲取指定key "codehole" > exists name (integer) 1 > del name (integer) 1 > get name (nil)

? ? ? ?批量鍵值對

> set name1 codehole OK > set name2 holycoder OK > mget name1 name2 name3 # 返回一個列表 1) "codehole" 2) "holycoder" 3) (nil) > mset name1 boy name2 girl name3 unknown > mget name1 name2 name3 1) "boy" 2) "girl" 3) "unknown"...

? ? ? ?過期和set命令擴展

? ? ? ?我們可以對key設置過期時間,到點自動刪除,一般我們通過這個功能來控制緩存的失效時間。

? ? ? ?

> set name c1 OK > get name "c1" > expire name 5 //設置五秒后過期 (integer) 1 //.....等待五秒 > get name (nil)> setex name 5 c1 //5s 后過期,等價于 set+expire > get name "c1" //.....等待五秒 > get name (nil)> setnx name c1 // 如果 name 不存在就執行 set 創建 (integer) 1 > get name "c1" > setnx name c2 (integer) 0 // 因為 name 已經存在,所以 set 創建不成功 > get name "c1" // 沒有改變...

?

? ? ? ?計數

? ? ? ?如果value值是一個整數,還可以對他進行自增操作。自增是有范圍的,它的范圍是 signend long 的最大最小值,超過了這個值,Redis會報錯。

> set age 30 OK > incr age //通過incr命令將key中存儲的數值增一,如果key不存在,key的值會被先初始化為0,然后再進行INCR操作 (integer) 31 > incrby age 5 //通過incrby命令將key中存儲的數值加上指定的增加量,如果key不存在,key的值會被先初始化為0,然后再進行INCR操作 (integer) 36 > incrby age -5 (integer) 31 > set c1 9223372036854775807 // Long.Max OK > incr c1 (error) ERR increment or decrement would overflow...

? ? ? ?字符串由多個字節(Byte)組成,每個字節由8個bit組成,我們可以講一個字符串看成很多bit的組合,這就是bitmap(位圖)的數據結構。

? ? ? list(列表)

? ? ? ?Redis的list列表相當于Java中的LinkedList,它是鏈表而不是數組,意味著增刪快而檢索查詢慢。

? ? ? ?當 list 彈出了最后一個元素后,該數據結構會被自動刪除,內存被回收。

??

? ? ? ?Redis的 list 結構通常用來做異步隊列使用。將需要延后處理的任務結構體序列化成字符串塞進 list 列表,另一個線程從這個列表中輪詢數據進行處理。

? ? ? ? 先進先出:隊列

? ? ? ?

> rpush book java (integer) 1 > rpush book python (integer) 2 > rpush book golong (integer) 3// 將一個或多個值 value 插入到列表 key 的表尾(最右邊) // 也可寫為
// > rpush books python java golang
> llen book//返回列表的長度 (integer) 3 > lpop book "java" > lpop book "python" > lpop book//移除列表左側的頭元素 "golong"

? ? ? ?先進后出:棧

> rpush book python java golang (integer) 3 > rpop book "golang" > rpop book "java" > rpop book "python" > rpop book (nil)...

?

? ? ? ?慢操作

? ? ? ?lindex 相當于Java鏈表的 get(int index) 方法,他需要對鏈表進行遍歷,性能隨鏈表長度的增大而變差。

? ? ? ?

redis> LPUSH mylist "World" (integer) 1redis> LPUSH mylist "Hello" (integer) 2redis> LINDEX mylist 0 "Hello"redis> LINDEX mylist -1 "World"redis> LINDEX mylist 3 //index不在 mylist 的區間范圍內 (nil)

? ? ? ?Ltrim 和跟著的兩個參數start_index和end_index定義了一個區間,在這個區間內的值,ltrim要保留,區間之外統統砍掉。我們可以通過ltrim來實現一個定長的鏈表。(其實就是裁剪)

? ? ? ?index可以為負數,index=-1表示倒數第一個元素,同樣index=-2表示倒數第二個元素。

? ? ? ?Lrange 則是返回指定區間的元素。

> RPUSH mylist "hello" (integer) 1 > RPUSH mylist "hello" (integer) 2 > RPUSH mylist "foo" (integer) 3 > RPUSH mylist "bar" (integer) 4 > LTRIM mylist 1 -1 OK > LRANGE mylist 0 -1 1) "hello" 2) "foo" 3) "bar"

? ? ? ?快速列表

? ? ? ?Redis的底層存儲還不是一個簡單的linkedList,而是稱之為快速鏈表 ??quicklis的一個結構。

? ? ? ?

?

? ? ? ?在列表元素較少的情況下會使用一塊連續的內存存儲,這個結構是ziplist即壓縮列表

? ? ? ?它將所有的元素緊挨著一起存儲,分配的是一塊連續的內存。當數據較多的時候會改成quicklist。因為普通的鏈表需要的附加指針空間太大,會浪費空間,同時會加重內存的碎片化。

? ? ? ?例如,一個列表中存儲的只是 int 類型的數據,結構上還需要兩個額外的指針prev和next。所以Redis將鏈表和ziplist結合起來組成了quicklist。也就是將多個ziplist使用雙向指針穿起來使用。這樣既滿足了快速的插入刪除性能,又不會出現太大的空間冗余。

?

? ? ? ?hash(字典)

? ? ? ?Redis的hash相當于Java中的HashMap,是無序的。內部結構上也和HashMap是一致的,同樣是數組+鏈表的結構。

?

?

? ? ? ?但是和HashMap不一樣的是,Redis中的hash的值只能是字符串,另外他們的rehash的方式不一樣,因為Java的HashMap在散列表很大時,rehash時一個耗時的操作,需要一次性全部rehash。而Redis為了高性能,不能堵塞服務,所以采取了漸進式rehash策略。  

? ? ? ?漸進式rehash會在rehash的同時,保留新舊兩個hash結構,查詢時會同時查詢兩個hash結構,然后在后續的定時任務中以及hash操作指令中,循序漸進的將舊hash的內容一點一點的遷移到新的hash結構中。當遷移完成了,就會用新的hash結構取而代之。

? ? ? ?再簡單一點講,就是Redis在做擴容時,拷貝節點數據的過程全部平攤到后續的操作中,而不是一次性拷貝,而我們想要實現這樣的平攤,就必須對節點進行操作,例如再次插入,查找,修改,刪除時都會進行拷貝。

? ? ? ?當hash移除了最后一個元素之后,該數據結構就會被自動刪除,內存被回收。

? ? ? ?hash結構也可以用來存儲用戶信息,不同于字符串一次性要全部序列化整個對象,hash可以對用戶結構中的每個字段單獨存儲。這樣我們需要獲取用戶信息時就可以進行部分獲取。而用整個字符串的形式去保存用戶信息的話,就只能一次性全部獲取,比較浪費網絡流量。

? ? ? ?當然,hash也是有缺點的,hash的存儲結構消耗要高于單個字符串,使用hash或者字符串時,需要根據實際的情況再三權衡。  

> hset books java "think in java" //命令行的字符串如果包含空格,要用引號括起來。。。hset 字典名 鍵 值 (integer) 1 > hset books golang "concurrency in go" (integer) 1 > hset books python "python cookbook" (integer) 1 > hgetall books //entries(),key 和 value 間隔出現 1) "java" 2) "think in java" 3) "golang" 4) "concurrency in go" 5) "python" 6) "python cookbook" > hlen books (integer) 3 > hget books java "think in java" > hset books golang "learning go programming" //因為是更新操作,所以返回 0 (integer) 0 > hget books golang "learning go programming" > hmset books java "effective java" python "learning python" golang "modern golang programming" // 批量 set OK...

? ? ? ?同字符串一樣,hash結構中單個子key也可以計數,對應的指令 hincrby ,和incr基本一樣。

?

HSET myhash field 5 (integer) 1 HINCRBY myhash field 1 (integer) 6 HINCRBY myhash field -1 (integer) 5 HINCRBY myhash field -10 (integer) -5

?

? ? ??

? ? ? ?set(集合)

? ? ? ?Redis的集合相當于Java中的HashSet,它內部的鍵值對時無序且唯一的。

? ? ? ?當集合中最后一個元素移除之后,數據結構自動刪除,內存被回收。

? ? ? ?Set結構可以存儲某些特殊場景的數據,比如活動中獎用戶的ID,可以保證用一個用戶不會中獎兩次。

?

> sadd books python (integer) 1 > sadd books python # 重復 (integer) 0 > sadd books java golang (integer) 2 > smembers books // 注意順序,和插入的并不一致,因為 set 是無序的 1) "java" 2) "python" 3) "golang" > sismember books java // 查詢某個 value 是否存在,相當于 contains(o) (integer) 1 > sismember books rust (integer) 0 > scard books // 獲取長度相當于 count() (integer) 3 > spop books // 彈出一個 "java"...

? ? ? ?zset(有序列表)

? ? ? ?zset是Redis提供的最為特色的數據結構。可以把它想象成HashMap和SortedSet的結合體,一方面它是一個set,保證了內部value值得唯一性,另一方面它可以給每一個value都賦予一個score,代表這個value的排序權重,也就是說根據這個score的分數來排序。

?

? ? ? ?zset中最后一個value被移除后,數據結構會自動刪除,內存會被回收。

? ? ? ?下面是一些常用的命令

> zadd books 9.0 "think in java" (integer) 1 > zadd books 8.9 "java concurrency" (integer) 1 > zadd books 8.6 "java cookbook" (integer) 1 > zrange books 0 -1 // 按 score 排序列出,0表示第一個成員,-1表示倒數第一個成員 1) "java cookbook" 2) "java concurrency" 3) "think in java" > zrevrange books 0 -1 // 按 score 逆序列出,參數區間為排名范圍 1) "think in java" 2) "java concurrency" 3) "java cookbook" > zcard books // 統計這個列表中元素的個數 (integer) 3 > zscore books "java concurrency" // 獲取指定 value 的 score "8.9000000000000004" // 內部 score 使用 double 類型進行存儲,所以存在小數點精度問題 > zrank books "java concurrency" // 排名 (integer) 1 > zrangebyscore books 0 8.91 //根據分值區間遍歷 zset 1) "java cookbook" 2) "java concurrency" > zrangebyscore books -inf 8.91 withscores // 根據分值區間 (-∞, 8.91] 遍歷 zset,同時返回分值。inf 代表 infinite,無窮大的意思。 1) "java cookbook" 2) "8.5999999999999996" 3) "java concurrency" 4) "8.9000000000000004" > zrem books "java concurrency" // 刪除 value (integer) 1 > zrange books 0 -1 1) "java cookbook" 2) "think in java"...

? ? ? ?zset的內部排序是通過【跳躍列表】的數據結構實現的,這種數據結構比較復雜,也很特殊。

? ? ? ?因為zset要支持隨機的插入和刪除,所以不好用數組來表示。這個我們到后面再具體探討跳躍列表

?

? ? 容器型數據結構的通用規則

? ? ? ?list/set/hash/zset 這四種數據結構是容器型的數據結構,有如下兩條通用規則:

?

? ? ? ?1、create if not exists

? ? ? ? ? 如果容器不存在,那就創建一個,再進行操作。

? ? ? ?2、drop if no elements

? ? ? ? ? ?如果容器里的元素沒有了,那么立刻刪除容器,釋放內存。

?

? ? ?過期時間

? ? ? ?Redis 所有的數據結構都可以設置過期時間,時間到了,Redis會自動刪除相應的對象。需要注意的是過期是一對象為單位,比如一個hash結構的過期是整個hash對象的過期,而不是其中的某個鍵值。

? ? ? ?還有一個需要注意的是如果一個字符已經設置了過期時間,但是你調用了set方法修改他,它的過期時間就會消失。

?

?

?

?

?

轉載于:https://www.cnblogs.com/WeirdRomance/p/9511495.html

總結

以上是生活随笔為你收集整理的Redis 之(二) Redis的基本数据结构以及一些常用的操作的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。