目錄
一、Pipelin模式介紹
1、redis的通常使用方式
2、Pipeline模式
3、性能對比
二、Redis事物
1、事務命令
2、事務例外
三、redis發布與訂閱
1、Redis發布訂閱常用命令
2、性能測驗
3、應用場景
四、鍵的遷移
1、move
2、dump
3、migrate
五、自定義命令封裝
六、鍵全量遍歷
1、keys
2、漸進式遍歷 scan
3、scan 和keys對比
4、其他遍歷命令
在redis入門章節時,已經給大家介紹了redis的基本操作指令,今天對redis的進階操作給大家介紹一下,以及對于jedis和redisTemplate等工具包沒有封裝的命令我們該如何使用?相信大家讀了本篇對redis的整體會有更深的認知,
一、Pipelin模式介紹
1、redis的通常使用方式
大多數情況下,我們都會通過請求-相應機制去操作redis,使用這種模式的步驟為
- 獲得jedis實體
- 發送redis命令
- 由于redis是單執行緒的,所以處理完上一個指令之后才會進行執行該命令,
整個互動流程如下

2、Pipeline模式
然而使用Pipeline 模式,客戶端可以一次性的發送多個命令,無需等待服務端回傳,這樣就大大的減少了網路往返時間,提高了系統性能,
pipeline是多條命令的組合,使用PIPELINE 可以解決網路開銷的問題,原理也非常簡單,流程如下, 將多個指令打包后,一次性提交到Redis, 網路通信只有一次

3、性能對比
| 網路 | 延遲 | 非Pipeline | Pipeline |
| 本機 | 1300 | 1414 | 114 |
| 內網服務器 | 1222ms | 1532ms | 310ms |
| 異地機房 | 90910ms | 92 000ms | 1090ms |
可以看到,redis的延遲主要出現在網路請求的IO次數上,因此我們在使用redis的時候,盡量減少網路IO次數,通過pipeline的方式將多個指令封裝在一個命令里執行,
二、Redis事物
redis的簡單事務是將一組需要一起執行的命令放到multi和exec兩個命令之間,其中multi代表事務開始,exec代表事務結束

1、事務命令
multi:事務開始
exec:提交事務
watch:事務監控
WATCH命令可以監控一個或多個鍵,一旦其中有一個鍵被修改(或洗掉),之后的事務就不會執行,監控一直持續到
discard:停止事務
在執行exec之前執行該命令,提交事務會失敗,執行的命令會進行回滾
127.0.0.1:6379> multi //開始事務
OK
127.0.0.1:6379> sadd tt 1 //業務操作
QUEUED
127.0.0.1:6379> DISCARD //停止事務
OK
127.0.0.1:6379> exec //提交事務
(error) ERR EXEC without MULTI //報不存在事務例外
127.0.0.1:6379> get tt //獲取不到物件
(nil)
127.0.0.1:6379>
2、事務例外
redis支持事務,但他屬于弱事務,中間的一些例外可能會導致事務失效,
1、命令錯誤,語法不正確,導致事務不能正常結束
127.0.0.1:6379> multi //開始事務
OK
127.0.0.1:6379> set aa 123 //業務操作
QUEUED
127.0.0.1:6379> sett bb 124 //命令錯誤
(error) ERR unknown command 'sett'
127.0.0.1:6379> exec
(error) EXECABORT Transaction discarded because of previous errors. //提交事務例外
127.0.0.1:6379> get aa //查詢不到資料
(nil)
127.0.0.1:6379>
2、運行錯誤,語法正確,但型別錯誤,事務可以正常結束
127.0.0.1:6379> multi
OK
127.0.0.1:6379> set t 1 //業務操作1
QUEUED
127.0.0.1:6379> sadd t 1 //業務操作2
QUEUED
127.0.0.1:6379> set t 2 //業務操作3
QUEUED
127.0.0.1:6379> exec
1) OK
2) (error) WRONGTYPE Operation against a key holding the wrong kind of value //型別例外
3) OK
127.0.0.1:6379> get t //可以獲取到t
"2"
127.0.0.1:6379>
三、redis發布與訂閱
redis提供了“發布、訂閱”模式的訊息機制,其中訊息訂閱者與發布者不直接通信,發布者向指定的頻道(channel)發布訊息,訂閱該頻道的每個客戶端都可以接收到訊息

1、Redis發布訂閱常用命令
| 命令 | 含義 |
| publish channel | 發布訊息 |
| subscribe channel | 訂閱訊息 |
| pubsub numsub channel | 查看訂閱數 |
| unsubscribe channel | 取消訂閱 |
| psubscribe ch* | 按模式訂閱和取消訂閱 |
2、性能測驗
見我的另一個博文:redis 發布訂閱 性能測驗
3、應用場景
redis主要提供發布訊息、訂閱頻道、取消訂閱以及按照模式訂閱和取消訂閱,和很多專業的訊息佇列(kafka rabbitmq),redis的發布訂閱顯得很lower, 比如無法實作訊息規程和回溯, 但就是簡單,如果能滿足應用場景,用這個也可以
- 訂閱號、公眾號、微博關注、郵件訂閱系統等
- 即使通信系統
- 群聊部落系統(微信群)
四、鍵的遷移
鍵遷移大家可能用的不是很多,因為一般都是使用redis主從同步,不過對于我們做資料統計分析使用的時候,可能會使用到,比如用戶標簽,為了避免key批量洗掉導致的redis雪崩,一般都是通過一個計算使用的redis和一個最終業務使用的redis,通過將計算時用的redis里的鍵值通過遷移的方式一個一個的更新到業務redis中,使其對業務沖擊最小化,
1、move
move指令將redis一個庫中的資料遷移到另外一個庫中,
move key db //reids有16個庫, 編號為0-15
set name DK; move name 5 //遷移到第6個庫
elect 5 ;//資料庫切換到第6個庫,
get name 可以取到james1
如果key在目標資料庫中已存在,那么什么也不會發生,這種模式不建議在生產環境使用,在同一個reids里可以玩
2、dump
Redis DUMP 命令用于將key給序列化 ,并回傳被序列化的值,用于匯入到其他服務中
一般通過dump命令匯出,使用restore命令匯入,
1,在A服務器上
set name james;
dump name; // 得到"\x00\x05james\b\x001\x82;f\"DhJ"
2,在B服務器上
restore name 0 "\x00\x05james\b\x001\x82;f\"DhJ" //0代表沒有過期時間
get name //回傳james
3、migrate
migrate用于在Redis實體間進行資料遷移,實際上migrate命令是將dump、restore、del三個命令進行組合,從而簡化了操作流程,
migrate命令具有原子性,從Redis 3.0.6版本后已經支持遷移多個鍵的功能,migrate命令的資料傳輸直接在源Redis和目標Redis上完成,目標Redis完成restore后會發送OK給源Redis,
| migrate | 192.168.42.112 | 6379 | name | 0 | 1000 | copy | replace |
| 指令 | 要遷移的目標IP | 埠 | 遷移鍵值 | 目標庫 | 超時時間 | 遷移后不洗掉原鍵 | 不管目標庫是不存在test鍵都遷移成功 |
比如:把111上的name鍵值遷移到112上的redis
192.168.42.111:6379> migrate 192.168.42.112 6379 name 0 1000 copy
五、自定義命令封裝
當我們使用jedis或者jdbctemplate時,想執行鍵遷移的指令的時候,發現根本沒有給我們封裝相關指令,這個時候我們該怎么辦呢?除了框架幫我們封裝的方法外,我們自己也可以通過反射的方式進行命令的封裝,主要步驟如下
- 建立Connection鏈接,使用Connection連接Redis
- 通過反射獲取Connection中的sendCommand方法(protected Connection sendCommand(Command cmd, String... args)),
- 呼叫connection的sendCommand方法,第二個引數為執行的命令(比如set,get,client等),第三個引數為命令的引數,可以看到ProtocolCommand這個列舉物件包含了redis的所有指令,即所有的指令都可以通過這個物件獲取到,并封裝執行
- 執行invoke方法,并且按照redis的指令封裝引數
- 獲取Redis的命令執行結果
package com.james.cache.jedis;
import redis.clients.jedis.Connection;
import redis.clients.jedis.Protocol;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* @Auther: DK
* @Date: 2020/10/11 23:17
* @Description:
*/
public class RedisKeyMove {
public static void main(String[] args) throws IOException {
//1.使用Connection連接Redis
try (Connection connection = new Connection("10.1.253.188", 6379)) {
// 2. 通過反射獲取Connection中的sendCommand方法(protected Connection sendCommand(Command cmd, String... args)),
Method method = Connection.class.getDeclaredMethod("sendCommand", Protocol.Command.class, String[].class);
method.setAccessible(true); // 設定可以訪問private和protected方法
// 3. 呼叫connection的sendCommand方法,第二個引數為執行的命令(比如set,get,client等),第三個引數為命令的引數,
// 3.1 該命令最終對應redis中為: set test-key test-value
method.invoke(connection, Protocol.Command.MIGRATE,
new String[] {"10.1.253.69", "6379", "name", "0", "1000", "copy"});
// 4.獲取Redis的命令執行結果
System.out.println(connection.getBulkReply());
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
六、鍵全量遍歷
1、keys
| 指令 | 含義 |
| keys * | 回傳所有的鍵, *匹配任意字符多個字符 |
| keys *y | 以結尾的鍵 |
| keys n*e | 以n開頭以e結尾,回傳name |
| keys n?me | ?問號代表只匹配一個字符 回傳name,全域匹配 |
| keys n?m* | 回傳name |
| keys [j,l]* | 回傳以j l開頭的所有鍵 keys [j]ames 全量匹配james |
考慮到是單執行緒,使用改命令會阻塞執行緒, 在生產環境不建議使用,鍵多可能會阻塞,
2、漸進式遍歷 scan
1,初始化資料
mset n1 1 n2 2 n3 3 n4 4 n5 5 n6 6 n7 7 n8 8 n9 9 n10 10 n11 11 n12 12 n13 13
2,遍歷匹配
scan 0 match n* count 5 匹配以n開頭的鍵,最大是取5條,第一次scan 0開始
第二次從游標4096開始取20個以n開頭的鍵,相當于一頁一頁的取當最后回傳0時,鍵被取完,
3、scan 和keys對比
- 通過游標分布進行的,不會阻塞執行緒;
- 提供 limit 引數,可以控制每次回傳結果的最大條數,limit 不準,回傳的結果可多可少;
- 同 keys 一樣,Scan也提供模式匹配功能;
- 服務器不需要為游標保存狀態,游標的唯一狀態就是 scan 回傳給客戶端的游標整數;
- scan回傳的結果可能會有重復,需要客戶端去重復;
- scan遍歷的程序中如果有資料修改,改動后的資料能不能遍歷到是不確定的;
- 單次回傳的結果是空的并不意味著遍歷結束,而要看回傳的游標值是否為零;
4、其他遍歷命令
SCAN 命令用于迭代當前資料庫中的資料庫鍵,
SSCAN 命令用于迭代集合鍵中的元素,
HSCAN 命令用于迭代哈希鍵中的鍵值對,
ZSCAN 命令用于迭代有序集合中的元素(包括元素成員和元素分值),
用法和scan一樣
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/171989.html
標籤:其他
上一篇:愛了愛了!阿里爆款Spring進階寶典,涵蓋其所有技術堆疊(原始碼+實戰徹底玩轉Spring框架)
下一篇:2006-京淘Day11
