redis最基礎的入門教程
-
- Redis最基礎入門教程
- 簡介
- Redis最基礎入門教程
- Redis 簡介
- Redis 優勢
- Redis與其他key-value儲存有什麼不同?
- 字串(Strings)
- 雜湊(Hash)
- 列表(List)
- 集合(Sets)
- 有序集合(sorted sets)
- 釋出訊息/訂閱頻道
- 結語
Redis最基礎入門教程
還記得第一次面試來也的時候,面試官問我,“會MongoDB嗎?”,“不會”;“知道redis嗎?”,“知道,但是沒用過”,“emm……”
簡介
在面對高併發的資料讀取的時候,當連表查詢的需求不是那麼的強烈,此時,非關係型資料庫得到了高速的發展。其中,非關係型資料庫中的鍵值資料庫中的redis便是我們今天需要講的內容。其中redis為了保證效率,會將資料儲存在記憶體中(當然redis會週期性的把更新的資料寫入磁碟或者把修改操作寫入追加的記錄檔案)。
Redis亦被稱為資料機構伺服器,因為它的值(Value)可以是字串(String),雜湊(Hash),列表(List),集合(Sets)和有序集合(sorted sets)。
Redis 線上測試:http://try.redis.io/
下面是一段來自於菜鳥教程的介紹
Redis 簡介
Redis 是完全開源免費的,遵守BSD協議,是一個高效能的key-value資料庫。
Redis 與其他 key - value 快取產品有以下三個特點:
- Redis支援資料的持久化,可以將記憶體中的資料儲存在磁碟中,重啟的時候可以再次載入進行使用。
- Redis不僅僅支援簡單的key-value型別的資料,同時還提供list,set,zset,hash等資料結構的儲存。
- Redis支援資料的備份,即master-slave模式的資料備份。
Redis 優勢
- 效能極高 – Redis能讀的速度是110000次/s,寫的速度是81000次/s 。
- 豐富的資料型別 – Redis支援二進位制案例的 Strings, Lists, Hashes, Sets 及 Ordered Sets 資料型別操作。
- 原子 – Redis的所有操作都是原子性的,意思就是要麼成功執行要麼失敗完全不執行。單個操作是原子性的。多個操作也支援事務,即原子性,通過MULTI和EXEC指令包起來。
- 豐富的特性 – Redis還支援 publish/subscribe, 通知, key 過期等等特性。
Redis與其他key-value儲存有什麼不同?
- Redis有著更為複雜的資料結構並且提供對他們的原子性操作,這是一個不同於其他資料庫的進化路徑。Redis的資料型別都是基於基本資料結構的同時對程式設計師透明,無需進行額外的抽象。
- Redis執行在記憶體中但是可以持久化到磁碟,所以在對不同資料集進行高速讀寫時需要權衡記憶體,因為資料量不能大於硬體記憶體。在記憶體資料庫方面的另一個優點是,相比在磁碟上相同的複雜的資料結構,在記憶體中操作起來非常簡單,這樣Redis可以做很多內部複雜性很強的事情。同時,在磁碟格式方面他們是緊湊的以追加的方式產生的,因為他們並不需要進行隨機訪問。
redis怎麼安裝,我就不做介紹了,因為不同的系統安裝方式不一樣。如果不想安裝話可以使用線上的redis環境。不過還是推薦一下,因為接下來會使用python去實現一些操作。其中redis資料庫的視覺化可以使用redis-desktop-manager。命令列操作使用redis-cli。
接下來我將通過不同的資料結構來介紹redis的操作。
字串(Strings)
字串(Strings)是Redis的基本資料結構之一,由key和value組成。我們可以這樣類比成程式語言的變數:keya代表變數名,value代表變數值。
檢視所有的key的命令
keys *
建立字串
set key value
如果value中有空格,則需要使用**""**將value包起來。如:
set x "xxx xxx xxx"
讀取字串
get key
如果獲取一個不存在的key,則會返回nil。
修改key裡面的值
-
進行修改
下面這個命令key存在則修改,不存在則建立
set key 新的值
如果我們不希望set的命令覆蓋舊值怎麼辦?在使用"NX"引數即可。這樣,當key存在時,使用set key value NX
並不能覆蓋原來的值。
set key value NX
-
進行增添
如果我們想在value的末尾加上一些字串,使用append命令。(當key不存在的時候,則會建立key)當然,如果如果值有空格的話,和set的處理方法一樣。
append key value
-
數字進行修改
注意下面的命令只針對於value為數字的情況,否則就會報錯。
# 讓key裡面的數字加1 incr key # 減1 decr key # 加n incrby key n # 減n decrby key n
刪除
如果key存在則放回1,否則返回0
del key
程式碼實現
下面是使用python對以上的所有命令進行實現(任何程式語言都差不多)
import redis
client = redis.Redis()
# 獲得所有的key
keys = client.keys()
# 建立字串
client.set("thisKey","thatValue")
# 獲得value
value = client.get("thisKey")
# 不覆蓋修改
client.set("thisKey","way",nx=True)
# 增添
client.append("thisKey","newMSg")
# 對數字就行修改
client.set("num",1)
client.incr("num")
client.incrby("num",10)
client.decr("num")
client.decrby("num",4)
# 進行刪除操作
client.delete("thisKey")
雜湊(Hash)
在前面我們介紹了字串型別的Redis儲存方案,這個時候我們可以想一想如果我需要儲存10w個人的分數,右需要儲存10w個人的密碼(假如這樣做),那麼我們需要多少多少個key?20w個key!!那麼我們的key又該怎樣分配呢(注意:key不能重複)?我們是不是得這樣:使用者名稱_score,使用者名稱_pwd,在使用者名稱後面加上不同的型別來代表不同的資料。那麼在redis如何解決這些問題呢?使用雜湊表!!關於雜湊表的資料結構我們可以看看這篇
Redis hash 是一個string型別的field和value的對映表(key任然為key),hash特別適合用於儲存物件,每個 hash 可以儲存 232 - 1 鍵值對(43多億)。使用Hash表不僅能夠減少Redis中key的個數,還能優化儲存空間,佔用的記憶體要比字串小很多。
下面是redis的儲存示意圖:
新增資料:
一次新增一個鍵值對資料:
hset key field value
一次新增多個鍵值對資料:
hmset key field1 value1 [field2 value2 ]
當然如果我們不想對已經存在的field進行修改
hsetnx key field value
獲得資料:
獲得一個欄位的值:
hget key field
獲得多個欄位的值:
hmget key field1 [field2]
獲得所有的欄位名和值
hgetall key
當然我們也可以分別獲得所有的field獲得value
hvals key
hkeys key
判斷是否存在某欄位
HEXISTS key field
如果欄位存在則返回1,如果不存在則返回0
獲得雜湊表中欄位的數量
hlen key
接下來我就不再使用python實現這些東西了,會更多的來介紹各種結構的特點。如果想了解更多的指令可以看菜鳥教程
列表(List)
列表是一種很神奇的結構,可以把列表成一根水管,資料從可以從一邊進,然後從另外一邊出來(當然,那一邊即可以進又可以出,只不過順序不同而已)。那麼這種結構有什麼用處呢?我們可以以發訊息為例。發訊息我們需要保證訊息到達的順序,那麼我們是不是就可以使用列表了呢?例如:傳送訊息從左邊進,接受訊息從右邊得到。下面介紹幾個簡單的指令:
插入資料
l代表left(左),r代表right(右)
從左邊插入資料
lpush key value
從右邊插入資料
rpush key value
獲得列表的長度
注意下面的第一個l並不是代表left,而是代表list
llen key
檢視資料
lrang key 開始索引 結束索引
索引從最左邊開始編號,意思就是最後一個lpush的資料的索引是0(將列表想成一個小水管就行)。如果開始索引和結束索引一樣,就返回索引位置的值。那麼如果從右邊開始呢?使用“負索引”即可。其中**-1**代表最右邊的資料。-2代表最右邊的第二個資料。
彈出資料
彈出最左邊的資料
lpop key
彈出最右邊的資料
rpop key
彈出資料和檢視資料的差別在於,彈出資料的同時也會將資料進行刪除。
集合(Sets)
這個集合和數學中的集合有著差不多的概念。怎麼說呢?在redis的集合中,資料是無序的,不能重複。
新增資料:
s代表集合(set)
sadd key value1 value2 value3……
獲得集合中元素的數量
如果不存在這個集合則返回0
scard key
從集合中獲取資料
spop key count
前面我們說道,集合是無序的,所以spop的獲取也是無序的。(獲得資料後會將資料刪除)count代表獲取幾條資料。
這個是獲得集合的所有資料(並不會刪除資料)。不過這個命令在生產環境中最好不要使用,因為資料量大的話你的伺服器可能就炸了。
SMEMBERS key
判斷資料是否存在
sismember key value
存在返回1,否則返回0
刪除資料
srem key value1 value2……
下面便是數學上面的知識了
取交集
sinter key1 key2……
取並集
sunion key1 key2……
取差集
sdiff key1 key2……
有序集合(sorted sets)
有序集合,顧名思義就是集合裡面的資料是有序的。那麼它有什麼含義呢?我們想象一下,在一個高併發的場景中,資料是一直更新的,如果我們將資料存到資料庫中,如果需要實時獲取排名的話,那麼肯定會對資料的效能造成很大的影響。畢竟資料量越大,排序時間也就越緩慢。和集合不同的是,有序集合的元素會關聯一個double型別的分數,其中元素不能重複,但是分數可以重複。
新增資料
zadd key score1 member1 [score2 member2]
前面說過,score必須為double型別,所以如果輸入非double則會報錯。
修改資料
修改資料可以使用zadd進行修改資料的分數,同時可以新增NX引數
zadd key NX sorce member
還可以使用zincrby對資料對資料的分數進行加減操作
ZINCRBY key 改變數 member
其中改變數既可以為正數也可以為負數。如果member不存在則會建立,member的分數和改變數一致。
獲取資料
基於評分範圍內的排序
- 從小到大排序
zrangebyscore 有序集合名 評分下限 評分上限 [withsores limit 切片開始位置 結果數量]
- 從大到小排序
zrevrangebyscore 有序集合名 評分下限 評分上限 [withsores limit 切片開始位置 結果數量]
其中使用括號括起來的代表可以省略,如果withsores省略代表只返回值,不返回評分。省略“limit 切片開始位置 結果數量”代表不對結果進行切片。
基於位置的排序
-
從小到大排序
位置是從零開始的
zrange 有序集合名 開始位置(含) 結束位置 (含)[withsores]
-
從大到小排序
zrevrange 有序集合名 開始位置(含) 結束位置 (含)[withsores]
獲得排名
zrank 有序集合名 值
zrevrank 有序集合名 值
zrank 和 zrevrank的區別在於,zrank排名是從0開始的,評分越小則排名越靠近0,評分最小的值排名為0。而zrevrank則是評分越大則越靠近0。相同點在於如果值不存在則返回None。
獲得一個值的評分
zscore 有序集合名 值
如果一個值不存在則返回None。
檢視某個評分範圍內的值有多少
zcount 有序集合名 評分下限 評分上限
釋出訊息/訂閱頻道
我們來說一個場景,還是以前面的發訊息場景為例,如果服務端的訊息在進行更新,那麼我們如何更新客戶端的資訊呢?按照前面的方法,我們只有使用輪詢查詢的方式,按照一定的時間(比如說1s)檢查redis,看訊息是否發生改變,如果訊息發生了改變,則客戶端進行更新,那麼接下來就會有以下的問題:
- 不停地檢查redis,耗費系統資源
- 使用輪詢查詢,訊息會有延時
- 即使1s(輪詢的時間)中傳送了5條訊息,那麼客戶端只會發生一次改變。
這個時候我們就是可以使用redis的“釋出/訂閱”模式實現訊息通訊。
- 釋出:訊息的釋出者
- 訂閱:訊息的接受者,可以為1個也可以為多個
釋出訊息
publish 頻道名 資訊
訂閱頻道
subscribe 頻道名1 頻道名2……
其中會返回3條訊息:第一條是資訊的型別,第二條是頻道名,第三條是被髮布的內容。其中需要注意,只能接受目前的訊息,新加入的訂閱是沒辦法接受到以前的訂閱的。
結語
以上便是redis的一個很簡單的入門教程。只介紹了redis的簡單使用和一些基本操作,至於redis命令中更復雜的指令,百度或者google就行了。對於redis,我覺得我們(作為一個學生)應該關注的是redis為什麼能夠如此優秀?裡面用了什麼資料結構,以及如何能夠將redis應用到高併發的場景中,怎麼實現多伺服器資料的儲存以及備份問題。