Redis資料庫筆記

來源:互聯網
上載者:User

標籤:關聯式資料庫   新浪微博   遊戲伺服器   做什麼   互連網應用   

1.redis是什嗎?
  redis(REmote DIctionary Server)是一種使用C語言開發的NOSQL,即非關聯式資料庫;Redis是一個操作資料結構的語言工具是一種記憶體資料庫或者資料結構伺服器,將資料直接儲存在記憶體中,但又提供了持久化支援;是一種索引值對資料庫,儲存的是索引值對資料,相當於儲存了一個變數及變數的值;以字典結構儲存資料,並允許其他應用通過TCP協議讀寫字典中的內容;是Memcached快取服務器的替代者。
2.redis可以用來做什嗎?
  資料庫、隊列、緩衝系統,新浪微博大量使用了redis.Key-Value Store 是當下比較流行的話題,尤其在構建諸如搜尋引擎、IM、P2P、遊戲伺服器、SNS等大型互連網應用以及提供雲端運算服務的時候,保證系統在海量資料環境下的高效能、高可靠性、高擴充性、高可用性、低成本.
適用場合:
a.取最新 N 個資料的操作
b.熱門排行榜應用,取 TOP N 操作
c.需要精準設定到期時間的應用
d.計數器應用 INCR DECR
e.Uniq 操作,擷取某段時間所有資料排重值
f.即時系統,反垃圾系統 SET集合
g.Pub/Sub 構建即時訊息系統
h.構建隊列系統
i.緩衝
3.redis與memcashed的優劣
 在效能上Redis是單執行緒模式,而Memcached支援多線程,所以在多核伺服器上後者的效能更高一些。然而,前面已經介紹過,Redis的效能已經足夠優異,在絕大部分場合下其效能都不會成為瓶頸。所以在使用時更應該關心的是二者在功能上的區別,如果需要用到進階的資料類型或是持久化等功能,Redis將會是Memcached很好的替代品。
 作為緩衝系統,Redis還可以限定資料佔用的最大記憶體空間,在資料達到空間限制後可以按照一定的規則自動淘汰不需要的鍵。
 除此之外,Redis的清單類型鍵可以用來實現隊列,並且支援阻塞式讀取,可以很容易地實現一個高效能的優先順序隊列。同時在更高層面上,Redis還支援“發布/訂閱”的訊息模式,可以基於此構建聊天室等系統。
4.redis安裝與啟動
redis官方只提供了POSIX系統版的redis版本,http://download.redis.io/redis-stable.tar.gz可以下載最新的穩定版。redis沒有其它外部依賴。在window中安裝,需要使用cygwin環境。
伺服器端啟動:
>redis-server         :直接啟動,預設連接埠6379
>redis-server --port 6380       :指定連接埠上啟動
>redis-server redis.conf        :啟動時使用設定檔初始化,redis.conf 位於安裝檔案中。
>redis-cli   SHUTDOWN           :安全終止redis伺服器
用戶端啟動:
>redis-cli  -h 127.0.0.1 -p 6379     :用戶端啟動並串連伺服器
5.redis命令執行的傳回值(5種)
a.狀態回複  回複命令的執行狀態,如set和PING的回複
b.錯誤回複  命令執行錯誤,回複形式為:(error)...
c.整數回複  redis雖然沒有整數類型,但提供了一組用於字元整數操作的命令,這些命令的回複返回整數,如INCR,DBSIZE ,回複形式為:(integer) n
e.字串回複  當請求一個字串類型鍵的索引值或一個其他類型鍵中的某個元素時就會得到一個字串回複,如GET,回複形式為:“...”
f.多行字串回複  如KEYS命令,回複時會添加字串行號。
6.redis的多資料庫
如mysql可以建立多個資料庫一樣,redis可以建立的資料庫個數通過redis.conf中的databases來配置,預設為16個,資料庫號從0-15,不支援自訂資料庫名稱。用戶端redis-cli與Redis建立串連後會自動選擇0號資料庫,不過可以隨時使用SELECT n命令更換資料庫。
7.常用命令
KEYS glob_pattern     :查詢當前資料庫中所有的鍵glob_pattern : ?,*,[],\x
EXISTS key   :判斷一個鍵是否存在,存在返回1,否則0
DEL key [key …] :刪除一個或多個鍵
TYPE key  :返回key鍵的資料類型
EXPIRE key time  :設定一個鍵的到期時間
PERSIST key  :移除該鍵的到期時間
MOVE key n  :將當前資料庫的key鍵移動到n號資料庫
SELECT n  :選擇n號資料庫作為當前資料庫,0-15
RANDOMKEY  :隨機返回當前資料庫的一個鍵
RENAME key newkey :重新命名一個key
  伺服器相關命令
PING   :測試連接是否存活
ECHO "..."  :在命令列列印一行內容
QUIT   :退出串連
DBSIZE   :返回當前資料庫中鍵的個數
INFO   :返回伺服器的資訊和統計
MONITOR   :即時轉儲收到的請求
CONFIG GET dir  :擷取伺服器配置資訊
FLUSHDB   :刪除當前資料庫中的所有key
FLUSHALL  :刪除所有資料庫中的key

8.redis的5大資料(鍵)類型
字串(string)、散列(hash)、列表(list)、集合(set)、有序集合(zset),每一個鍵都是這5種資料類型中的一種,根據鍵的建立方式不同來決定屬於哪種類型。Redis不支援資料類型嵌套。列表(list)、集合(set)、有序集合鍵只能儲存字串類型的資料。
a.字串類型:一個字串類型鍵允許儲存的資料的最大容量是512MB。字串類型是其他4種資料類型的基礎,其他資料類型和字串類型的差別從某種角度來說只是組織字串的形式不同。例如,清單類型是以列表的形式組織字串,而集合類型是以集合的形式組織字串。
命令:
對字串的操作
SET key value  :建立字串變數並賦值
GET key   :當鍵不存在時會返回空結果。
SETNX key value  :如果鍵key不存在,則設定該鍵;存在則返回0,不進行設定
SETEX key time value  :設定鍵key的同時指定該鍵的有效期間為time,可以使用TTL查看
SETRANGE key start jointvalue :將鍵key從第8個字元起,替換為jointvalue
APPEND key value  :向一個字串的尾部增加值
STRLEN key   :擷取字串長度
MSET key value [key value …] :同時設定多個鍵的值
MGET key [key …]  :同時擷取多個鍵的值
MSETNX key value [key value …] :當失敗時,一個鍵也不會被設定
GETSET key value  :設定並返回key的值
GETRANGE key start end  :返回key字串中從start到end的子竄
對實數字串的操作
INCR key   :遞增數字,對非數字遞增將返回錯誤
INCRBY key increment  :按指定數字增加
DECR key  :遞減數字
DECRBY key decrement :按指定數字遞減
INCRBYFLOAT key increment :對浮點數加
對字串進行位操作的4大命令(是記憶體意義上的二進位位的操作)
GETBIT key offset  :擷取字串中總第offset位的二進位值
SETBIT key offset value  :設定字串中總第offset位的二進位值
BITCOUNT key [m] [n]  :統一字串中從第m位元組到第n位元組中的位元中的1的個數
BITOP operation destkey key [key …]:BITOP命令可以對多個字串類型鍵進行位元運算,並將結果儲存在destkey參數指定的鍵中。BITOP命令支援的運算操作有AND、OR、XOR 和NOT
b.散列類型(python中的字典類型)
散列類型(hash)的索引值是一種字典結構,其儲存了欄位(field)和欄位值的映射,但欄位值只能是字串,不支援其他資料類型,一個散列類型鍵可以包含
至多232-1個欄位。
賦值與取值:
HSET key field value   :設定該鍵指定欄位的值
HGET key field    :擷取該鍵指定欄位的值
HMSET key field value [field value …] :設定該鍵多個欄位的值
HMGET key field [field …]  :擷取該鍵多個欄位的值
HGETALL key    :擷取該鍵所有欄位名及域值
HKEYS key    :擷取該鍵所有欄位名
HVALS key    :擷取該鍵所有欄位的值
HLEN key    :擷取該鍵欄位的個數
     
HEXISTS key field   :判斷該鍵中是否存在某個欄位
HSETNX key field value   :該欄位不存在時賦值
HINCRBY key field increment  :對數字字串加increment  
HDEL key field [field …]  :刪除欄位

c.清單類型(雙端鏈表)
向列表兩端壓入和彈出元素
LPUSH key value [value …]  :向列表左端添加元素
RPUSH key value [value …]  :向列表右端添加元素
LPOP key    :由列表左端彈出元素
RPOP key    :由列表右端彈出元素
LLEN key    :擷取列表中元素的個數
LRANGE key start stop   :獲得列表片段,-1,最後一個元素,-2倒數第二個元素
LREM key count value   :當count>會從左邊刪除列表中前count個值為value的元素,傳回值是實際刪除的元素個數;當count<0從右邊起刪除;count=0,會刪除所有值為value的元素。
LINDEX key index   :獲得指定索引的元素值,支援負索引
LSET key index value   :設定指定索引的元素值
LTRIM key start end   :只保留列表指定片段
LINSERT key BEFORE|AFTER pivot value :從左至右尋找值為pivot的元素,將value插入到該元素的BEFORE或AFTER
RPOPLPUSH source destination  :將元素從一個列表的右邊彈出轉到另一個列表的左邊

d.集合(儲存不相同的字串)
在集合中的每個元素都是不同的,且沒有順序。一個集合類型(set)鍵可以儲存至多2次方32-1個(相信這個數字對大家來說已經很熟悉了)字串。集合類型的常用操作是向集合中加入或刪除元素、判斷某個元素是否存在等,由於集合類型在Redis內部是使用值為空白的散列表(hash table)實現的,所以這些操作的時間複雜度都是0(1)。最方便的是多個集合類型鍵之間還可以進行並集、交集和差集運算。
SADD key member [member …]  :增加元素
SREM key member [member …]  :刪除元素
SMEMBERS key    :獲得集合中的所有元素
SISMEMBER key member   :判斷元素是否在集合中
SDIFF key [key …]   :差集
SINTER key [key …]   :交集
SUNION key [key …]   :並集
SCARD key    :獲得集合中元素個數
SDIFFSTORE destination key [key …] :進行集合運算並將結果儲存
SINTERSTORE destination key [key …]
SUNIONSTORE destination key [key …]
SRANDMEMBER key [count]   :隨機獲得集合中的元素(預設1個)當count為正數時,SRANDMEMBER會隨機從集合裡獲得count個不重複的元素。如果count的值大於集合中的元素個數,則SRANDMEMBER會返回集合中的全部元素;)當count為負數時,SRANDMEMBER會隨機從集合裡獲得|count|個的元素,這些元素有可能相同。
SPOP key    :從集合中彈出一個元素
SMOVE source destination value  :將鍵source中的value移動到destination中。
e.有序集合類型(sorted set)
在集合類型的基礎上有序集合類型為集合中的每個元素都關聯了一個分數,這使得我們不僅可以完成插入、刪除和判斷元素是否存在等集合類型支援的操作,還能夠獲得分數最高(或最低)的前N個元素、獲得指定分數範圍內的元素等與分數有關的操作。雖然集合中每個元素都是不同的,但是它們的分數卻可以相同。
 有序集合類型在某些方面和清單類型有些相似。
(1)二者都是有序的。
(2)二者都可以獲得某一範圍的元素。
但是二者有著很大的區別,這使得它們的應用情境也是不同的。
(1)清單類型是通過鏈表實現的,擷取靠近兩端的資料速度極快,而當元素增多後,訪問中間資料的速度會較慢,所以它更加適合實現如“新鮮事”或“日誌”這樣很少訪問中間元素的應用。
(2)有序集合類型是使用散列表和跳躍表(Skip list)實現的,所以即使讀取位於中間部分的資料速度也很快(時間複雜度是O(log(N)))。
(3)列表中不能簡單地調整某個元素的位置,但是有序集合可以(通過更改這個元素的分數)。
(4)有序集合要比清單類型更耗費記憶體
有序集合類型算得上是 Redis的5種資料類型中最進階的類型。

ZADD key score member [score member …] :增加元素,score可以是任意實數
ZSCORE key member   :獲得指定元素的分數
ZRANGE key start stop [WITHSCORES] :獲得排名在某個範圍的元素列表(升序),如前三ZRANGE key 0 2 ,[WITHSCORES]返回member的同時返回分數
ZREVRANGE key start stop [WITHSCORES] :按分數降序返回
ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count] :獲得指定分數範圍的成員(升序),[LIMIT offset count]從offset成員開始,返回count個成員
例 ZRANGEBYSCORE scoreboard (80 +inf LIMIT 5 3   返回80以上(不包括80)的從第5個人開始的3個人
Z INCRBY key increment member   :增加某個元素的分數,increment可以為負
ZCARD key    :獲得集合中元素的個數
ZCOUNT key min max   :獲得指定分數範圍內的元素個數
ZREM key member [member …]  :刪除一個或多個元素
ZREMRANGEBYRANK key start stop  :按照升序排名範圍刪除元素
ZREMRANGEBYSCORE key min max  :按照分數範圍刪除元素
ZRANK key member   :獲得指定元素的升序排名
ZREVRANK key member   :獲得指定元素的降序排名
ZINTERSTORE destination numkeys key [key …] [WEIGHTS weight [weight …]] [AGREGATE SUM|MIN|MAX] :計算有序集合的交集,如果權重相同,分數則按[AGREGATE SUM|MIN|MAX]計算
 
9.redis的事務
a.事務文法
redis的事務是需要原子執行的一組命令的集合。事務的原理是先將屬於一個事務的命令發送給Redis,然後再讓Redis依次執行這些命令。MULTI-EXEC關鍵字
redis>MULTI
OK
redis>SADD "user:1:following" 2
QUEUED
redis>SADD "user:2:followers" 1
QUEUED
redis>EXEC
1) (integer) 1
2) (integer) 1
在執行過程中如果有語法錯誤,則離開返回;如果是其它錯誤(如命令與索引值類型不符)則不返回,繼續執行下面的命令,直到結束。不過由於Redis不支援復原功能,也使得Redis在事務上可以保持簡潔和快速。另外回顧剛才提到的會導致事務執行失敗的兩種錯誤,其中語法錯誤完全可以在開發時找出並解決,另外如果能夠很好地規劃資料庫(保證鍵名規範等)的使用,是不會出現如命令與資料類型不匹配這樣的運行錯誤的。
b.監控-WATCH key
WATCH命令可以監控一個或多個鍵,一旦其中有一個鍵被修改(或刪除),之後的事務就不會執行。監控一直持續到WATCH後面執行的第一個EXEC命令為止(事務中的命令是在EXEC之後才執行的,所以在MULTI命令後可以修改WATCH監控的索引值)。
例子:
redis>SET key 1
OK
redis>WATCH key
OK
redis>SET key 2
OK
redis>MULTI
OK
redis>SET key 3
QUEUED
redis>EXEC  //在執行EXEC前,修改了WATCH監控的key值,所以WATCH緊跟的EXEC沒有執行。
(nil)
redis>GET key
"2"

c.取消監控-UNWATCH -可以在EXEC之前,認為的取消監控
10.鍵的存留時間-EXPIRE key seconds  設定某個鍵的存留時間,時間到達後,鍵被刪除;TTL key查看剩餘的時間;PERSIST key取消存留時間
例子:
redis>SET foo bar
OK
redis>EXPIRE foo 20
(integer) 1
redis>TTL foo
(integer) 15
redis>TTL foo
(integer) 7
redis> TTL foo
(integer) -1 //鍵不存在,或者該鍵沒有存留時間

redis>EXPIRE foo 20
(integer) 1
redis>SET foo bar  //使用SET對鍵重新賦值,相當於刪除該鍵,然後重建立立了一個新鍵
OK
redis>TTL foo
(integer) -1
 如果使用WATCH命令監測了一個擁有存留時間的鍵,該鍵時間到期自動刪除並不會被WATCH命令認為該鍵被改變。
EXPIREAT  key stamps   時間戳記,s單位
PEXPIREAT key stamps   時間戳記,ms單位

11.排序
排序可以使用有序集合,也可以使用SORT命令。
SORT命令可以多LIST、SET、ZSET類型的key進行排序。
a.命令格式: SORT key [ALPHA] [DESC] LIMIT start end   :[ALPHA]表示按字母排序;預設是升序;LIMIT start end取排序結果的從start到end結果返回
b.SORT的BY參數:BY 參數的文法為“BY參考鍵”。其中參考鍵可以是字串類型鍵或者是散列類型鍵的某個欄位(表示為鍵名->欄位名)。如果提供了BY參數,SORT命令將不再依據元素自身的值進行排序,而是對每個元素使用元素的值替換參考鍵中的第一個“*”並擷取其值,然後依據該值對元素排序。參考鍵可以是散列或字串類型。
例子:
redis>SORT tag:ruby:posts BY post:*->time DESC
1) "12"
2) "26"
3) "6"
4) "2"

對字串進行排序:參考鍵為字串
redis>LPUSH sortbylist 2 1 3
(integer) 3
redis>SET itemscore:1 50
OK
redis>SET itemscore:2 100
OK
redis>SET itemscore:3 -10
OK
redis>SORT sortbylist BY itemscore:* DESC
1) "2"
2) "1"
3) "3"
例子中anytext是常量鍵名(甚至anytext鍵可以不存在),此時SORT的結果與LRANGE的結果相同,沒有執行排序操作;如果幾個元素的參考索引值相同,則SORT命令會再比較元素本身的值來決定元素的順序。
c.SORT的GET參數:GET參數不影響排序,它的作用是使SORT命令的返回結果不再是元素自身的值,而是GET參數中指定的索引值。GET參數的規則和BY參數一樣,GET參數也支援字串類型和散列類型的鍵,並使用“*”作為預留位置。
redis>SORT tag:ruby:posts BY post:*->time DESC GET post:*->title
1) "Windows 8 app designs"
2) "RethinkDB - An open-source distributed database built with love"
3) "Uses for cURL"
4) "The Nature of Ruby"  
排序後返回的不是ID,而是ID對應的文章。(redis是否只能對數字和字母進行排序,不能對字串進行排序?)
d.SORT的STORE參數:預設情況下SORT會直接返回排序結果,如果希望儲存排序結果,可以使用STORE參數。
例子:
SORT some.list STORE cache.sort

12.訊息通知
a.任務隊列
說到隊列很自然就能想到Redis的清單類型。如果要實現任務隊列,只需要讓生產者將任務使用LPUSH命令加入到某個鍵中,另一邊讓消費者不斷地使用RPOP命令從該鍵中取出任務即可。 BRPOP(右邊出棧)和BLPOP(左邊出棧) 命令就可以實現請求阻塞。
BRPOP命令接收兩個參數,第一個是鍵名,第二個是逾時時間,單位是秒。當超過了此時間仍然沒有獲得新元素的話就會返回nil。上例中逾時時間為“0”,表示不限制等待的時間,即如果沒有新元素加入列表就會永遠阻塞下去。當獲得一個元素後BRPOP命令返回兩個值,分別是鍵名和元素值。
例子:(多個用戶端執行個體中實現生產者與消費者模型)
在執行個體A中:
redis A>BRPOP queue 0
鍵入斷行符號後執行個體1會處於阻塞狀態,這時在執行個體B中向queue中加入一個元素:
redis B>LPUSH queue task
(integer) 1
在LPUSH命令執行後執行個體A馬上就返回了結果:
1) "queue"
2) "task"

b.優先順序隊列
BRPOP命令和BLPOP命令實際上可以同時阻塞的讀取多個鍵,最前面的鍵優先順序最高;如果所有鍵都沒有元素則阻塞;如果都有元素,則先讀取第一個鍵的元素。
BLPOP key [key …] timeout    :最前面的鍵具有更高的優先順序
>LPUSH queue2 task2
1) (integer) 1
>LPUSH queue3 task3
1) (integer) 1
redis>BRPOP queue1 queue2 queue3 0
1) "queue:2"
2) "task2"

c.“發布/訂閱”模式
“發布/訂閱”模式同樣可以實現進程間的訊息傳遞,其原理是這樣的:“發布/訂閱”模式中包含兩種角色,分別是發行者和訂閱者。訂閱者可以訂閱一個或若干
個頻道(channel),而發行者可以向指定的頻道發送訊息,所有訂閱此頻道的訂閱者都會收到此訊息。
發行者發布訊息的命令是PUBLISH,用法是
PUBLISH channel message,如向channel.1說一聲“hi”:
redis>PUBLISH channel.1 hi
(integer) 0
PUBLISH命令的傳回值表示接收到這條訊息的訂閱者數量訂閱頻道的命令是SUBSCRIBE,可以同時訂閱多個頻道,用法是
SUBSCRIBEchannel[channel …]  現在新開一個redis-cli執行個體A,用它來訂閱channel.1:
redis A>SUBSCRIBE channel.1
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "channel.1"
3) (integer) 1
執行SUBSCRIBE命令後用戶端會進入訂閱狀態,處於此狀態下用戶端不能使用除SUBSCRIBE/UNSUBSCRIBE/PSUBSCRIBE/PUNSUBSCRIBE這4個屬於“發布/訂閱”模式的命令之外的命令(後面3個命令會在下面介紹),否則會報錯。相當於阻塞在訂閱模式中。UNSUBSCRIBE退訂。

按照通配規則訂閱:可以使用PSUBSCRIBE命令按照通配規則訂閱指定的規則
>PSUBSCRIBE channel.?*
Reading messages... (press Ctrl-C to quit)1) "psubscribe"
2) "channel.?*"
3) (integer) 1
 
redis B>PUBLISH channel.1 hi!
(integer) 2
訂閱者返回結果:
1) "pmessage"
2) "channel.?*"
3) "channel.1"
4) "hi!"
 使用PSUBSCRIBE命令可以重複訂閱一個頻道,如某用戶端執行了PSUBSCRIBE channel.? channel.?*,這時向channel.2發布訊息後該用戶端會收到兩條訊息,而同時PUBLISH命令返回的值也是2而不是1。
PUNSUBSCRIBE命令可以退訂指定的規則,用法是
PUNSUBSCRIBE [pattern[pattern …]]
如果沒有參數則會退訂所有規則。
UNSUBSCRIBE命令只能退訂通過PSUBSCRIBE命令訂閱的規則,不會影響直接通過SUBSCRIBE命令訂閱的頻道;同樣UNSUBSCRIBE命令也不會影響通過PSUBSCRIBE命令訂閱的規則。另外容易出錯的一點是使用PUNSUBSCRIBE命令退訂某個規則時不會將其中的萬用字元展開,而是進行嚴格的字串匹配,所以PUNSUBSCRIBE*無法退訂channel.*規則,而是必須使用PUNSUBSCRIBE channel.*才能退訂。

13.管道
Redis的底層通訊協定對管道(pipelining)提供了支援。通過管道可以一次性發送多條命令並在執行完後一次性將結果返回,當一組命令中每條命令都不依賴於之前命令的執行結果時就可以將這組命令一起通過管道發出。管道通過減少用戶端與Redis的通訊次數來實現降低往返時延累計值的目的。降低TCP訊息包的數量。

14.redis與python
Redis官方推薦的Python用戶端是redis-py,見https://github.com/andymccurdy/redis-py。
a.redis的python用戶端在python編程中的使用方法:
import redis   //首先需要引入redis-py:
r=redis.StrictRedis()  //下面的代碼將建立一個預設串連到地址127.0.0.1,連接埠6379的Redis串連:
r=redis.StrictRedis(host=‘127.0.0.1‘, port=6379, db=0)  //也可以顯式地指定需要串連的地址:
r.set(‘foo‘, ‘bar‘) # True
a=r.get(‘foo‘) # ‘bar‘
b.HMSET/HGETALL
HMSET支援將字典作為參數儲存,同時HGETALL的傳回值也是一個字典,搭配使用十分方便:
r.hmset(‘dict‘, {‘name‘: ‘Bob‘})
people=r.hgetall(‘dict‘)
print people # {‘name‘: ‘Bob‘}
c.事務和管道
redis-py的事務使用方式如下:
pipe=r.pipeline()
pipe.set(‘foo‘, ‘bar‘)
pipe.get(‘foo‘)
result=pipe.execute()
print result # [True, ‘bar‘]
管道的使用方式和事務相同,只不過需要在建立時加上參數transaction=False:
pipe=r.pipeline(transaction=False)
事務和管道還支援鏈式調用:
result=r.pipeline().set(‘foo‘, ‘bar‘).get(‘foo‘).execute()
# [True, ‘bar‘]

15.redis指令碼
Redis在2.6版推出了指令碼功能,允許開發人員使用Lua語言編寫指令碼傳到Redis中執行。在Lua指令碼中可以調用大部分的Redis命令
使用指令碼的好處如下:
(1)減少網路開銷:6.1節中的第一段代碼最多需要向Redis發送5次請求,而使用指令碼功能完成同樣的操作只需要發送一個請求即可,減少了網路往返時延。
(2)原子操作:Redis會將整個指令碼作為一個整體執行,中間不會被其他命令插入。換句話說在編寫指令碼的過程中無需擔心會出現競態條件,也就無需使用事務。事務可以完成的所有功能都可以用指令碼來實現。
(3)複用:用戶端發送的指令碼會永久儲存在Redis中,這就意味著其他用戶端(可以是其他語言開發的項目)可以複用這一指令碼而不需要使用程式碼完成同樣的邏輯。
下面是一段lua指令碼,名字為a.lua
local times=redis.call(‘incr‘, KEYS[1])
if times==1 then   -- KEYS[1]鍵剛建立,所以為其設定存留時間
redis.call(‘expire‘, KEYS[1], ARGV[1])
end
if times>tonumber(ARGV[2]) then
return 0
end
return 1
那麼,如何測試這個指令碼呢?首先把這段代碼存為a.lua,然後在命名行中輸入:
 redis-cli --eval a.lua rate.limiting:127.0.0.1 , 10 3
 
其中--eval 參數是告訴redis-cli讀取並運行後面的Lua指令碼,後面跟著的是傳給Lua指令碼的參數。其中“,”前的
rate.limiting:127.0.0.1是要操作的鍵,可以在指令碼中使用KEYS[1]擷取,“,”後面的10和3是參數,在指令碼中
能夠使用ARGV[1]和ARGV[2]獲得。結合指令碼的內容可知這行命令的作用就是將訪問頻率限制為每10秒最多3次,
所以在終端中不斷地運行此命令會發現當訪問頻率在10秒內小於或等於3次時返回1,否則返回0。注意上面
的命令中“,”兩邊的空格不能省略,否則會出錯。
16.redis與lua
a.在指令碼中調用Redis命令
在指令碼中可以使用redis.call函數調用Redis命令。就像這樣:
redis.call(‘set‘, ‘foo‘, ‘bar‘)
local value=redis.call(‘get‘, ‘foo‘) --value的值為bar
redis.call函數的傳回值就是Redis命令的執行結果。第2章介紹過Redis命令的傳回值有5種
類型,redis.call函數會將這5種類型的回複轉換成對應的Lua的資料類型.
Redis還提供了redis.pcall函數,功能與redis.call相同,唯一的區別是當命令執行出錯時redis.pcall會記錄錯誤並繼續執行,而redis.call會直接返回錯誤,不會繼續執行。
b. 從指令碼中傳回值 return
在指令碼中可以使用return語句將值返回給用戶端,如果沒有執行return語句則預設返回nil。因為我們可以像調用其他Redis內建命令一樣調用我們自己寫的指令碼
c. 指令碼相關命令
EVAL命令:EVAL命令的格式是:EVAL指令碼內容key參數的數量[key …] [arg …]
可以通過key和arg這兩類參數向指令碼傳遞資料,它們的值可以在指令碼中分別使用KEYS和ARGV兩個表類型的全域變數訪問
例如,我們希望用指令碼功能實現一個SET命令(當然現實中我們不會這麼幹),指令碼內容是這樣的:
return redis.call(‘SET‘, KEYS[1], ARGV[1])
現在開啟redis-cli執行此指令碼:
redis>EVAL "return redis.call(‘SET‘, KEYS[1], ARGV[1])" 1 foo bar
OK
redis>GET foo
"bar"
EVALSHA命令:
考慮到在指令碼比較長的情況下,如果每次呼叫指令碼都需要將整個指令碼傳給Redis會佔用較
多的頻寬。為瞭解決這個問題,Redis提供了EVALSHA命令允許開發人員通過指令碼內容的SHA1
摘要來執行指令碼,該命令的用法和EVAL一樣,只不過是將指令碼內容替換成指令碼內容的SHA1
摘要.
在程式中使用EVALSHA命令的一般流程如下。
(1)先計算指令碼的SHA1摘要,並使用EVALSHA命令執行指令碼。
(2)獲得傳回值,如果返回“NOSCRIPT”錯誤則使用EVAL命令重新執行指令碼。
雖然這一流程略顯麻煩,但值得慶幸的是很多程式設計語言的Redis用戶端都會代替開發人員完
成這一流程。比如使用node_redis用戶端執行EVAL命令時,node_redis會先嘗試執行EVALSHA
命令,如果失敗了才會執行EVAL命令

本文出自 “tech記錄” 部落格,謝絕轉載!

Redis資料庫筆記

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.