網站首頁 編程語言 正文
1.背景
在使用jedis客戶端操作redis數據的過程中,發現了一個通用的方法sendCommand,封裝了redis的所有命令,代碼路徑:redis.clients.jedis.BinaryJedis#sendCommand(redis.clients.jedis.commands.ProtocolCommand, byte[]...),具體代碼如下
public Object sendCommand(ProtocolCommand cmd, byte[]... args) {
this.checkIsInMultiOrPipeline();
this.client.sendCommand(cmd, args);
return this.client.getOne();
}
2.封裝使用sendCommand方法
封裝代碼
public void sendCommandWrapper(List<List<byte[]>> commandList) {
Jedis jedis = new Jedis("127.0.0.1",3306);
for (List<byte[]> command : commandList) {
byte[][] splitResult = command.stream().toArray(byte[][]::new);
for (byte[] cmd : command) {
jedis.sendCommand(() -> splitResult[0],
Arrays.copyOfRange(splitResult, 1, splitResult.length));
}
}
}
方法入參
參數類似如下
[[["set"],["a"],["v"]],[["set"],["a"],["b"]]],[["set"],["a"],["1"]]]]
然后把每個字符換成byte
[[[115, 101, 116], [97], [118]], [[115, 101, 116], [97], [98]], [[115, 101, 116], [97], [49]]]
3.存在的問題
sendCommand方法可以傳遞string的命令轉成的byte[]參數,但是其中有兩個特例
需要注意的特例
zset的score是有符號的浮點型
Pexpireat key 時間戳:時間戳是long型
問題歸納
以“Pexpireat key 時間戳”命令為例,long型時間戳通過redis協議到redis底層存儲是byte[]的方式,使用sendCommand的時候傳遞的命令入參也是byte[],但是這兩種byte[]不是同一種byte[]。
這兩種 byte[] 不同的主要原因是它們所表示的含義不同。
在使用 Redis 命令時,我們需要將命令的參數轉換為 byte[] 格式,以便可以發送給 Redis 服務器。這里的 byte[] 實際上是字符串的字節數組表示。Redis 協議是基于文本的,即它要求在與服務器通信時發送文本字符串,因此發送給 Redis 服務器的 byte[] 實際上是表示字符串的字節數組。
String.valueOf(redisTTLLong).getBytes(StandardCharsets.UTF_8)
而在 Redis 底層存儲中,時間戳所表示的含義是一個數字,而不是一個字符串。在底層存儲中,Redis 將時間戳轉換為了二進制形式,即一個 byte[] 數組。這個 byte[] 數組表示的是一個數字,它在內存中以二進制補碼的形式存儲。
//比如從底層取出來的byte,想轉回時間戳需要的轉換邏輯:?byte轉long
private static long convertRedisTTLToTimestamp(byte[] ttlBytes) {
// Convert the byte array to an 8-byte binary string
byte[] binaryBytes = new byte[8];
for (int i = 0; i < 8; i++) {
binaryBytes[i] = i < ttlBytes.length ? ttlBytes[i] : 0;
if (binaryBytes[i] < 0) {
binaryBytes[i] += 256;
}
}
// Rearrange the binary string according to the big endian byte order
long timestamp = 0L;
for (int i = 0; i < 8; i++) {
timestamp = (timestamp << 8) + (binaryBytes[i] & 0xff);
}
// returns the converted timestamp in milliseconds
return timestamp;
}
因此,這兩種 byte[] 不同的原因在于它們所表示的含義不同。一個表示字符串,一個表示數字的二進制補碼。雖然它們都是 byte[] 類型,但它們的內部存儲和解析方式是不同的。
4.總結
使用jedis的sendCommand命令時,要記住要傳入的參數,原本屬于數值類型時,需要轉byte[]數組是直接轉成字符串的字節數組。也就是把long時間戳通過String.valueOf(redisTTLLong).getBytes(StandardCharsets.UTF_8)命令轉換出來的byte[]。
請勿與long轉byte等相關的補碼、大小端等概念混淆。
原文鏈接:https://blog.csdn.net/Mint6/article/details/130036916
- 上一篇:沒有了
- 下一篇:沒有了
相關推薦
- 2022-05-17 bat批處理之字符串操作的實現_DOS/BAT
- 2022-05-31 C++核心編程之內存分區詳解_C 語言
- 2022-04-21 Python?數據類型中的字符串和數字_python
- 2022-11-14 Windows進程的創建與結束
- 2022-09-10 Python學習筆記嵌套循環詳解_python
- 2022-09-24 C#實現對象的序列化和反序列化_C#教程
- 2022-05-19 詳解QTreeWidget隱藏節點的兩種方式_C 語言
- 2022-12-25 Flutter開發通用頁面Loading組件示例詳解_Android
- 欄目分類
-
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支