# redis-sdk
**Repository Path**: cangjie-tpc/redis-sdk
## Basic Information
- **Project Name**: redis-sdk
- **Description**: 仓颉语言实现的Redis客户端SDK。接口设计兼容jedis接口语义,支持RESP2和RESP3协议,支持发布订阅模式,支持哨兵模式和集群模式。
- **Primary Language**: Unknown
- **License**: Apache-2.0
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 9
- **Forks**: 0
- **Created**: 2024-07-02
- **Last Updated**: 2025-09-01
## Categories & Tags
**Categories**: database-dev
**Tags**: None
## README
# Redis仓颉语言客户端
仓颉原生Redis客户端。
依赖库为[Hyperion TCP框架](https://gitcode.com/Cangjie-TPC/hyperion.git),由[北京宝兰德软件股份有限公司](https://www.bessystem.com)实现。
API设计参考如下项目:
https://github.com/redis/jedis
https://github.com/lettuce-core/lettuce-io
用户手册请参考:[用户手册](./docs/Redis_SDK_User_Guide.md)
## 特性
1. 支持RESP2和RESP3协议
2. 接口设计兼容jedis接口语义
3. 丰富的管理命令支持
4. 支持单连接多线程模式
5. 支持发布订阅模式
6. 支持哨兵模式和集群模式
7. 完备的单元测试覆盖
8. 架构简洁,易于扩展
## 开发计划
1. 2024.3.22 完成支持单机模式的RESP2和RESP3协议的客户端,提供Beta版本
2. 2024.4.16 完成支持Sentinel集群模式的客户端,提供Beta版本
3. 2024.5.31 完成支持Redis集群模式的客户端,提供Beta版本
4. 2024.6.30 完成1.0.0 RC版本的发布
## 支持版本
Redis 7.x: 目前在Redis 7.0.0——Redis 7.2.4版本上完成兼容性测试
Redis 6.x: 目前在Redis 6.0.0——Redis 6.2.14版本上完成兼容性测试
其他版本的兼容性测试陆续完善中,敬请期待
## 工程目录结构
工程目录结构
```shell
|---samples Redis客户端使用示例目录
|---src Redis客户端源码目录
|---test Redis客户端单元测试目录
| |---UT 通用命令的单元测试目录
|---HLT 需要准备特殊环境的命令的单元测试
|---module.json
|---README.md
```
## 已经实现的命令
### BitMap数据类型操作命令
BITCOUNT, BITFIELD, BITFIELD_RO, BITOP, GETBIT, SETBIT, BITPOS
### 地理空间坐标
GEOADD, GEODIST, GEOHASH, GEOENCODE, GEODECODE, GEOPOS, GEORADIUS, GEORADIUS_RO, GEORADIUSBYMEMBER, GEORADIUSBYMEMBER_RO, GEOSEARCH, GEOSEARCHSTORE
### Key命令
COPY, DEL, DUMP, EXISTS, EXPIRE, EXPIREAT, EXPIRETIME, MOVE, KEYS, MIGRATE, MEMORYUSAGE, OBJECTENCODING, OBJECTFREQ, OBJECTIDLETIME, OBJECTREFCOUNT, PERSIST, PEXPIRE, PEXPIREAT, PEXPIRETIME, PTTL, RANDOMKEY, RENAME,RENAMENX, RESTORE, SCAN, SORT, SORT_RO, TOUCH, TTL, TYPE, UNLINK
### Hash数据类型操作命令
HDEL, HEXISTS, HGET, HGETALL, HINCRBY, HINCRBYFLOAT, HKEYS, HLEN, HMGET, HMSET, HRANDFIELD, HSCAN, HSET, HSETNX, HSTRLEN, HVALS
### List数据类型操作命令
BLMOVE, BLMPOP, BLPOP, BRPOP, BRPOPLPUSH, LINDEX, LINSERT, LLEN, LMOVE, LMPOP, LPOP, LPOS, LPUSH, LPUSHX, LRANGE, LREM, LSET, LTRIM, RPOP, RPOPLPUSH, RPUSH, RPUSHX
### Set数据类型操作命令
SADD, SCARD, SDIFF, SDIFFSTORE, SINTER, SINTERCARD, SINTERSTORE, SISMEMBER, SMEMBERS, SMOVE, SPOP, SRANDMEMBER, SREM, SSCAN, SUNION, SUNIONSTORE
### Stream数据类型操作命令
XACK, XADD, XAUTOCLAIM, XCLAIM, XDEL, XGROUP CREATE, XGROUP CREATECONSUMER, XGROUP DELCONSUMER, XGROUP DESTROY, XGROUP SETID, XINFO CONSUMERS, XINFO GROUPS, XINFO STREAM, XLEN, XPENDING, XRANGE, XREVRANGE, XREAD, XREADGROUP, XTRIM
### String数据类型操作命令
APPEND, DECR, DECRBY, GET, GETDEL, GETEX, GETRANGE, GETSET, INCR, INCRBY, INCRBYFLOAT, MGET, MSET, MSETNX, PSETEX, SET, SETEX, SETNX, SETRANGE, STRLEN, SUBSTR
### ZSet数据类型操作命令
BZMPOP, BZPOPMAX, ZADD, ZCARD, ZCOUNT, ZDIFF, ZDIFFSTORE, ZINCRBY, ZINTER, ZINTERCARD, ZINTERSTORE, ZLEXCOUNT, ZMSCORE, ZMPOP, ZPOPMIN, ZPOPMAX, ZRANDMEMBER, ZRANGE, ZRANGEBYSCORE, ZRANGESTORE, ZRANK, ZREM, ZREMRANGEBYRANK, ZREMRANGEBYSCORE, ZREVRANGE, ZREVRANGEBYLEX, ZREVRANGEBYSCORE, ZREVRANK, ZSCAN, ZSCORE, ZUNION, ZUNIONSTORE, ZREMRANGEBYLEX, ZRANGEBYLEX
### HyperLogLog命令
PFADD, PFCOUNT, PFMERGE
### Script和Function命令
EVAL, EVAL_RO, EVALSHA, EVALSHA_RO, SCRIPT EXISTS, SCRIPT FLUSH, SCRIPT KILL, SCRIPT LOAD
FCALL, FCALL_RO, FUNCTION DELETE, FUNCTION DUMP, FUNCTION FLUSH, FUNCTION KILL, FUNCTION LIST, FUNCTION LOAD, FUNCTION RESTORE, FUNCTION STATS
### Connection Mangement命令
AUTH, ECHO, PING, RESET
### DataBase 命令
DBSIZE, FLUSHDB, FLUSHALL, SELECT, SWAPDB
### ACL命令
ACL CAT, ACL DELUSER, ACL DRYRUN, ACL GENPASS, ACL GETUSER, ACL LIST, ACL LOAD, ACL LOG, ACL SAVE, ACL SETUSER, ACL USERS, ACL WHOAMI
### CLIENT命令
CLIENT GETNAME, CLIENT ID, CLIENT INFO, CLIENT KILL, CLIENT LIST, CLIENT NO-EVICT, CLIENT NO-TOUCH, CLIENT PAUSE, CLIENT SETINFO, CLIENT SETNAME, CLIENT UNBLOCK, CLIENT UNPAUSE
### CONFIG命令
CONFIG GET, CONFIG RESETSTAT, CONFIG REWRITE, CONFIG SET
### Server Mangement命令
BGREWRITEAOF, BGSAVE, INFO, LASTSAVE, LATENCYDOCTOR, LOLWUT, REPLICAOF, SAVE, SHUTDOWN, SLAVEOF
### 其他
MEMORY DOCTOR, MEMORY PURGE, MEMORY STATS, ROLE, WAIT, WAITAOF
## 1. 在工程中使用Redis仓颉语言客户端
### 1.1 通过源码方式引入Redis客户端依赖
仓颉0.51.4以上版本:在项目的cjpm.toml中添加dependencies引入redis_sdk依赖:
```
[dependencies]
redis_sdk = {git = "https://gitcode.com/Cangjie-TPC/redis-sdk.git", branch = "master", version = "1.0.0"}
```
仓颉0.45.2版本:在项目的module.json中添加requires引入redis_sdk依赖:
```
"requires": {
"redis_sdk": {
"organization": "Beijing Baolande Software Corporation",
"version": "1.0.0",
"branch": "master",
"git": "https://gitcode.com/Cangjie-TPC/redis-sdk.git"
}
},
```
更新依赖,运行cjpm update会自动下载依赖redis_sdk项目到~/.cjpm目录下
`$> cjpm update`
### 1.2 编译Redis仓颉语言客户端并导入静态库依赖
编译Redis仓颉语言客户端请参考:[用户手册](./docs/Redis_SDK_User_Guide.md)
引入编译好的静态库依赖和通过源码方式引入依赖,任意选取一种方式即可。 参考"1.1 通过源码方式引入Redis客户端依赖"。
仓颉0.51.4以上版本,需要先确定平台对应的target-name:
例如Windows X64平台执行`cjc -v`命令返回如下:
```
$cjc -v
Cangjie Compiler: 0.51.4 (cjnative)
Target: x86_64-w64-mingw32
```
例如Linux X64平台执行`cjc -v`命令返回如下:
```
$cjc -v
Cangjie Compiler: 0.51.4 (cjnative)
Target: x86_64-unknown-linux-gnu
```
在工程的cjpm.toml中添加平台对应的二进制依赖,以Linux X64为例:
```
[target.x86_64-unknown-linux-gnu.bin-dependencies.package-option]
"hyperion_hyperion.buffer" = "${path_to_redis_sdk}/build/release/hyperion/hyperion.buffer.cjo"
"hyperion_hyperion.logadapter" = "${path_to_redis_sdk}/build/release/hyperion/hyperion.logadapter.cjo"
"hyperion_hyperion.objectpool" = "${path_to_redis_sdk}/build/release/hyperion/hyperion.objectpool.cjo"
"hyperion_hyperion.threadpool" = "${path_to_redis_sdk}/build/release/hyperion/hyperion.threadpool.cjo"
"hyperion_hyperion.transport" = "${path_to_redis_sdk}/build/release/hyperion/hyperion.transport.cjo"
"redis_sdk_redis.client.api" = "${path_to_redis_sdk}/build/release/redis_sdk/redis.client.api.cjo"
"redis_sdk_redis.client.commands" = "${path_to_redis_sdk}/build/release/redis_sdk/redis.client.commands.cjo"
"redis_sdk_redis.client.commands.impl" = "${path_to_redis_sdk}/build/release/redis_sdk/redis.client.commands.impl.cjo"
"redis_sdk_redis.client" = "${path_to_redis_sdk}/build/release/redis_sdk/redis.client.cjo"
```
仓颉0.45.2版本,在工程的module.json中引入Redis仓颉语言客户端的静态库:
```
"package_requires": {
"package_option": {
"hyperion_hyperion.buffer": "${path_to_redis_sdk}/build/release/hyperion/hyperion.buffer.cjo",
"hyperion_hyperion.logadapter": "${path_to_redis_sdk}/build/release/hyperion/hyperion.logadapter.cjo",
"hyperion_hyperion.objectpool": "${path_to_redis_sdk}/build/release/hyperion/hyperion.objectpool.cjo",
"hyperion_hyperion.threadpool": "${path_to_redis_sdk}/build/release/hyperion/hyperion.threadpool.cjo",
"hyperion_hyperion.transport": "${path_to_redis_sdk}/build/release/hyperion/hyperion.transport.cjo",
"redis_sdk_redis.client.api": "${path_to_redis_sdk}/build/release/redis_sdk/redis.client.api.cjo",
"redis_sdk_redis.client.commands": "${path_to_redis_sdk}/build/release/redis_sdk/redis.client.commands.cjo",
"redis_sdk_redis.client.commands.impl": "${path_to_redis_sdk}/build/release/redis_sdk/redis.client.commands.impl.cjo",
"redis_sdk_redis.client": "${path_to_redis_sdk}/build/release/redis_sdk/redis.client.cjo"
},
"path_option": []
},
```
### 1.3 创建RedisClient用于执行Redis命令
```
from redis_sdk import redis.client.api.*
from redis_sdk import redis.client.commands.*
from redis_sdk import redis.client.*
public func getRedisClient(): RedisClient {
let redisClient = RedisClientBuilder.builder()
.host("127.0.0.1")
.port(6379)
.readTimeout(Duration.second * 60)
.writeTimeout(Duration.second * 30)
.receiveBufferSize(32768)
.sendBufferSize(32768)
.build()
return redisClient
}
```
### 1.4 使用RedisClient执行Redis命令操作
```
from redis_sdk import redis.client.api.*
from redis_sdk import redis.client.commands.*
from redis_sdk import redis.client.*
main() {
// 获取Redis客户端
let client = getRedisClient()
// 执行 SET testKey1 testValue1 XX命令
let result = client.set("testKey1", "testValue1", SetParams().xx())
if (let Some(result) <- result) {
println(result)
} else {
println("nil")
}
// 执行 GET testKey1命令
var getResult = client.get("testKey1")
if (let Some(getResult) <- getResult) {
println(getResult)
} else {
println("nil")
}
}
```
## 2. 扩展Redis仓颉语言客户端
### 2.1 Redis命令处理模块的架构
Redis命令处理的架构图如下:

#### RedisCommand类
Redis命令的实现类
包含以下成员:
commandType: Redis命令的名称
commandArgs: Redis命令的参数列表
response: Redis命令的响应消息,类型为RedisMessage
exception: 执行Redis命令发生的异常
#### CommandArg类
封装Redis命令的基本类型参数,包括Array<Byte>、String、Integer、Double
#### CommandArgs类
Redis命令的参数列表,包含CommandArg的列表
#### CompositeArgs类
封装Redis命令参数列表中存在关联关系的多个参数
调用buildArgs(CommandArgs)方法将多个存在关联的参数添加到CommandArgs的参数列表中
#### RedisMessage类
封装Redis命令的响应消息
RESP2协议对应的RedisMessage:
SIMPLE_STRINGS: StringRedisMessage
SIMPLE_ERRORS: ErrorRedisMessage
INTEGERS: IntegerRedisMessage
BULK_STRINGS: BulkStringRedisMessage
ARRAYS: ArraysRedisMessage
RESP3协议对应的RedisMessage:
NULLS:NullArraysRedisMessage
BOOLEANS:BooleanRedisMessage
DOUBLES:DoubleRedisMessage
BIG_NUMBERS:BigNumberRedisMessage
BULK_ERRORS:BulkErrorRedisMessage
VERBATIM_STRINGS:VerbatimRedisMessage
MAPS:MapRedisMessage
SETS:SetRedisMessage
PUSHES:PushesRedisMessage
#### ResponseBuilder<T>类
将RedisMessage转换为命令执行的结果
基本数据类型的RepsonseBuilder实现:
StringResponseBuilder
IntegerResponseBuilder
DoubleResponseBuilder
BoolResponseBuilder
NillableStringResponseBuilder
集合类型的RepsonseBuilder实现:
ListResponseBuilder<T>
SetOfResponseBuilder<T>
PrimitiveMapResponseBuilder<String, T>
ListOfAnyResponseBuilder
MapOfAnyResponseBuilder
#### ParameterizedRedisCommand<T>类
RedisCommand的子类,支持将Redis命令的响应构建为类型T,包含成员RepsonseBuilder<T>用于处理响应
注意:
需要返回响应的命令,可以使用RedisCommand类, 也可以使用ParameterizedRedisCommand<T>类;
不需要返回响应的命令,只能使用RedisCommand类
### 2.2 Redis编解码模块的架构
Redis编解码处理的架构图如下:

#### MessageCompletedHandler接口
解码二进制报文时,判断二进制报文是否包含完整的消息报文
#### ByteToRedisMessageDecoder类
RESP协议解码器实现,将RESP协议的二进制报文转换为RedisMessage
该类实现了MessageCompletedHandler接口
#### RedisCommandToByteEncoder类
RESP协议编码器实现,将RedisCommand编码为RESP协议的二进制报文
#### RedisCodec类
实现了Hyperion TCP框架的IOFilter接口,处理Redis命令和Redis响应的编解码
#### RedisCommandHandler类
实现了Hyperion TCP框架的IOFilter接口,处理RedisMessage和RedisCommand的关联
#### RedisSubscriberHandler类
实现了Hyperion TCP框架的IOFilter接口,处理RedisMessage和Redis订阅者的关联
在未切换成订阅模式之前,处理方式和RedisCommandHandler类一致(处理认证和握手相关命令)
切换成订阅模式之后,只能执行以下命令:
SUBSCRIBE channel \[channel ...\]
PSUBSCRIBE pattern \[pattern ...\]
UNSUBSCRIBE channel \[channel ...\]
PUNSUBSCRIBE pattern \[pattern ...\]
UNSUBSCRIBE
PUNSUBSCRIBE
PING
PING message
#### RedisClientConfig
记录Redis客户端的参数配置
#### RedisClientBuilder类
用于创建RedisClient对象,RedisClient可以执行Redis命令
#### RedisClient类
执行Redis命令,并返回命令执行的结果
#### RedisSubscriberBuilder类
用于创建RedisSubscriber对象,RedisSubscriber可以订阅消息
#### RedisSubscriber类
订阅Redis频道的消息
### 2.3 编写Redis命令的实现
对于一个特定的数据类型,例如String类型,需要提供以下2个接口:
StringCommands接口:定义String类型的操作命令对应的接口
StringCommansBuidldler接口:构建Sting类型相关命令对应的ParameterizedRedisCommand<T>对象
需要实现以上2个接口:
StringCommandsImpl类:提供String类型的操作命令对应的实现
StringCommansBuidlerImpl类:构建Sting类型相关命令对应的ParameterizedRedisCommand<T>对象
RedisClient类需要实现StringCommands接口,并将String类型的相关方法委托给StringCommandsImpl类

String类型,支持超时参数的SET命令按如下方式构建(参考StringCommansBuidlerImpl类):
```
public func set(key: String, value: String, params: SetParams): ParameterizedRedisCommand {
let commandArgs = CommandArgs().add(StringArg(key)).add(StringArg(value))
let command = ParameterizedRedisCommand(
CommandType.SET,
commandArgs,
params,
ResponseBuilderFactory.nillableStringBuilder
)
return command
}
```
String类型,支持超时参数的SET命令的实现如下:
```
public func set(key: String, value: String, params: SetParams): ?String {
let redisCommand = RedisCommandBuilder.set(key, value, params)
return executeCommand(redisCommand)
}
```
调用String类型,支持超时参数的SET命令:
```
let client = RedisClientBuilder.builder()
.host(servHost)
.port(servPort)
.password(servPass)
.build()
// 500秒后超时
let result = client.set(myKey, myValue,
SetParams().exAt(DateTime.now().addSeconds(500).toUnixTimeStamp().toSeconds())
```
## 3. 技术支持和建议
redis-sdk项目由[北京宝兰德软件股份有限公司](https://www.bessystem.com)中间件团队实现并维护。 欢迎大家试用,并提供宝贵的意见和建议。
技术支持和意见反馈请提[Issue](https://gitcode.com/Cangjie-TPC/redis-sdk/issues)。