Redis基礎(chǔ)入門(mén)篇

一拷恨、安裝Redis

體驗(yàn) Redis 需要使用 Linux 或者 Mac 環(huán)境张症,如果是 Windows 可以考慮使用虛擬機(jī)产还。主要方式有四種:

  1. 使用 Docker 安裝砖瞧。
  2. 通過(guò) Github 源碼編譯嘲恍。
  3. 直接安裝 apt-get install(Ubuntu)足画、yum install(RedHat) 或者 brew install(Mac)。
  4. 如果讀者懶于安裝操作佃牛,也可以使用網(wǎng)頁(yè)版的 Web Redis 直接體驗(yàn)淹辞。
1.1 Docker 方式
# 拉取 redis 鏡像
> docker pull redis
# 運(yùn)行 redis 容器
> docker run --name myredis -d -p6379:6379 redis
# 執(zhí)行容器中的 redis-cli,可以直接使用命令行操作 redis
> docker exec -it myredis redis-cli
1.2 Github 源碼編譯方式
# 下載源碼
> git clone --branch 2.8 --depth 1 git@github.com:antirez/redis.git
> cd redis
# 編譯
> make
> cd src
# 運(yùn)行服務(wù)器俘侠,daemonize表示在后臺(tái)運(yùn)行
> ./redis-server --daemonize yes
# 運(yùn)行命令行
> ./redis-cli
1.3 直接安裝方式
# mac
> brew install redis
# ubuntu
> apt-get install redis
# redhat
> yum install redis
# 運(yùn)行客戶(hù)端
> redis-cli

或參考菜鳥(niǎo)教程:Redis 安裝

二象缀、Redis簡(jiǎn)介

Remote Dictionary Server(Redis) 是一個(gè)由Salvatore Sanfilippo寫(xiě)的key-value存儲(chǔ)系統(tǒng)。Redis是一個(gè)開(kāi)源的使用ANSI C語(yǔ)言編寫(xiě)爷速、遵守BSD協(xié)議央星、支持網(wǎng)絡(luò)、可基于內(nèi)存亦可持久化的日志型惫东、Key-Value數(shù)據(jù)庫(kù)莉给,并提供多種語(yǔ)言的API。它通常被稱(chēng)為數(shù)據(jù)結(jié)構(gòu)服務(wù)器廉沮,因?yàn)橹担╲alue)可以是 字符串(String)颓遏、 哈希(Hash),、列表(list)滞时、 集合(sets) 和 有序集合(sorted sets)等類(lèi)型叁幢。

Redis 是完全開(kāi)源免費(fèi)的,是一個(gè)高性能的key-value數(shù)據(jù)庫(kù)漂洋。Redis 與其他 key - value 緩存產(chǎn)品有以下三個(gè)特點(diǎn):

1遥皂、Redis支持?jǐn)?shù)據(jù)的持久化力喷,可以將內(nèi)存中的數(shù)據(jù)保存在磁盤(pán)中,重啟的時(shí)候可以再次加載進(jìn)行使用演训。

2弟孟、Redis不僅僅支持簡(jiǎn)單的key-value類(lèi)型的數(shù)據(jù),同時(shí)還提供list样悟,set拂募,zset,hash等數(shù)據(jù)結(jié)構(gòu)的存儲(chǔ)窟她。

3陈症、Redis支持?jǐn)?shù)據(jù)的備份,即master-slave模式的數(shù)據(jù)備份震糖。

三录肯、Redis 優(yōu)勢(shì)

1、性能極高 – Redis能讀的速度是110000次/s,寫(xiě)的速度是81000次/s 吊说。

2论咏、豐富的數(shù)據(jù)類(lèi)型 – Redis支持二進(jìn)制案例的 Strings, Lists, Hashes, Sets 及 Ordered Sets 數(shù)據(jù)類(lèi)型操作。

3颁井、原子 – Redis的所有操作都是原子性的厅贪,意思就是要么成功執(zhí)行要么失敗完全不執(zhí)行。單個(gè)操作是原子性的雅宾。多個(gè)操作也支持事務(wù)养涮,即原子性,通過(guò)MULTI和EXEC指令包起來(lái)眉抬。

4贯吓、豐富的特性 – Redis還支持 publish/subscribe, 通知, key 過(guò)期等等特性。

四吐辙、Redis與其他key-value存儲(chǔ)有什么不同宣决?

1、Redis有著更為復(fù)雜的數(shù)據(jù)結(jié)構(gòu)并且提供對(duì)他們的原子性操作昏苏,這是一個(gè)不同于其他數(shù)據(jù)庫(kù)的進(jìn)化路徑尊沸。Redis的數(shù)據(jù)類(lèi)型都是基于基本數(shù)據(jù)結(jié)構(gòu)的同時(shí)對(duì)程序員透明,無(wú)需進(jìn)行額外的抽象贤惯。

2洼专、Redis運(yùn)行在內(nèi)存中但是可以持久化到磁盤(pán),所以在對(duì)不同數(shù)據(jù)集進(jìn)行高速讀寫(xiě)時(shí)需要權(quán)衡內(nèi)存孵构,因?yàn)閿?shù)據(jù)量不能大于硬件內(nèi)存屁商。在內(nèi)存數(shù)據(jù)庫(kù)方面的另一個(gè)優(yōu)點(diǎn)是,相比在磁盤(pán)上相同的復(fù)雜的數(shù)據(jù)結(jié)構(gòu)颈墅,在內(nèi)存中操作起來(lái)非常簡(jiǎn)單蜡镶,這樣Redis可以做很多內(nèi)部復(fù)雜性很強(qiáng)的事情雾袱。同時(shí),在磁盤(pán)格式方面他們是緊湊的以追加的方式產(chǎn)生的官还,因?yàn)樗麄儾⒉恍枰M(jìn)行隨機(jī)訪(fǎng)問(wèn)芹橡。

五、Redis 數(shù)據(jù)類(lèi)型

Redis支持五種數(shù)據(jù)類(lèi)型:String(字符串)望伦,Hash(哈希)林说,List(列表),Set(集合)及zset(sorted set:有序集合)屯伞。

Redis數(shù)據(jù)類(lèi)型
5.1 String(字符串)

String 是 Redis 最基本的類(lèi)型腿箩,你可以理解成與 Memcached 一模一樣的類(lèi)型,一個(gè) key 對(duì)應(yīng)一個(gè) value劣摇。String 類(lèi)型是二進(jìn)制安全的珠移。意思是 Redis 的 String 可以包含任何數(shù)據(jù)。比如jpg圖片或者序列化的對(duì)象末融。String 類(lèi)型是 Redis 最基本的數(shù)據(jù)類(lèi)型剑梳,String 類(lèi)型的值最大能存儲(chǔ) 512MB。

5.1.1鍵值對(duì)

實(shí)例

127.0.0.1:6379> set name "AlanChen"
OK
127.0.0.1:6379> get name
"AlanChen"
127.0.0.1:6379> exists name
(integer) 1
127.0.0.1:6379> del name
(integer) 1
127.0.0.1:6379> get name
(nil)

在以上實(shí)例中我們使用了 Redis 的 set 和 get 命令滑潘。鍵為 name,對(duì)應(yīng)的值為 AlanChen锨咙。

字符串結(jié)構(gòu)使用非常廣泛语卤,一個(gè)常見(jiàn)的用途就是緩存用戶(hù)信息。我們將用戶(hù)信息結(jié)構(gòu)體使用 JSON 序列化成字符串酪刀,然后將序列化后的字符串塞進(jìn) Redis 來(lái)緩存粹舵。同樣,取用戶(hù)信息會(huì)經(jīng)過(guò)一次反序列化的過(guò)程骂倘。

Redis 的字符串是動(dòng)態(tài)字符串眼滤,是可以修改的字符串,內(nèi)部結(jié)構(gòu)實(shí)現(xiàn)上類(lèi)似于 Java 的 ArrayList历涝,采用預(yù)分配冗余空間的方式來(lái)減少內(nèi)存的頻繁分配诅需,內(nèi)部為當(dāng)前字符串實(shí)際分配的空間 capacity 一般要高于實(shí)際字符串長(zhǎng)度 len。當(dāng)字符串長(zhǎng)度小于 1M 時(shí)荧库,擴(kuò)容都是加倍現(xiàn)有的空間堰塌,如果超過(guò) 1M,擴(kuò)容時(shí)一次只會(huì)多擴(kuò) 1M 的空間分衫。需要注意的是字符串最大長(zhǎng)度為 512M场刑。

5.1.2批量鍵值對(duì)

可以批量對(duì)多個(gè)字符串進(jìn)行讀寫(xiě),節(jié)省網(wǎng)絡(luò)耗時(shí)開(kāi)銷(xiāo)蚪战。

實(shí)例

127.0.0.1:6379> mset name1 AlanChen name2 Kyra
OK
127.0.0.1:6379> mget name1 name2
1) "AlanChen"
2) "Kyra"
5.1.3過(guò)期和 set 命令擴(kuò)展

可以對(duì) key 設(shè)置過(guò)期時(shí)間牵现,到點(diǎn)自動(dòng)刪除铐懊,這個(gè)功能常用來(lái)控制緩存的失效時(shí)間。不過(guò)這個(gè)「自動(dòng)刪除」的機(jī)制是比較復(fù)雜的瞎疼。

實(shí)例

127.0.0.1:6379> set name "AlanChen"
OK
127.0.0.1:6379> get name
"AlanChen"
127.0.0.1:6379> expire name 5     # 5s 后過(guò)期
(integer) 1

...  #wait for 5s

127.0.0.1:6379> get name
(nil)
127.0.0.1:6379> setex name 5 "AlanChen"  #5s 后過(guò)期科乎,等價(jià)于 set+expire
OK
127.0.0.1:6379> get name
"AlanChen"

... #wait for 5s

127.0.0.1:6379> get name
(nil)
127.0.0.1:6379> setnx name "AlanChen"  #如果 name 不存在就執(zhí)行 set 創(chuàng)建
(integer) 1
127.0.0.1:6379> get name
"AlanChen"
127.0.0.1:6379> setnx name "AC"   #因?yàn)?name 已經(jīng)存在,所以 set 創(chuàng)建不成功
(integer) 0
127.0.0.1:6379> get name    #沒(méi)有改變
"AlanChen"
5.1.4 計(jì)數(shù)

如果 value 值是一個(gè)整數(shù)丑慎,還可以對(duì)它進(jìn)行自增操作喜喂。自增是有范圍的,它的范圍是 signed long 的最大最小值竿裂,超過(guò)了這個(gè)值玉吁,Redis 會(huì)報(bào)錯(cuò)。

實(shí)例

127.0.0.1:6379> set age 30
OK
127.0.0.1:6379> incr age
(integer) 31
127.0.0.1:6379> incrby age 5
(integer) 36
127.0.0.1:6379> incrby age -5
(integer) 31
5.2 Hash(哈希)

Redis Hash 是一個(gè)鍵值(key=>value)對(duì)集合腻异。Redis Hash 是一個(gè) String 類(lèi)型的 field 和 value 的映射表进副,Hash 特別適合用于存儲(chǔ)對(duì)象。

實(shí)例

127.0.0.1:6379> hmset Student name "AlanChen" age 18
OK
127.0.0.1:6379> hgetall Student
1) "name"
2) "AlanChen"
3) "age"
4) "18"
127.0.0.1:6379> hget Student name
"AlanChen"
127.0.0.1:6379> hlen Student
(integer) 2

實(shí)例中我們使用了 Redis hmset, hget 命令悔常,hmset 設(shè)置了三個(gè) field=>value 對(duì), hget 獲取對(duì)應(yīng) field 對(duì)應(yīng)的 value影斑。每個(gè) Hash 可以存儲(chǔ) 232 -1 鍵值對(duì)(40多億)。

Redis 的字典相當(dāng)于 Java 語(yǔ)言里面的 HashMap机打,它是無(wú)序字典矫户。內(nèi)部實(shí)現(xiàn)結(jié)構(gòu)上同 Java 的 HashMap 也是一致的,同樣的數(shù)組 + 鏈表二維結(jié)構(gòu)残邀。第一維 hash 的數(shù)組位置碰撞時(shí)皆辽,就會(huì)將碰撞的元素使用鏈表串接起來(lái)。

不同的是芥挣,Redis 的字典的值只能是字符串驱闷,另外它們 rehash 的方式不一樣,因?yàn)?Java 的 HashMap 在字典很大時(shí)空免,rehash 是個(gè)耗時(shí)的操作空另,需要一次性全部 rehash。Redis 為了高性能蹋砚,不能堵塞服務(wù)扼菠,所以采用了漸進(jìn)式 rehash 策略。漸進(jìn)式 rehash 會(huì)在 rehash 的同時(shí)坝咐,保留新舊兩個(gè) hash 結(jié)構(gòu)娇豫,查詢(xún)時(shí)會(huì)同時(shí)查詢(xún)兩個(gè) hash 結(jié)構(gòu),然后在后續(xù)的定時(shí)任務(wù)中以及 hash 操作指令中畅厢,循序漸進(jìn)地將舊 hash 的內(nèi)容一點(diǎn)點(diǎn)遷移到新的 hash 結(jié)構(gòu)中冯痢。當(dāng)搬遷完成了,就會(huì)使用新的hash結(jié)構(gòu)取而代之。當(dāng) hash 移除了最后一個(gè)元素之后浦楣,該數(shù)據(jù)結(jié)構(gòu)自動(dòng)被刪除袖肥,內(nèi)存被回收。

hash 結(jié)構(gòu)也可以用來(lái)存儲(chǔ)用戶(hù)信息振劳,不同于字符串一次性需要全部序列化整個(gè)對(duì)象椎组,hash 可以對(duì)用戶(hù)結(jié)構(gòu)中的每個(gè)字段單獨(dú)存儲(chǔ)。這樣當(dāng)我們需要獲取用戶(hù)信息時(shí)可以進(jìn)行部分獲取历恐。而以整個(gè)字符串的形式去保存用戶(hù)信息的話(huà)就只能一次性全部讀取寸癌,這樣就會(huì)比較浪費(fèi)網(wǎng)絡(luò)流量。

hash 也有缺點(diǎn)弱贼,hash 結(jié)構(gòu)的存儲(chǔ)消耗要高于單個(gè)字符串蒸苇,到底該使用 hash 還是字符串,需要根據(jù)實(shí)際情況再三權(quán)衡吮旅。

5.3 List(列表)

Redis 列表是簡(jiǎn)單的字符串列表溪烤,按照插入順序排序。你可以添加一個(gè)元素到列表的頭部(左邊)或者尾部(右邊)庇勃。

Redis 的列表相當(dāng)于 Java 語(yǔ)言里面的 LinkedList檬嘀,注意它是鏈表而不是數(shù)組。這意味著 list 的插入和刪除操作非吃鹑拢快鸳兽,時(shí)間復(fù)雜度為 O(1),但是索引定位很慢罕拂,時(shí)間復(fù)雜度為 O(n)贸铜。當(dāng)列表彈出了最后一個(gè)元素之后,該數(shù)據(jù)結(jié)構(gòu)自動(dòng)被刪除聂受,內(nèi)存被回收。

5.3.1 基本操作

實(shí)例

127.0.0.1:6379> rpush nameList AlanChen
(integer) 1
127.0.0.1:6379> rpush nameList Kyra
(integer) 2
127.0.0.1:6379> rpush nameList AC
(integer) 3
127.0.0.1:6379> lrange nameList 0 1
1) "AlanChen"
2) "Kyra"

列表最多可存儲(chǔ) 232 - 1 元素 (4294967295, 每個(gè)列表可存儲(chǔ)40多億)烤镐。

Redis 的列表結(jié)構(gòu)常用來(lái)做異步隊(duì)列使用蛋济。將需要延后處理的任務(wù)結(jié)構(gòu)體序列化成字符串塞進(jìn) Redis 的列表,另一個(gè)線(xiàn)程從這個(gè)列表中輪詢(xún)數(shù)據(jù)進(jìn)行處理炮叶。

5.3.2 先進(jìn)先出:隊(duì)列
127.0.0.1:6379> rpush userNames AlanChen Kyra AC
(integer) 3
127.0.0.1:6379> llen userNames
(integer) 3
127.0.0.1:6379> lpop userNames
"AlanChen"
127.0.0.1:6379> lpop userNames
"Kyra"
127.0.0.1:6379> lpop userNames
"AC"
127.0.0.1:6379> lpop userNames
(nil)
5.3.3 先進(jìn)后出:棧
127.0.0.1:6379> del userNames
(integer) 0
127.0.0.1:6379> rpush userNames AlanChen Kyra AC
(integer) 3
127.0.0.1:6379> rpop userNames
"AC"
127.0.0.1:6379> rpop userNames
"Kyra"
127.0.0.1:6379> rpop userNames
"AlanChen"
127.0.0.1:6379> rpop userNames
(nil)
5.3.4 lindex 碗旅、 trim

lindex 相當(dāng)于 Java 鏈表的get(int index)方法,它需要對(duì)鏈表進(jìn)行遍歷镜悉,性能隨著參數(shù)index增大而變差祟辟。

ltrim 跟的兩個(gè)參數(shù)start_index和end_index定義了一個(gè)區(qū)間,在這個(gè)區(qū)間內(nèi)的值侣肄,ltrim 要保留旧困,區(qū)間之外統(tǒng)統(tǒng)砍掉。我們可以通過(guò)ltrim來(lái)實(shí)現(xiàn)一個(gè)定長(zhǎng)的鏈表,這一點(diǎn)非常有用吼具。

index 可以為負(fù)數(shù)僚纷,index=-1表示倒數(shù)第一個(gè)元素,同樣index=-2表示倒數(shù)第二個(gè)元素拗盒。

> rpush books python java golang
(integer) 3
> lindex books 1  # O(n) 慎用
"java"
> lrange books 0 -1  # 獲取所有元素怖竭,O(n) 慎用
1) "python"
2) "java"
3) "golang"
> ltrim books 1 -1 # O(n) 慎用
OK
> lrange books 0 -1
1) "java"
2) "golang"
> ltrim books 1 0 # 這其實(shí)是清空了整個(gè)列表,因?yàn)閰^(qū)間范圍長(zhǎng)度為負(fù)
OK
> llen books
(integer) 0
5.3.5 linked list & quickest

如果再深入一點(diǎn)陡蝇,你會(huì)發(fā)現(xiàn) Redis 底層存儲(chǔ)的還不是一個(gè)簡(jiǎn)單的 linkedlist痊臭,而是稱(chēng)之為快速鏈表 quicklist 的一個(gè)結(jié)構(gòu)。

首先在列表元素較少的情況下會(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)空間蹋凝,而且會(huì)加重內(nèi)存的碎片化。比如這個(gè)列表里存的只是 int 類(lèi)型的數(shù)據(jù)总棵,結(jié)構(gòu)上還需要兩個(gè)額外的指針 prev 和 next 鳍寂。所以 Redis 將鏈表和 ziplist 結(jié)合起來(lái)組成了 quicklist。也就是將多個(gè) ziplist 使用雙向指針串起來(lái)使用情龄。這樣既滿(mǎn)足了快速的插入刪除性能迄汛,又不會(huì)出現(xiàn)太大的空間冗余。

5.4 Set(集合)

Redis 的 Set 是 String 類(lèi)型的無(wú)序集合骤视。集合是通過(guò)哈希表實(shí)現(xiàn)的鞍爱,所以添加,刪除专酗,查找的復(fù)雜度都是 O(1)睹逃。

集合中最大的成員數(shù)為 232 - 1(4294967295, 每個(gè)集合可存儲(chǔ)40多億個(gè)成員)。

Redis 的集合相當(dāng)于 Java 語(yǔ)言里面的 HashSet祷肯,它內(nèi)部的鍵值對(duì)是無(wú)序的唯一的沉填。它的內(nèi)部實(shí)現(xiàn)相當(dāng)于一個(gè)特殊的字典,字典中所有的 value 都是一個(gè)值NULL佑笋。當(dāng)集合中最后一個(gè)元素移除之后翼闹,數(shù)據(jù)結(jié)構(gòu)自動(dòng)刪除,內(nèi)存被回收蒋纬。

Set 結(jié)構(gòu)可以用來(lái)存儲(chǔ)活動(dòng)中獎(jiǎng)的用戶(hù) ID猎荠,因?yàn)橛腥ブ毓δ芗崛酰梢员WC同一個(gè)用戶(hù)不會(huì)中獎(jiǎng)兩次。

實(shí)例

127.0.0.1:6379> sadd nameSet AlanChen
(integer) 1
127.0.0.1:6379> sadd nameSet AlanChen   #重復(fù)
(integer) 0
127.0.0.1:6379> sadd nameSet AC Kyra
(integer) 2
127.0.0.1:6379> members nameSet  # 注意順序,和插入的并不一致法牲,因?yàn)?set 是無(wú)序的
1) "AC"
2) "AlanChen"
3) "Kyra"
127.0.0.1:6379> sismember nameSet AC  # 查詢(xún)某個(gè) value 是否存在史汗,相當(dāng)于 contains(o)
(integer) 1
127.0.0.1:6379> sismember nameSet Tom
(integer) 0
127.0.0.1:6379> scare nameSet  # 獲取長(zhǎng)度相當(dāng)于 count()
(integer) 3
127.0.0.1:6379> stop nameSet  # 彈出一個(gè)
"Kyra"
5.5 zset(sorted set:有序集合)

Redis zset 和 Set 一樣也是String類(lèi)型元素的集合,且不允許重復(fù)的成員拒垃。不同的是每個(gè)元素都會(huì)關(guān)聯(lián)一個(gè)double類(lèi)型的分?jǐn)?shù)停撞。Redis正是通過(guò)分?jǐn)?shù)來(lái)為集合中的成員進(jìn)行從小到大的排序。zset的成員是唯一的,但分?jǐn)?shù)(score)卻可以重復(fù)悼瓮。

zset 可能是 Redis 提供的最為特色的數(shù)據(jù)結(jié)構(gòu)戈毒,它也是在面試中面試官最?lèi)?ài)問(wèn)的數(shù)據(jù)結(jié)構(gòu)。它類(lèi)似于 Java 的 SortedSet 和 HashMap 的結(jié)合體横堡,一方面它是一個(gè) set埋市,保證了內(nèi)部 value 的唯一性,另一方面它可以給每個(gè) value 賦予一個(gè) score命贴,代表這個(gè) value 的排序權(quán)重道宅。它的內(nèi)部實(shí)現(xiàn)用的是一種叫做「跳躍列表」的數(shù)據(jù)結(jié)構(gòu)。

zset 中最后一個(gè) value 被移除后胸蛛,數(shù)據(jù)結(jié)構(gòu)自動(dòng)刪除污茵,內(nèi)存被回收。

zset 可以用來(lái)存粉絲列表葬项,value 值是粉絲的用戶(hù) ID泞当,score 是關(guān)注時(shí)間。我們可以對(duì)粉絲列表按關(guān)注時(shí)間進(jìn)行排序民珍。

zset 還可以用來(lái)存儲(chǔ)學(xué)生的成績(jī)襟士,value 值是學(xué)生的 ID,score 是他的考試成績(jī)嚷量。我們可以對(duì)成績(jī)按分?jǐn)?shù)進(jìn)行排序就可以得到他的名次陋桂。

實(shí)例

> 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 排序列出,參數(shù)區(qū)間為排名范圍
1) "java cookbook"
2) "java concurrency"
3) "think in java"
> zrevrange books 0 -1  # 按 score 逆序列出蝶溶,參數(shù)區(qū)間為排名范圍
1) "think in java"
2) "java concurrency"
3) "java cookbook"
> zcard books  # 相當(dāng)于 count()
(integer) 3
> zscore books "java concurrency"  # 獲取指定 value 的 score
"8.9000000000000004"  # 內(nèi)部 score 使用 double 類(lèi)型進(jìn)行存儲(chǔ)嗜历,所以存在小數(shù)點(diǎn)精度問(wèn)題
> zrank books "java concurrency"  # 排名
(integer) 1
> zrangebyscore books 0 8.91  # 根據(jù)分值區(qū)間遍歷 zset
1) "java cookbook"
2) "java concurrency"
> zrangebyscore books -inf 8.91 withscores # 根據(jù)分值區(qū)間 (-∞, 8.91] 遍歷 zset,同時(shí)返回分值身坐。inf 代表 infinite,無(wú)窮大的意思落包。
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跳表

六部蛇、容器型數(shù)據(jù)結(jié)構(gòu)的通用規(guī)則

list/set/hash/zset 這四種數(shù)據(jù)結(jié)構(gòu)是容器型數(shù)據(jù)結(jié)構(gòu),它們共享下面兩條通用規(guī)則:
1咐蝇、create if not exists
如果容器不存在涯鲁,那就創(chuàng)建一個(gè),再進(jìn)行操作。比如 rpush 操作剛開(kāi)始是沒(méi)有列表的抹腿,Redis 就會(huì)自動(dòng)創(chuàng)建一個(gè)岛请,然后再 rpush 進(jìn)去新元素。

2警绩、drop if no elements
如果容器里元素沒(méi)有了崇败,那么立即刪除元素,釋放內(nèi)存肩祥。這意味著 lpop 操作到最后一個(gè)元素后室,列表就消失了。

七混狠、過(guò)期時(shí)間

Redis 所有的數(shù)據(jù)結(jié)構(gòu)都可以設(shè)置過(guò)期時(shí)間岸霹,時(shí)間到了,Redis 會(huì)自動(dòng)刪除相應(yīng)的對(duì)象将饺。需要注意的是過(guò)期是以對(duì)象為單位贡避,比如一個(gè) hash 結(jié)構(gòu)的過(guò)期是整個(gè) hash 對(duì)象的過(guò)期,而不是其中的某個(gè)子 key予弧。

還有一個(gè)需要特別注意的地方是如果一個(gè)字符串已經(jīng)設(shè)置了過(guò)期時(shí)間刮吧,然后你調(diào)用了 set 方法修改了它,它的過(guò)期時(shí)間會(huì)消失桌肴。

127.0.0.1:6379> set name alanchen
OK
127.0.0.1:6379> tel name  #查看過(guò)期的剩余時(shí)間 -1 表示不過(guò)期
(integer) -1
127.0.0.1:6379> expire name 20   # 設(shè)置過(guò)期時(shí)間為20s
(integer) 1
127.0.0.1:6379> tel name   #查看過(guò)期的剩余時(shí)間
(integer) 16
127.0.0.1:6379> set name AC  # 重新設(shè)置name
OK
127.0.0.1:6379> tel name   # name的過(guò)期時(shí)間消失
(integer) -1

八皇筛、各個(gè)數(shù)據(jù)類(lèi)型應(yīng)用場(chǎng)景

類(lèi)型 簡(jiǎn)介 特性 場(chǎng)景
String(字符串) 二進(jìn)制安全 可以包含任何數(shù)據(jù),比如jpg圖片或者序列化的對(duì)象,一個(gè)鍵最大能存儲(chǔ)512M -
Hash(字典) 鍵值對(duì)集合,即編程語(yǔ)言中的Map類(lèi)型 適合存儲(chǔ)對(duì)象,并且可以像數(shù)據(jù)庫(kù)中update一個(gè)屬性一樣只修改某一項(xiàng)屬性值(Memcached中需要取出整個(gè)字符串反序列化成對(duì)象修改完再序列化存回去) 存儲(chǔ)、讀取坠七、修改用戶(hù)屬性
List(列表) 鏈表(雙向鏈表) 增刪快,提供了操作某一段元素的API 1水醋、最新消息排行等功能(比如朋友圈的時(shí)間線(xiàn)) 2、消息隊(duì)列
Set(集合) 哈希表實(shí)現(xiàn),元素不重復(fù) 1彪置、添加拄踪、刪除,查找的復(fù)雜度都是O(1) 2、為集合提供了求交集拳魁、并集惶桐、差集等操作 1、共同好友 2潘懊、利用唯一性,統(tǒng)計(jì)訪(fǎng)問(wèn)網(wǎng)站的所有獨(dú)立ip 3姚糊、好友推薦時(shí),根據(jù)tag求交集,大于某個(gè)閾值就可以推薦
Sorted Set(有序集合) 將Set中的元素增加一個(gè)權(quán)重參數(shù)score,元素按score有序排列 數(shù)據(jù)插入集合時(shí),已經(jīng)進(jìn)行天然排序 1、排行榜 2授舟、帶權(quán)重的消息隊(duì)列

九救恨、Redis & 多個(gè)數(shù)據(jù)庫(kù)

Redis支持多個(gè)數(shù)據(jù)庫(kù),并且每個(gè)數(shù)據(jù)庫(kù)的數(shù)據(jù)是隔離的不能共享释树,并且基于單機(jī)才有肠槽,如果是集群就沒(méi)有數(shù)據(jù)庫(kù)的概念擎淤。

Redis是一個(gè)字典結(jié)構(gòu)的存儲(chǔ)服務(wù)器,而實(shí)際上一個(gè)Redis實(shí)例提供了多個(gè)用來(lái)存儲(chǔ)數(shù)據(jù)的字典秸仙,客戶(hù)端可以指定將數(shù)據(jù)存儲(chǔ)在哪個(gè)字典中嘴拢。這與我們熟知的在一個(gè)關(guān)系數(shù)據(jù)庫(kù)實(shí)例中可以創(chuàng)建多個(gè)數(shù)據(jù)庫(kù)類(lèi)似,所以可以將其中的每個(gè)字典都理解成一個(gè)獨(dú)立的數(shù)據(jù)庫(kù)寂纪。

每個(gè)數(shù)據(jù)庫(kù)對(duì)外都是一個(gè)從0開(kāi)始的遞增數(shù)字命名席吴,Redis默認(rèn)支持16個(gè)數(shù)據(jù)庫(kù)(可以通過(guò)配置文件支持更多,無(wú)上限)弊攘,可以通過(guò)配置databases來(lái)修改這一數(shù)字抢腐。客戶(hù)端與Redis建立連接后會(huì)自動(dòng)選擇0號(hào)數(shù)據(jù)庫(kù)襟交,不過(guò)可以隨時(shí)使用SELECT命令更換數(shù)據(jù)庫(kù)迈倍,如要選擇1號(hào)數(shù)據(jù)庫(kù):

redis> SELECT 1
OK
redis [1] > GET foo
(nil)

然而這些以數(shù)字命名的數(shù)據(jù)庫(kù)又與我們理解的數(shù)據(jù)庫(kù)有所區(qū)別。首先Redis不支持自定義數(shù)據(jù)庫(kù)的名字捣域,每個(gè)數(shù)據(jù)庫(kù)都以編號(hào)命名啼染,開(kāi)發(fā)者必須自己記錄哪些數(shù)據(jù)庫(kù)存儲(chǔ)了哪些數(shù)據(jù)。另外Redis也不支持為每個(gè)數(shù)據(jù)庫(kù)設(shè)置不同的訪(fǎng)問(wèn)密碼焕梅,所以一個(gè)客戶(hù)端要么可以訪(fǎng)問(wèn)全部數(shù)據(jù)庫(kù)迹鹅,要么連一個(gè)數(shù)據(jù)庫(kù)也沒(méi)有權(quán)限訪(fǎng)問(wèn)。最重要的一點(diǎn)是多個(gè)數(shù)據(jù)庫(kù)之間并不是完全隔離的贞言,比如FLUSHALL命令可以清空一個(gè)Redis實(shí)例中所有數(shù)據(jù)庫(kù)中的數(shù)據(jù)斜棚。

綜上所述,這些數(shù)據(jù)庫(kù)更像是一種命名空間该窗,而不適宜存儲(chǔ)不同應(yīng)用程序的數(shù)據(jù)弟蚀。比如可以使用0號(hào)數(shù)據(jù)庫(kù)存儲(chǔ)某個(gè)應(yīng)用生產(chǎn)環(huán)境中的數(shù)據(jù),使用1號(hào)數(shù)據(jù)庫(kù)存儲(chǔ)測(cè)試環(huán)境中的數(shù)據(jù)酗失,但不適宜使用0號(hào)數(shù)據(jù)庫(kù)存儲(chǔ)A應(yīng)用的數(shù)據(jù)而使用1號(hào)數(shù)據(jù)庫(kù)B應(yīng)用的數(shù)據(jù)义钉,不同的應(yīng)用應(yīng)該使用不同的Redis實(shí)例存儲(chǔ)數(shù)據(jù)。由于Redis非常輕量級(jí)规肴,一個(gè)空Redis實(shí)例占用的內(nèi)在只有1M左右捶闸,所以不用擔(dān)心多個(gè)Redis實(shí)例會(huì)額外占用很多內(nèi)存。

十拖刃、Redis 發(fā)布訂閱

Redis 發(fā)布訂閱

十一删壮、Redis 事務(wù)

Redis 事務(wù)可以一次執(zhí)行多個(gè)命令, 并且?guī)в幸韵氯齻€(gè)重要的保證:
1兑牡、批量操作在發(fā)送 EXEC 命令前被放入隊(duì)列緩存央碟。
2、收到 EXEC 命令后進(jìn)入事務(wù)執(zhí)行发绢,事務(wù)中任意命令執(zhí)行失敗硬耍,其余的命令依然被執(zhí)行。
3边酒、在事務(wù)執(zhí)行過(guò)程经柴,其他客戶(hù)端提交的命令請(qǐng)求不會(huì)插入到事務(wù)執(zhí)行命令序列中。

一個(gè)事務(wù)從開(kāi)始到執(zhí)行會(huì)經(jīng)歷以下三個(gè)階段:開(kāi)始事務(wù)墩朦、命令入隊(duì)坯认、執(zhí)行事務(wù)。

實(shí)例
以下是一個(gè)事務(wù)的例子氓涣, 它先以 multi 開(kāi)始一個(gè)事務(wù)牛哺, 然后將多個(gè)命令入隊(duì)到事務(wù)中, 最后由 EXEC 命令觸發(fā)事務(wù)劳吠, 一并執(zhí)行事務(wù)中的所有命令:

127.0.0.1:6379> multi
OK
127.0.0.1:6379> set user-name "AlanChen"
QUEUED
127.0.0.1:6379> get user-name
QUEUED
127.0.0.1:6379> hmset User name "AC" age 10
QUEUED
127.0.0.1:6379> sadd names "Tom"
QUEUED
127.0.0.1:6379> sadd names "Kyra"
QUEUED
127.0.0.1:6379> exec
1) OK
2) "AlanChen"
3) OK
4) (integer) 1
5) (integer) 1
127.0.0.1:6379> get user-name
"AlanChen"
127.0.0.1:6379> smembers names
1) "Tom"
2) "Kyra"

資料來(lái)源:

Redis 教程 菜鳥(niǎo)教程

《Redis深度歷險(xiǎn):核心原理與應(yīng)用實(shí)踐》

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末引润,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子痒玩,更是在濱河造成了極大的恐慌淳附,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,826評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蠢古,死亡現(xiàn)場(chǎng)離奇詭異奴曙,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)草讶,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,968評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)洽糟,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人堕战,你說(shuō)我怎么就攤上這事坤溃。” “怎么了践啄?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,234評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵浇雹,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我屿讽,道長(zhǎng)昭灵,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,562評(píng)論 1 293
  • 正文 為了忘掉前任伐谈,我火速辦了婚禮烂完,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘诵棵。我一直安慰自己抠蚣,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,611評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布履澳。 她就那樣靜靜地躺著嘶窄,像睡著了一般怀跛。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上柄冲,一...
    開(kāi)封第一講書(shū)人閱讀 51,482評(píng)論 1 302
  • 那天吻谋,我揣著相機(jī)與錄音,去河邊找鬼现横。 笑死漓拾,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的戒祠。 我是一名探鬼主播骇两,決...
    沈念sama閱讀 40,271評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼姜盈!你這毒婦竟也來(lái)了低千?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,166評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤馏颂,失蹤者是張志新(化名)和其女友劉穎栋操,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體饱亮,經(jīng)...
    沈念sama閱讀 45,608評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡矾芙,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,814評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了近上。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片剔宪。...
    茶點(diǎn)故事閱讀 39,926評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖壹无,靈堂內(nèi)的尸體忽然破棺而出葱绒,到底是詐尸還是另有隱情,我是刑警寧澤斗锭,帶...
    沈念sama閱讀 35,644評(píng)論 5 346
  • 正文 年R本政府宣布地淀,位于F島的核電站,受9級(jí)特大地震影響岖是,放射性物質(zhì)發(fā)生泄漏帮毁。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,249評(píng)論 3 329
  • 文/蒙蒙 一豺撑、第九天 我趴在偏房一處隱蔽的房頂上張望烈疚。 院中可真熱鬧,春花似錦聪轿、人聲如沸爷肝。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,866評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)灯抛。三九已至金赦,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間对嚼,已是汗流浹背素邪。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,991評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留猪半,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,063評(píng)論 3 370
  • 正文 我出身青樓偷线,卻偏偏與公主長(zhǎng)得像磨确,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子声邦,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,871評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • NOSQL類(lèi)型簡(jiǎn)介鍵值對(duì):會(huì)使用到一個(gè)哈希表乏奥,表中有一個(gè)特定的鍵和一個(gè)指針指向特定的數(shù)據(jù),如redis亥曹,volde...
    MicoCube閱讀 3,981評(píng)論 2 27
  • 數(shù)據(jù)結(jié)構(gòu) 字符串 :可以是字符串邓了、數(shù)字、整形浮點(diǎn)數(shù)媳瞪、二進(jìn)制(圖片/音頻/視頻)骗炉,最大不超過(guò)512M。 設(shè)值命令 s...
    易碼當(dāng)先閱讀 224評(píng)論 0 1
  • 本文為筆者對(duì)在學(xué)習(xí)Redis過(guò)程中所收集資料的一個(gè)總結(jié)蛇受,目的是為了以后方便回顧相關(guān)的知識(shí),大部分為非原創(chuàng)內(nèi)容句葵。特此...
    EakonZhao閱讀 14,433評(píng)論 0 9
  • Redis 是一個(gè)鍵值對(duì)數(shù)據(jù)庫(kù)(key-value DB),數(shù)據(jù)庫(kù)的值可以是字符串兢仰、集合乍丈、列表等多種類(lèi)型的對(duì)象,而...
    吳昂_ff2d閱讀 3,195評(píng)論 0 5
  • Ubuntu下安裝redis 安裝redis 在 Ubuntu 系統(tǒng)安裝 Redi 可以使用以下命令: 啟動(dòng) Re...
    riverstation閱讀 933評(píng)論 0 0