Redis(Remote Dictionary Server ),即遠端字典服務,是一個開源的使用ANSI C語言編寫、支援網路、可基於記憶體亦可持久化的日誌型、Key- Value資料庫,並提供多種語言的API。
(學習影片分享:redis影片教學)
1.redis發布訂閱模式
Redis除了提供像list的這種的訊息佇列模式,還提供了一組命令實現發布/訂閱模式。例如微博,公眾號等都是可以由此實現。
1.2 訂閱頻道
發布者需要將訊息傳送到一個地方,讓訂閱者可以訂閱訊息,而這個地方就是頻道(channel)。訂閱者可以訂閱一個或多個頻道,所有訂閱了這個頻道的訂閱者都會受到這則訊息。
開啟兩個客戶端進行測試
客户端1 订阅channel1 127.0.0.1:6379> subscribe channel1 Reading messages... (press Ctrl-C to quit) 1) "subscribe" 2) "channel1" 3) (integer) 1 客户端2 发布一则消息 127.0.0.1:6379> publish channel1 test (integer) 1 客户端1 订阅消息 127.0.0.1:6379> subscribe channel1 Reading messages... (press Ctrl-C to quit) 1) "subscribe" 2) "channel1" 3) (integer) 1 1) "message" 2) "channel1" 3) "test"
1.2 依規則訂閱
#支援?和*佔位符。 ?代表一個字符,*代表 0 個或多個字符。
啟動四個redis-cli,一個作為訊息的發布者,另外三個作為訂閱者。
訂閱者1:訂閱體育相關
psubscribe *sport
訂閱者2:訂閱新聞相關
psubscribe news*
訂閱者3:訂閱天氣相關
psubscribe new weather*
發布者:
publish news-sport Kobe publish news-music jaychou publish news-weather rain
此時訂閱者1將會收到Kobe,訂閱者2將會收到全部訊息,訂閱者3將會收到rain。
2.redis事務
2.1 為什麼要用交易
我們都是知道redis的單一指令是原子性的,但是如果需要用多個指令作為一個不可分割的操作序列,就需要用到交易。
例如使用setnx實現分散式鎖,我們一般先set,然後對key設定expire,防止del發生異常時候鎖不會釋放,業務處理完之後在del,這三個操作我們就希望作為一組命令執行。
redis交易有兩個特點:
依照進入佇列的順序執行
不會受到其他客戶端請求影響
redis的交易設計四個指令:multi(開啟交易),exec(執行交易),dicard(取消交易),watch(監視)
2.2 交易的用法
轉帳場景A和B各有100元,A向B轉帳10元,A減10元,B加10元
127.0.0.1:6379> set A 100 OK 127.0.0.1:6379> set B 100 OK 127.0.0.1:6379> multi OK 127.0.0.1:6379> decrby A 10 QUEUED 127.0.0.1:6379> incrby B 10 QUEUED 127.0.0.1:6379> exec 1) (integer) 90 2) (integer) 110 127.0.0.1:6379> get A "90" 127.0.0.1:6379> get B "110"
透過multi指令開啟交易。事務不能嵌套,多個multi指令效果一樣的
使用multi開啟事務之後,客戶端向伺服器發送多條指令,這些指令並不會立即被執行,而是會被放到一個佇列中,當exec指令呼叫之後,佇列中的命令才會被執行。
我們可以使用discard來清空事務佇列。
127.0.0.1:6379> multi OK 127.0.0.1:6379> set k1 1 QUEUED 127.0.0.1:6379> set k2 2 QUEUED 127.0.0.1:6379> discard OK 127.0.0.1:6379> get k1 (nil) 127.0.0.1:6379> get k2 (nil)
當我們執行事務的時候出現了問題會回滾嗎?
exec之前發生錯誤(如指令語法錯誤)
127.0.0.1:6379> clear 127.0.0.1:6379> multi OK 127.0.0.1:6379> set name test QUEUED 127.0.0.1:6379> hset user lisi (error) ERR wrong number of arguments for 'hset' command 127.0.0.1:6379> exec (error) EXECABORT Transaction discarded because of previous errors. 127.0.0.1:6379> get name (nil)
exec之後發生錯誤(對同一個key使用不同資料類型的命令)
127.0.0.1:6379> multi OK 127.0.0.1:6379> set k1 1 QUEUED 127.0.0.1:6379> hset k1 a b QUEUED 127.0.0.1:6379> exec 1) OK 2) (error) WRONGTYPE Operation against a key holding the wrong kind of value 127.0.0.1:6379> get k1 "1"
透過上面操作,我們可以知道當交易在exec前發生錯誤,將會回滾所有操作;如果在exec後發生錯誤,只有錯誤的指令不會被執行。
為什麼redis在一個交易中存在錯誤不進行回滾呢?
我們從上面操作可以看出,redis只有在指令語法錯誤的時候進行回滾,而指令操作錯誤是有開發人員導致的bug,例如:你對一個int型別進行1,然後不小心2,或對一個string類型進行1,回滾是不適用的
2.3 watch指令
它可以為Redis事務提供CAS樂觀鎖定操作,也就是多個執行緒更新某個變數的時候,會讓舊值跟記憶體位址比較,如果相等,則更新為新值。
我們可以用watch監視一個或多個key,如果開啟事務之後,至少有一個被監視的key在exec執行之前被修改,則會取消整個事務。
首先client 1執行watch監視money這個key,並開啟事務對money進行增加100
127.0.0.1:6379> set money 1000 OK 127.0.0.1:6379> watch money OK 127.0.0.1:6379> multi OK 127.0.0.1:6379> incrby money 100 QUEUED
在事務結束之前,在client 2對money進行減少100
127.0.0.1:6379> decrby money 100 (integer) 900
此時client 1結束事務,money的值並沒有被增加,反而減少,說明事務的修改失效
127.0.0.1:6379> exec (nil) 127.0.0.1:6379> get money "900"
3. Lua腳本
Lua腳本是一種輕量級腳本語言,C語言寫的,跟預存過程有點類似。為啥要用lua腳本呢?
一次發送多個命令,減少網路開銷Redis會將腳本作為一個整體執行,確保原子性(可用此方式替換事務)腳本復用,以便於多個客戶端完成相同的邏輯。
3.1 使用
我們可以使用以下指令進行呼叫lua腳本
eval script numkeys [key1 key2 key3 ....] [arg1 arg2 arg3 ....]
eval 執行lua腳本
script 代表lua腳本的內容
numkeys key的數量
[key1 key2 key3 ....] 键名参数,表示在脚本中所用到的那些 Redis 键(key),这些键名参数可以在 Lua 中通过全局变量 KEYS 数组,用 1 为基址的形式访问( KEYS[1] , KEYS[2] ,以此类推)。
[arg1 arg2 arg3 ....] 全局变量,可以在 Lua 中通过全局变量 ARGV 数组访问,访问的形式和 KEYS 变量类似( ARGV[1] 、 ARGV[2] ,诸如此类)
来个简单的例子
127.0.0.1:6379> eval "return {KEYS[1],ARGV[1],KEYS[2],ARGV[2]}" 2 key1 key2 val1 val1 1) "key1" 2) "val1" 3) "key2" 4) "val1" 127.0.0.1:6379> eval "return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}" 2 key1 key2 val1 val1 1) "key1" 2) "key2" 3) "val1" 4) "val1"
在lua脚本如何调用redis命令呢?
我们可以使用 redis.call(command, key [param1, param2…])进行操作
commond redis的命令,如set,get等key 被操作的键[param1, param2…]表示给key的参数
127.0.0.1:6379> eval "redis.call('mset',KEYS[1],ARGV[1],KEYS[2],ARGV[2])" 2 name age lisi 18 (nil) 127.0.0.1:6379> mget name age 1) "lisi" 2) "18
以上命令等价于 mset name lisi age 18, key的数量为2,2 后面两个值为key,在之后就是args
直接在redis-cli中写lua脚本不够方便,通常我们会把脚本放在文件中,然后执行这个文件
我们在一个目录下新建一个test.lua的脚本,填写以下内容后执行。
root@VM-0-5-centos src]# mkdir testlua [root@VM-0-5-centos src]# cd testlua/ [root@VM-0-5-centos testlua]# ll total 0 [root@VM-0-5-centos testlua]# touch test.lua [root@VM-0-5-centos testlua]# vim test.lua redis.call('set',KEYS[1],ARGV[1]) return redis.call('get',KEYS[1]) [root@VM-0-5-centos testlua]# redis-cli --eval test.lua 1 myname , Armin "Armin"
值得注意的是key和arg之间需要加上空格逗号空格(myname , Armin)
3.2 缓存lua脚本
之所以需要缓存lua脚本,这是因为每次调用的时候都将整个脚本传给redis服务端,会产生较大的网络开销。为了解决这个问题,Redis提供了evalsha命令,让开发人员通过脚本内容的SHA1摘要执行脚本。
那么怎么将生成这个SHA1并将脚本内容加载到缓存呢,这就用到script load命令去计算脚本的SHA1摘要并记录脚本到缓存中,执行evalsha时,redis会根据提供的摘要去脚本缓存找到对应脚本内容,如果找到则执行,否则返回错误提示: “NOSCRIPT No matching script. Please use EVAL”
127.0.0.1:6379> script load "return 'Hey boy'" "3760855b303510c83f0be2e8acfb0be64113ae6e" 127.0.0.1:6379> evalsha 3760855b303510c83f0be2e8acfb0be64113ae6e 0 "Hey boy" 127.0.0.1:6379> script exists 3760855b303510c83f0be2e8acfb0be64113ae6e //判断是否存在 1) (integer)
Redis还给lua脚本的执行提供了超时时间,默认的超时时间为5s,超过5s之后redis会接受其他命令但是会返回一个"BUSY"的错误
可在redis.conf中修改指定参数
lua-time-limit 5000
Redis提供了个script kill的命令来终止正在运行的脚本
127.0.0.1:6379> set name lisi (error) BUSY Redis is busy running a script. You can only call SCRIPT KILL or SHUTDOWN NOSAVE. 127.0.0.1:6379> script kill OK 127.0.0.1:6379> set name lisi OK
如果数据进行了修改操作,将无法使用script kill终止脚本,因为违反了原子性。此时只能通过shutdown nosave来强行终止redis。
shutdown nosave 和 shutdown 的区别在于 shutdown nosave 不会进行持久化
操作,意味着发生在上一次快照后的数据库修改都会丢失。
相关推荐:redis数据库教程
以上是redis的高階特性介紹的詳細內容。更多資訊請關注PHP中文網其他相關文章!

Redis的關鍵特性包括速度、靈活性和豐富的數據結構支持。 1)速度:Redis作為內存數據庫,讀寫操作幾乎瞬時,適用於緩存和會話管理。 2)靈活性:支持多種數據結構,如字符串、列表、集合等,適用於復雜數據處理。 3)數據結構支持:提供字符串、列表、集合、哈希表等,適合不同業務需求。

Redis的核心功能是高性能的內存數據存儲和處理系統。 1)高速數據訪問:Redis將數據存儲在內存中,提供微秒級別的讀寫速度。 2)豐富的數據結構:支持字符串、列表、集合等,適應多種應用場景。 3)持久化:通過RDB和AOF方式將數據持久化到磁盤。 4)發布訂閱:可用於消息隊列或實時通信系統。

Redis支持多種數據結構,具體包括:1.字符串(String),適合存儲單一值數據;2.列表(List),適用於隊列和棧;3.集合(Set),用於存儲不重複數據;4.有序集合(SortedSet),適用於排行榜和優先級隊列;5.哈希表(Hash),適合存儲對像或結構化數據。

Redis計數器是一種使用Redis鍵值對存儲來實現計數操作的機制,包含以下步驟:創建計數器鍵、增加計數、減少計數、重置計數和獲取計數。 Redis計數器的優勢包括速度快、高並發、持久性和簡單易用。它可用於用戶訪問計數、實時指標跟踪、遊戲分數和排名以及訂單處理計數等場景。

使用 Redis 命令行工具 (redis-cli) 可通過以下步驟管理和操作 Redis:連接到服務器,指定地址和端口。使用命令名稱和參數向服務器發送命令。使用 HELP 命令查看特定命令的幫助信息。使用 QUIT 命令退出命令行工具。

Redis集群模式通過分片將Redis實例部署到多個服務器,提高可擴展性和可用性。搭建步驟如下:創建奇數個Redis實例,端口不同;創建3個sentinel實例,監控Redis實例並進行故障轉移;配置sentinel配置文件,添加監控Redis實例信息和故障轉移設置;配置Redis實例配置文件,啟用集群模式並指定集群信息文件路徑;創建nodes.conf文件,包含各Redis實例的信息;啟動集群,執行create命令創建集群並指定副本數量;登錄集群執行CLUSTER INFO命令驗證集群狀態;使

要從 Redis 讀取隊列,需要獲取隊列名稱、使用 LPOP 命令讀取元素,並處理空隊列。具體步驟如下:獲取隊列名稱:以 "queue:" 前綴命名,如 "queue:my-queue"。使用 LPOP 命令:從隊列頭部彈出元素並返回其值,如 LPOP queue:my-queue。處理空隊列:如果隊列為空,LPOP 返回 nil,可先檢查隊列是否存在再讀取元素。

Redis 集群中使用 zset:zset 是一種有序集合,將元素與評分關聯。分片策略: a. 哈希分片:根據 zset 鍵的哈希值分佈。 b. 範圍分片:根據元素評分劃分為範圍,並將每個範圍分配給不同的節點。讀寫操作: a. 讀操作:如果 zset 鍵屬於當前節點的分片,則在本地處理;否則,路由到相應的分片。 b. 寫入操作:始終路由到持有 zset 鍵的分片。


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

MinGW - Minimalist GNU for Windows
這個專案正在遷移到osdn.net/projects/mingw的過程中,你可以繼續在那裡關注我們。 MinGW:GNU編譯器集合(GCC)的本機Windows移植版本,可自由分發的導入函式庫和用於建置本機Windows應用程式的頭檔;包括對MSVC執行時間的擴展,以支援C99功能。 MinGW的所有軟體都可以在64位元Windows平台上運作。

MantisBT
Mantis是一個易於部署的基於Web的缺陷追蹤工具,用於幫助產品缺陷追蹤。它需要PHP、MySQL和一個Web伺服器。請查看我們的演示和託管服務。

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用