Redis基礎與持久化

Redis介紹

軟件說明

Redis是一款開源的,ANSI C語言編寫的,高級鍵值(key-value)緩存和支持永久存儲NoSQL數據庫產品。
Redis採用內存(In-Memory)數據集(DataSet) 。
支持多種數據類型。
運行於大多數POSIX系統,如Linux、*BSD、OS X等。
做者: Salvatore Sanfilipporedis

軟件特性

1)透明性:分佈式系統對用戶來講是透明的,一個分佈式系統在用戶面前的表現就像一個傳統的單處理機分時系統,可以讓用戶沒必要了解內部結構就可使用。
2)擴展性:分佈式系統的最大特色就是可擴展性,他能夠根據需求的增長而擴展,能夠經過橫向擴展使集羣的總體性能獲得線性提高,也能夠經過縱向擴展單臺服務器的性能使服務器集羣的性能獲得提高。
3)可靠性:分佈式系統不容許單點失效的問題存在,它的基本思想是:若是一臺服務器壞了,其餘服務器接替它的工做,具備持續服務的特性。
4)高性能:高性能是人們設計分佈式系統的一個初衷,若是創建了一個透明,靈活,可靠的分佈式系統,但他運行起來像蝸牛同樣慢,那這個系統就是失敗的。數據庫

軟件功能

1)高速讀寫
2)數據類型豐富
3)支持持久化
4)多種內存分配及回收策略
5)支持事物
6)消息隊列、消息訂閱
7)支持高可用
8)支持分佈式分片集羣vim

Redis安裝部署

#下載
[root@db01 src]# wget http://download.redis.io/releases/redis-3.2.12.tar.gz
#解壓
[root@db01 src]# tar xf redis-3.2.12.tar.gz
#移動到指定目錄
[root@db01 src]# mv redis-3.2.12 /application/
#作軟連接
[root@db01 src]# ln -s /application/redis-3.2.12 /application/redis
#進入redis目錄
[root@db01 src]# cd /application/redis
#編譯
[root@db01 redis]# make
#添加環境變量
[root@db01 redis]# vim /etc/profile.d/redis.sh
export PATH="/application/redis/src:$PATH"
#啓動redis
[root@db01 redis]# src/redis-server &
#鏈接redis
[root@db01 redis]# redis-cli
#退出redis
127.0.0.1:6379> quit
#關閉redis鏈接
[root@db01 redis]# redis-cli
127.0.0.1:6379> shutdown

基本配置

#建立redis工做目錄
[root@db01 redis]# mkdir -p /etc/redis/6379
#建立redis配置文件
[root@db01 redis]# vim /etc/redis/6379/redis.conf
daemonize yes   //守護進程模式啓動
port 6379       //端口
logfile /etc/redis/6379/redis.log   //日誌文件位置
dir /etc/redis/6379     //持久化數據文件存儲位置
dbfilename dump.rdb     //RDB持久化數據文件名稱
#指定配置文件啓動redis
[root@db01 redis]# redis-server /etc/redis/6379/redis.conf

基本操做

#鏈接redis
[root@db01 redis]# redis-cli
#設置鍵值對
127.0.0.1:6379> set foo bar
OK
#取出值
127.0.0.1:6379> get foo
"bar"

安全配置

protected-mode: 禁止protected-mode yes/no(保護模式,是否只運行本地訪問)
bind: 指定監聽緩存

# 添加到配置文件
[root@db01 redis]# vim /etc/redis/6379/redis.conf
bind 127.0.0.1 10.0.0.51
requirepass  123

auth {password}: 在redis-cli中使用,進行認證安全

#不加認證,報錯
[root@db01 redis]# redis-cli
127.0.0.1:6379> set name zhangsan
(error) NOAUTH Authentication required.
#鏈接方式1
[root@db01 redis]# redis-cli
127.0.0.1:6379> AUTH zls
127.0.0.1:6379> set name zhangsan
OK
#鏈接方式2
[root@db01 redis]# redis-cli -a zls
127.0.0.1:6379> set name lisi
OK

在線查看和修改配置

#查看配置文件中的監聽地址
127.0.0.1:6379> CONFIG GET bind
1) "bind"
2) "127.0.0.1 10.0.0.51"

#查看dir
127.0.0.1:6379> CONFIG GET dir
1) "dir"
2) "/etc/redis/6379"

#查看全部配置
127.0.0.1:6379> CONFIG GET *

#修改配置,即時生效
127.0.0.1:6379> CONFIG SET requirepass 123
OK

#測試修改後鏈接
[root@db01 redis]# redis-cli -a 123
127.0.0.1:6379> set age 18
OK

#查看配置文件
[root@db01 redis]# cat /etc/redis/6379/redis.conf
daemonize yes
port 6379
logfile /etc/redis/6379/redis.log
dir /etc/redis/6379
dbfilename dump.rdb
bind 127.0.0.1 10.0.0.51
requirepass  zls        //能夠看出,配置文件中是沒有改變的,只要redis不重啓,密碼就是新改的

Redis持久化

什麼是持久化?
持久化::就是將內存中的數據,寫入到磁盤上,並永久存在的.bash

RDB持久化介紹

能夠在指定的時間間隔內生成數據集的時間點快照(point-in-time snapshot)
RDB持久化優勢:
1) RDB是一種表示某個即時點的Redis數據的緊湊文件.RDB文件適合用於備份.例如,能夠每小時歸檔最近24小時的RDB文件,天天保存近30天的RDB快照.
這容許你很容易的恢復不一樣版本的數據集以容災.
2) RDB很是適合用於災難恢復,做爲一個緊湊的單一文件,能夠被傳輸到遠程的數據中心.
3) RDB最大化了Redis的性能,由於Redis父進程持久化是惟一須要作的是啓動(fork)一個子進程,因爲子進程完成全部剩餘工做.父進程實例不須要執行像磁盤IO這樣的操做.
RDB持久化缺點:
1) 當你須要Redis中止工做,(例如停電)是最小化數據丟失,RDB可能不太好.你能夠配置不經過的保存點(save point)來保存RDB文件(例如, 至少5分鐘和對數進行100次後,可是你能夠有多個保存點.然而,你一般每隔5分鐘或更久建立一個RDB快照,因此一旦Redis由於任何緣由沒有正確關閉或中止工做,你就得作好最近幾分鐘數據丟失的準備了.
2) RDB須要進程調用fork()子進程來持久化到磁盤. 若是數據集很大的haul,fork()比較好使, 結果就是, 當數據集很是大而且CPU性能不夠強大的化,Redis會中止服務客戶端幾毫秒甚至一秒. AOF也須要fork(),可是你能夠調整多久評率重寫日誌而不會有損(trade-off)持久(durability).
RDB持久化優缺點總結
優勢:速度快,適合於用做備份,主從複製也是基於RDB持久化功能實現的。
缺點:會有數據丟失、致使服務中止幾秒
服務器

RDB持久化核心配置參數

#編輯配置文件
[root@db01 redis]# vim /etc/redis/6379/redis.conf
#持久化數據文件存儲位置
dir /etc/redis/6379
#rdb持久化數據文件名
dbfilename dump.rdb
#900秒(15分鐘)內有1個更改
save 900 1
#300秒(5分鐘)內有10個更改
save 300 10
#60秒(1分鐘)內有10000個更改
save 60 10000

AOF 持久化介紹

AOF(append only file)只追加文件,記錄服務器執行的全部寫操做命令,並在服務器啓動時,經過從新執行這些命令來還原數據集。 AOF 文件中的命令所有以 Redis 協議的格式來保存,新命令會被追加到文件的末尾。
AOF 持久化優勢:
1)使用AOF Redis會更具備可持久性(durable):你能夠有不少不一樣的fsync策略:沒有fsync,每秒fsync,每次請求時fsync。使用默認的每秒fsync策略,寫性能也仍然很不錯(fsync是由後臺線程完成的,主線程繼續努力地執行寫請求),即使你也就僅僅只損失一秒鐘的寫數據。
2)AOF日誌是一個追加文件,因此不須要定位,在斷電時也沒有損壞問題。即便因爲某種緣由文件末尾是一個寫到一半的命令(磁盤滿或者其餘緣由),redis-check-aof工具也能夠很輕易的修復。
3)當AOF文件變得很大時,Redis會自動在後臺進行重寫。重寫是絕對安全的,由於Redis繼續往舊的文件中追加,使用建立當前數據集所需的最小操做集合來建立一個全新的文件,一旦第二個文件建立完畢,Redis就會切換這兩個文件,並開始往新文件追加。
4)AOF文件裏面包含一個接一個的操做,以易於理解和解析的格式存儲。你也能夠輕易的導出一個AOF文件。例如,即便你不當心錯誤地使用FLUSHALL命令清空一切,若是此時並無執行重寫,你仍然能夠保存你的數據集,你只要中止服務器,刪除最後一條命令,而後重啓Redis就能夠。
AOF 持久化缺點
1)對一樣的數據集,AOF文件一般要大於等價的RDB文件。
2)AOF可能比RDB慢,這取決於準確的fsync策略。一般fsync設置爲每秒一次的話性能仍然很高,若是關閉fsync,即便在很高的負載下也和RDB同樣的快。不過,即便在很大的寫負載狀況下,RDB仍是能提供能好的最大延遲保證。
3)在過去,咱們經歷了一些針對特殊命令(例如,像BRPOPLPUSH這樣的阻塞命令)的罕見bug,致使在數據加載時沒法恢復到保存時的樣子。這些bug很罕見,咱們也在測試套件中進行了測試,自動隨機創造複雜的數據集,而後加載它們以檢查一切是否正常,可是,這類bug幾乎不可能出如今RDB持久化中。爲了說得更清楚一點:Redis AOF是經過遞增地更新一個已經存在的狀態,像MySQL或者MongoDB同樣,而RDB快照是一次又一次地從頭開始創造一切,概念上更健壯。可是,1)要注意Redis每次重寫AOF時都是以當前數據集中的真實數據從頭開始,相對於一直追加的AOF文件(或者一次重寫讀取老的AOF文件而不是讀內存中的數據)對bug的免疫力更強。2)咱們尚未收到一份用戶在真實世界中檢測到崩潰的報告。
AOF持久化優缺點總結
優勢:能夠最大程度保證數據不丟失
缺點:日誌記錄量級比較大微信

AOF持久化核心配置參數

#修改配置文件
[root@db01 redis]# vim /etc/redis/6379/redis.conf
#是否打開AOF日誌功能
appendonly yes/no

#每一條命令都當即同步到AOF
appendfsync always
#每秒寫一次
appendfsync everysec
#寫入工做交給操做系統,由操做系統判斷緩衝區大小,統一寫入到AOF
appendfsync no

RDB 和 AOF,應該用哪個?
1)通常來講,若是想達到足以媲美 PostgreSQL 的數據安全性, 你應該同時使用兩種持久化功能。app

2)若是你很是關心你的數據,但仍然能夠承受數分鐘之內的數據丟失, 那麼你能夠只使用 RDB 持久化。運維

3)有不少用戶單獨使用AOF,可是咱們並不鼓勵這樣,由於時常進行RDB快照很是方便於數據庫備份,啓動速度也較之快,還避免了AOF引擎的bug。

4)我的感觸:在企業中,一般都使用RDB來作持久化,由於通常redis是在作MySQL的緩存,就算緩存數據丟失,真實的數據仍是在MySQL中,之因此用緩存是爲了速度,性能而考慮,因此仍是建議使用RDB持久化,相對來講會好一些,除非專門用redis來作一個key:value的數據庫,並且數據很重要,那麼能夠考慮使用AOF

注意:基於這些緣由,未來咱們可能會統一AOF和RDB爲一種單一的持久化模型(長遠計劃)。

RDB快照的工做方式

1)默認狀況下,Redis保存數據集快照到磁盤,名爲dump.rdb的二進制文件。你能夠設置讓Redis在N秒內至少有M次數據集改動時保存數據集,或者你也能夠手動調用SAVE或者BGSAVE命令。

2)在上文中咱們已經在配置文件中作過對應的配置:
例如,這個配置會讓Redis在每一個60秒內至少有1000次鍵改動時自動轉儲數據集到磁盤:
save 60 1000

3)當 Redis 須要保存 dump.rdb 文件時,服務器執行如下操做:

Redis 調用 fork() ,同時擁有父進程和子進程。
子進程將數據集寫入到一個臨時的 RDB 文件中。當子進程完成對新 RDB 文件的寫入時, Redis 用新RDB 文件替換原來的 RDB 文件,並刪除舊的 RDB 文件。
4)這種方式使得 Redis 能夠從寫時複製機制中獲益。

AOF重寫功能介紹

1)由於 AOF 的運做方式是不斷地將命令追加到文件的末尾,因此隨着寫入命令的不斷增長, AOF 文件的體積也變得愈來愈大。舉個例子,若是你對一個計數器調用了 100 次 INCR ,那麼僅僅是爲了保存這個計數器的當前值, AOF 文件就須要使用 100 條記錄。然而在實際上,只使用一條 SET 命令已經足以保存計數器的當前值了,其他 99 條記錄實際上都是多餘的。

2)爲了處理這種狀況, Redis 支持一種有趣的特性:能夠在不斷服務客戶端的狀況下,對 AOF 文件進行重建。執行 BGREWRITEAOF 命令, Redis 將生產一個新的 AOF 文件,這個文件包含重建當前數據集所需的最少命令。

AOF 有多持久

你能夠配置 Redis 多久纔將數據 fsync 到磁盤一次。
有三個選項:

每次有新命令追加到 AOF 文件時就執行一次 fsync :很是慢,也很是安全。
每秒 fsync 一次:足夠快(和使用 RDB 持久化差很少,)而且在故障時只會丟失1秒鐘的數據。
從不 fsync :將數據交給操做系統來處理。更快,也更不安全的選擇。
推薦(而且也是默認)的措施爲每秒 fsync 一次,這種 fsync 策略能夠兼顧速度和安全性。

老是 fsync 的策略在實際使用中很是慢,即便在 Redis2.0 對相關的程序進行了改進以後還是如此。頻繁調用 fsync 註定了這種策略不可能快得起來。

RDB 和 AOF 之間的相互做用

1)在版本號大於等於 2.4 的 Redis 中, BGSAVE 執行的過程當中,不能夠執行 BGRWRITEAOF 。 反過來講,在 BGRWRITEAOF 執行的過程當中,也不能夠執行 BGSAVE 。
2)這能夠防止兩個 Redis 後臺進程同時對磁盤進行大量的 I/O 操做。若是 BGSAVE 正在執行,而且用戶顯示地調用 BGRWRITEAOF 命令,那麼服務器將向用戶回覆一個 OK 狀態,並告知用戶, BGRWRITEAOF 已經被預約執行; 一旦 BGSAVE 執行完畢, BGRWRITEAOF 就會正式開始。
3)當 Redis 啓動時,若是 RDB 持久化和 AOF 持久化都被打開了,那麼程序會優先使用 AOF 文件來恢復數據集,由於 AOF 文件所保存的數據一般是最完整的。

備份Redis數據

1)Redis 對於數據備份是很是友好的,由於你能夠在服務器運行的時候對 RDB 文件進行復制: RDB 文件一旦被建立,就不會進行任何修改。

2)當服務器要建立一個新的 RDB 文件時,它先將文件的內容保存在一個臨時文件裏面,當臨時文件寫入完畢時,程序才使用臨時文件替換原來的 RDB 文件。

3)這也就是說,不管什麼時候, 複製 RDB 文件都是絕對安全的。

如下是咱們的建議:
1)建立一個按期任務(cron job), 每小時將一個 RDB 文件備份到一個文件夾, 而且天天將一個 RDB 文件備份到另外一個文件夾。

2)確保快照的備份都帶有相應的日期和時間信息, 每次執行按期任務腳本時, 使用 find 命令來刪除過時的快照: 好比說, 你能夠保留最近 48 小時內的每小時快照, 還能夠保留最近一兩個月的每日快照。

3)至少天天一次, 將 RDB 備份到你的數據中心以外, 或者至少是備份到你運行 Redis 服務器的物理機器以外。

RDB持久化高級配置

#編輯配置文件
[root@db01 redis]# vim /etc/redis/6379/redis.conf
#後臺備份進程出錯時,主進程停不中止寫入? 主進程不中止容易形成數據不一致
stop-writes-on-bgsave-error yes
#導出的rdb文件是否壓縮 若是rdb的大小很大的話建議這麼作
rdbcompression yes 
#導入rbd恢復時數據時,要不要檢驗rdb的完整性 驗證版本是否是一致
rdbchecksum yes

AOF持久化高級配置

#編輯配置文件
[root@db01 redis]# vim /etc/redis/6379/redis.conf
#正在導出rdb快照的過程當中,要不要中止同步aof
no-appendfsync-on-rewrite yes/no
#aof文件大小比起上次重寫時的大小,增加率100%時重寫,缺點:業務開始的時候,會重複重寫屢次
auto-aof-rewrite-percentage 100
#aof文件,至少超過64M時,重寫
auto-aof-rewrite-min-size 64mb

Redis數據類型

String: 字符串類型
Hash: 哈希類型
List: 列表類型
Set: 集合類型
Sorted set: 順序集合類型

通用操做

#查看全部的key
127.0.0.1:6379> KEYS *
1) "age"
2) "name"
#判斷key是否存在
127.0.0.1:6379> EXISTS name
(integer) 1
#變動key名
127.0.0.1:6379> RENAME age nianling
#查看key的類型
127.0.0.1:6379> type name
string
#刪除key
127.0.0.1:6379> del name
(integer) 1
#以秒爲單位設置生存時間
127.0.0.1:6379> EXPIRE name 10
(integer) 1
#以毫秒爲單位設置生存時間
127.0.0.1:6379> PEXPIRE name 10000
(integer) 1
#取消剩餘生存時間
127.0.0.1:6379> PERSIST name
(integer) 1

strings(字符)類型操做

應用場景:
常規計數:微博數、粉絲數、直播平臺

#設置key
127.0.0.1:6379> set name zls
OK
#設置多個key
127.0.0.1:6379> mset name zls age 18 sex m
OK
#設置值、取值同時進行
127.0.0.1:6379> GETSET name zls
(nil)
127.0.0.1:6379> GETSET name zls
"zls"
#設置值同時設置生存時間
127.0.0.1:6379> set name zls ex 10
OK
#數量遞歸增長
127.0.0.1:6379> incr num
(integer) 1
#指定增長數值
127.0.0.1:6379> incrby num 2
(integer) 8
#數量遞減
127.0.0.1:6379> DECR num
(integer) -1
#指定遞減數
127.0.0.1:6379> DECRBY num 2
(integer) -3
#浮點增長
127.0.0.1:6379> incrbyfloat float 0.6
"0.6"

#刪除已有key
127.0.0.1:6379> DEL num

#追加(若該鍵不存在,則建立)
127.0.0.1:6379> APPEND name bgx
(integer) 6
#查看追加內容
127.0.0.1:6379> get name
"zlsbgx"
#修改第N個字符串
127.0.0.1:6379> SETRANGE name 3 a
(integer) 6
#查看結果
127.0.0.1:6379> get name
"zlsagx"

#獲取key值
127.0.0.1:6379> get name
"zls"
#查看string類型的長度
127.0.0.1:6379> STRLEN name
(integer) 6
#查看指定長度的string類型
127.0.0.1:6379> GETRANGE name  0 4
"zlsag"
#以秒查詢key剩餘生存時間
127.0.0.1:6379> ttl name
(integer) 8
#以毫秒查詢key剩餘生存時間
127.0.0.1:6379> pttl name
(integer) 44016
#獲取多個key值
127.0.0.1:6379> mget name age sex
1) "zls"
2) "18"
3) "m"

應用場景實現

#粉絲數量增長,每點一次關注,都執行如下命令一次
127.0.0.1:6379> incr num
(integer) 1
#取消關注則執行如下命令一次
127.0.0.1:6379> DECR num
(integer) -1
#顯示粉絲數量
127.0.0.1:6379> get num
"6"
#暗箱操做,刷粉絲
127.0.0.1:6379> incrby num 10000
(integer) 10006

hash(字典)類型操做

應用場景:
存儲部分變動的數據,如用戶信息,商品信息等。
最接近表結構的一種類型。
增:

#建立car的price值
127.0.0.1:6379> hset car price 500
(integer) 1
#建立car的name值
127.0.0.1:6379> hset car name BMW
(integer) 1
#建立car的date值
127.0.0.1:6379> hset car date 1982
(integer) 1
#設置多個哈希key(相似於MySQL的一個表中的一行數據)
127.0.0.1:6379> hmset teacher name zls age 18 sex m
OK
127.0.0.1:6379> hmset teacher name bgx age 80 sex f
OK

刪:

#刪除hash類型中的一個值
127.0.0.1:6379> HDEL teacher name
(integer) 1
#刪除整個hash類型key
127.0.0.1:6379> DEL teacher
(integer) 1

#修改hash類型值 增長1
127.0.0.1:6379> hincrby myhash num 1
(integer) 1

#獲取car的name值
127.0.0.1:6379> hget car name
"BMW"
#獲取key的所有value和值(運維經常使用)
127.0.0.1:6379> hgetall car
1) "price"
2) "500"
3) "name"
4) "BMW"
5) "date"
6) "1982"
#獲取key中部分值
127.0.0.1:6379> HMGET teacher name sex
1) "zls"
2) "m"

List(列表)類型操做

應用場景:

消息隊列系統

好比sina微博:在redis中咱們的最新微博ID使用了常駐緩存,這是一直更新的。
可是作了限制不能超過5000個ID,所以獲取ID的函數會一隻詢問redis。
系統不會像傳統方式那樣「刷新」緩存,redis實例中的信息永遠是一致的。
SQL數據庫(或是硬盤上的其餘類型數據)只是在用戶須要獲取「很遠」的數據時纔會被觸發,而主頁或第一個評論頁是不會麻煩到硬盤上的數據庫了。
增:

#將一個值或者多個值插入列表的表頭(若key不存在,則添加key並依次添加)
127.0.0.1:6379> lpush list zls
(integer) 1
127.0.0.1:6379> lpush list bgx
(integer) 2
127.0.0.1:6379> lpush list oldboy
(integer) 3
127.0.0.1:6379> lpush list alex
(integer) 4
#一行添加
127.0.0.1:6379> lpush teacher zls bgx oldboy alex
(integer) 4
#追加一個value值,若key不存在,則不建立
127.0.0.1:6379> LPUSHX teacher1 zls
(integer) 0
#在bgx前面添加zls
127.0.0.1:6379> linsert teacher before bgx zls
(integer) 6
#在尾部添加key
127.0.0.1:6379> rpush teacher wang5
(integer) 7
#將teacher的尾部元素彈出,再插入到teacher1的頭部
127.0.0.1:6379> rpoplpush teacher teacher1
"wang5"
#查看一個列表內有多少行
127.0.0.1:6379> llen list
(integer) 4

刪:

#刪除key
127.0.0.1:6379> del teacher
(integer) 1
#從頭部開始找,按前後順序,值爲a的元素,刪除數量爲2個,若存在第3個,則不刪除
127.0.0.1:6379> lrem teacher 2 zls
(integer) 2
#從頭開始,索引爲0,1,2的3個元素,其他所有刪除改
127.0.0.1:6379> ltrim teacher 0 2
OK

改:

#從頭開始, 將索引爲1的元素值,設置爲新值 e,若索引越界,則返回錯誤信息
127.0.0.1:6379> lset teacher 1 test
OK
#將 teacher 中的尾部元素移到其頭部
127.0.0.1:6379> rpoplpush teacher teacher
"oldboy"

#列表頭部彈出,彈一行少一行
127.0.0.1:6379> lpop teacher
"zls"
#列表尾部
127.0.0.1:6379> rpop teacher
"wang5"
#查詢索引(頭部開始)
127.0.0.1:6379> lindex list 0
"bgx"
#查詢索引(尾部第一個)
127.0.0.1:6379> lindex list -1
"alex"
#範圍查詢索引
127.0.0.1:6379> lrange list 0 1
1) "bgx"
2) "oldboy"

微博 微信朋友圈的場景實現:

#發朋友圈
127.0.0.1:6379> LPUSH wechat "monday,bgx is a bad man"
(integer) 1
127.0.0.1:6379> LPUSH wechat "Tuesday,zls is a nice boy"
(integer) 2
127.0.0.1:6379> LPUSH wechat "Wednesday,alex is a loser"
(integer) 3

#查看朋友圈內容
127.0.0.1:6379> LRANGE wechat 0 -1
1) "Wednesday,zls is a nice boy"
2) "Tuesday,zls is a nice boy"
3) "monday,zls is a nice boy"

Set(集合) 類型操做

應用場景:
在微博應用中,能夠將一個用戶全部的關注人存在一個集合中,將其全部粉絲存在一個集合。Redis還爲集合提供了求交集、並集、差集等操做,能夠很是方便的實現如共同關注、共同喜愛、二度好友等功能,對上面的全部集合操做,你還可使用不一樣的命令選擇將結果返回給客戶端仍是存集到一個新的集合中。

增:

#若key不存在,建立該鍵及與其關聯的set,依次插入bgx、lidao、xiaomimei若key存在,則插入value中,若bgx在zls_fans中已經存在,則插入了lidao和xiaomimei兩個新成員。
127.0.0.1:6379> sadd zls_fans bgx lidao xiaomimei
(integer) 3

#尾部的b被移出,事實上b並非以前插入的第一個或最後一個成員
127.0.0.1:6379> spop zls_fans
"bgx"
#若值不存在, 移出存在的值,並返回剩餘值得數量
127.0.0.1:6379> SREM zls_fans lidao oldboy alex
(integer) 1

#將小迷妹從 zls_fans 移到 bgx_fans
127.0.0.1:6379> SMOVE zls_fans bgx_fans xiaomimei
(integer) 1

#判斷xiaomimei是否已經存在,返回值爲 1 表示存在
127.0.0.1:6379> SISMEMBER zls_fans xiaomimei
(integer) 0
127.0.0.1:6379> SISMEMBER bgx_fans xiaomimei
(integer) 1
#查看set中的內容
127.0.0.1:6379> SMEMBERS zls_fans
1) "xiaomimei"
2) "bgx"
3) "lidao"
#獲取Set 集合中元素的數量
127.0.0.1:6379> scard zls_fans
(integer) 0
127.0.0.1:6379> scard bgx_fans
(integer) 1
#隨機的返回某一成員
127.0.0.1:6379> srandmember bgx_fans
"xiaomimei"

#建立三個集合
127.0.0.1:6379> sadd zls_fans bgx lidao xiaomimei
(integer) 3
127.0.0.1:6379> sadd bgx_fans zls lidao xiaomimei
(integer) 2
127.0.0.1:6379> sadd lidao_fans 0
(integer) 1

#1和2獲得一個結果,拿這個集合和3比較,得到每一個獨有的值
127.0.0.1:6379> sdiff zls_fans bgx_fans lidao_fans
1) "bgx"
#3個集和比較,獲取獨有的元素,並存入diffkey 關聯的Set中
127.0.0.1:6379> sdiffstore diffkey zls_fans bgx_fans lidao_fans
(integer) 1
#得到3個集合中都有的元素
127.0.0.1:6379> sinter zls_fans bgx_fans lidao_fans
(empty list or set)    //由於這裏沒有交集,因此返回一個空集合
#把交集存入interkey 關聯的Set中
127.0.0.1:6379> sinterstore interkey bgx_fans lidao_fans
(integer) 0  // 由於這裏沒有交集,因此存入的值爲0
#獲取3個集合中的成員的並集
127.0.0.1:6379> sunion zls_fans bgx_fans lidao_fans
1) "bgx"
2) "xiaomimei"
3) "zls"
4) "lidao"
5) "0"
#把並集存入unionkey 關聯的Set中
127.0.0.1:6379> sunionstore unionkey zls_fans bgx_fans lidao_fans
(integer) 5

Sorted-Set(有序集合)類型操做

應用場景:

排行榜應用,取TOP N操做
這個需求與上面需求的不一樣之處在於,前面操做以時間爲權重,這個是以某個條件爲權重,好比按頂的次數排序,這時候就須要咱們的sorted set出馬了,將你要排序的值設置成sorted set的score,將具體的數據設置成相應的value,每次只須要執行一條ZADD命令便可。

增:

#添加兩個分數分別是 2 和 3 的兩個成員
127.0.0.1:6379> zadd myzset 2 "two" 3 "three"
(integer) 2

#刪除多個成員變量,返回刪除的數量
127.0.0.1:6379> zrem myzset one two
(integer) 1

#將成員 one 的分數增長 2,並返回該成員更新後的分數
127.0.0.1:6379> zincrby myzset 2 one
"2"

#返回全部成員和分數,不加WITHSCORES,只返回成員
127.0.0.1:6379> zrange myzset 0 -1 WITHSCORES
1) "one"
2) "2"
3) "three"
4) "3"
#獲取成員one在Sorted-Set中的位置索引值。0表示第一個位置
127.0.0.1:6379> zrank myzset one
(integer) 0
#獲取 myzset 鍵中成員的數量
127.0.0.1:6379> zcard myzset
(integer) 2
#獲取分數知足表達式 1 <= score <= 2 的成員的數量
127.0.0.1:6379> zcount myzset 1 2
(integer) 1  
#獲取成員 three 的分數 
127.0.0.1:6379> zscore myzset three
"3"
#獲取分數知足表達式 1 < score <= 2 的成員
127.0.0.1:6379> zrangebyscore myzset  1 2
1) "one"
#-inf 表示第一個成員,+inf最後一個成員
#limit限制關鍵字
#2  3  是索引號
zrangebyscore myzset -inf +inf limit 2 3  返回索引是2和3的成員
#刪除分數 1<= score <= 2 的成員,並返回實際刪除的數量
127.0.0.1:6379> zremrangebyscore myzset 1 2
(integer) 1
#刪除位置索引知足表達式 0 <= rank <= 1 的成員
127.0.0.1:6379> zremrangebyrank myzset 0 1
(integer) 1
#按位置索引從高到低,獲取全部成員和分數
127.0.0.1:6379> zrevrange myzset 0 -1 WITHSCORES
#原始成員:位置索引從小到大
      one  0
      two  1
#執行順序:把索引反轉
      位置索引:從大到小
      one 1
      two 0
#輸出結果: 
       two
       one
#獲取位置索引,爲1,2,3的成員
127.0.0.1:6379> zrevrange myzset 1 3
(empty list or set)
#相反的順序:從高到低的順序
#獲取分數 3>=score>=0的成員並以相反的順序輸出
127.0.0.1:6379> zrevrangebyscore myzset 3 0
(empty list or set)
#獲取索引是1和2的成員,並反轉位置索引
127.0.0.1:6379> zrevrangebyscore myzset 4 0 limit 1 2
(empty list or set)
相關文章
相關標籤/搜索