仓颉语言实现的Redis客户端SDK。接口设计兼容jedis接口语义,支持RESP2和RESP3协议,支持发布订阅模式,支持哨兵模式和集群模式。当前master分支适配仓颉1.0.0 LTS版本,分支Branch_cj0.53.18适配仓颉0.53.18 Beta版本。
仓颉Redis语言客户端
![]()
这是一款原生为仓颉设计的Redis客户端。已针对仓颉1.0.0 LTS版本进行适配,依赖于Hyperion TCP框架,由北京宝兰德软件股份有限公司开发完成。API设计参照了以下项目:
用户手册请参阅:用户手册
功能特点
- 支持RESP2和RESP3协议
- 接口设计兼容jedis接口语义
- 提供丰富的管理命令支持
- 支持单连接多线程模式
- 支持发布订阅模式
- 支持哨兵模式和集群模式
- 完善的单元测试覆盖
- 架构简洁,便于扩展
支持的版本
- Redis 7.x:目前已针对Redis 7.0.0——Redis 7.2.4版本完成兼容性测试
- Redis 6.x:目前已针对Redis 6.0.0——Redis 6.2.14版本完成兼容性测试 其他版本的兼容性测试正在逐步完善中,敬请期待
仓颉SDK版本与分支对应关系
| 仓颉SDK版本 | 分支 |
|---|---|
| 1.0.0 LTS | master |
| 0.60.5 | Branch_cj0.60.5 |
| 0.53.18 Beta | Branch_cj0.53.18 |
| 0.45.2和0.51.4 | Branch_cj0.51.4 |
工程目录结构
工程目录结构说明
|---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
脚本和函数命令
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
连接管理命令
AUTH, ECHO, PING, RESET
数据库命令
DBSIZE, FLUSHDB, FLUSHALL, SELECT, SWAPDB
访问控制列表命令
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 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 GET, CONFIG RESETSTAT, CONFIG REWRITE, CONFIG SET
服务管理命令
BGREWRITEAOF, BGSAVE, INFO, LASTSAVE, LATENCYDOCTOR, LOLWUT, REPLICAOF, SAVE, SHUTDOWN, SLAVEOF
其他
MEMORY DOCTOR, MEMORY PURGE, MEMORY STATS, ROLE, WAIT, WAITAOF
![]()
2.1 Redis命令处理模块的架构
Redis命令处理的架构图如下:

RedisCommand类
Redis命令的实现类 包含以下成员: commandType: Redis命令的名称 commandArgs: Redis命令的参数列表 response: Redis命令的响应消息,类型为RedisMessage exception: 执行Redis命令发生的异常
CommandArg类
封装Redis命令的基本类型参数,包括Array、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类
将RedisMessage转换为命令执行的结果
基本数据类型的RepsonseBuilder实现: StringResponseBuilder IntegerResponseBuilder DoubleResponseBuilder BoolResponseBuilder NillableStringResponseBuilder
集合类型的RepsonseBuilder实现: ListResponseBuilder SetOfResponseBuilder PrimitiveMapResponseBuilder<String, T> ListOfAnyResponseBuilder MapOfAnyResponseBuilder
ParameterizedRedisCommand类
RedisCommand的子类,支持将Redis命令的响应构建为类型T,包含成员RepsonseBuilder用于处理响应 注意: 需要返回响应的命令,可以使用RedisCommand类, 也可以使用ParameterizedRedisCommand类; 不需要返回响应的命令,只能使用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对象 需要实现以上2个接口: StringCommandsImpl类:提供String类型的操作命令对应的实现 StringCommansBuidlerImpl类:构建Sting类型相关命令对应的ParameterizedRedisCommand对象
RedisClient类需要实现StringCommands接口,并将String类型的相关方法委托给StringCommandsImpl类

String类型,支持超时参数的SET命令按如下方式构建(参考StringCommansBuidlerImpl类):
public func set(key: String, value: String, params: SetParams): ParameterizedRedisCommand<?String> {
let commandArgs = CommandArgs().add(StringArg(key)).add(StringArg(value))
let command = ParameterizedRedisCommand<?String>(
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<String>(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.1 通过源代码方式集成Redis客户端依赖
在使用仓颉版本0.60.5及以上时,若需引入Redis客户端依赖,必须设置环境变量CANGJIE_STDX_PATH,以明确指定stdx扩展包的存放路径。
以下为Windows X64平台设置环境变量的示例:
SET CANGJIE_STDX_PATH=D:\cangjie-stdx-windows-x64-0.60.5.1\windows_x86_64_llvm\dynamic\stdx
SET PATH=%CANGJIE_STDX_PATH%;%PATH%
Linux X64平台环境下环境变量设置示例:
export CANGJIE_STDX_PATH= /opt/cangjie-stdx-linux-x64-0.60.5.1/linux_x86_64_llvm/dynamic/stdx
export LD_LIBRARY_PATH=$CANGJIE_STDX_PATH:$LD_LIBRARY_PATH
仓颉1.0.0 LTS版本:在项目配置文件 cjpm.toml 中添加 dependencies 以引入 redis_sdk 依赖项:
[dependencies]
redis_sdk = {git = "https://gitcode.com/Cangjie-TPC/redis-sdk.git", branch = "master", version = "3.0.0"}
仓颉0.53.18 Beta版:在项目的 cjpm.toml 文件中新增 dependencies 项以引入 redis_sdk 依赖。
[dependencies]
redis_sdk = {git = "https://gitcode.com/Cangjie-TPC/redis-sdk.git", branch = "Branch_cj0.53.18", version = "2.0.0"}
仓颉版本0.45.2与0.51.4,请参照Branch_cj0.51.4分支中的说明。
更新依赖时,执行cjpm update命令将自动下载redis_sdk项目的依赖至~/.cjpm目录下:
$> cjpm update
3.2 编译Redis仓颉语言客户端并导入静态库依赖
编译Redis仓颉语言客户端,请参阅:用户手册
您可以选择引入预编译的静态库依赖,或者通过源码方式引入依赖,任选其一。具体操作请参考"1.1 通过源码方式引入Redis客户端依赖"。
对于仓颉0.53.4及以上版本,您需要首先确认目标平台对应的target-name:
例如,在Windows X64平台上执行cjc -v命令,将返回以下信息:
$cjc -v
Cangjie Compiler: 0.53.4 (cjnative)
Target: x86_64-w64-mingw32
例如在Linux X64平台上执行cjc -v命令,返回结果如下:
$cjc -v
Cangjie Compiler: 0.53.4 (cjnative)
Target: x86_64-unknown-linux-gnu
在仓颉 0.53.4 版本中,需要在项目的 cjpm.toml 文件中添加与平台对应的二进制依赖项。以 Linux X64 平台为例:
[target.x86_64-unknown-linux-gnu.bin-dependencies.package-option]
"hyperion.buffer" = "${path_to_redis_sdk}/build/release/hyperion/hyperion.buffer.cjo"
"hyperion.logadapter" = "${path_to_redis_sdk}/build/release/hyperion/hyperion.logadapter.cjo"
"hyperion.objectpool" = "${path_to_redis_sdk}/build/release/hyperion/hyperion.objectpool.cjo"
"hyperion.threadpool" = "${path_to_redis_sdk}/build/release/hyperion/hyperion.threadpool.cjo"
"hyperion.transport" = "${path_to_redis_sdk}/build/release/hyperion/hyperion.transport.cjo"
"redis_sdk.client.api" = "${path_to_redis_sdk}/build/release/redis_sdk/redis_sdk.client.api.cjo"
"redis_sdk.client.commands" = "${path_to_redis_sdk}/build/release/redis_sdk/redis_sdk.client.commands.cjo"
"redis_sdk.client.commands.impl" = "${path_to_redis_sdk}/build/release/redis_sdk/redis_sdk.client.commands.impl.cjo"
"redis_sdk.client" = "${path_to_redis_sdk}/build/release/redis_sdk/redis_sdk.client.cjo"
请参考以下版本:仓颉0.45.2与0.51.4。具体说明,请查阅Branch_cj0.51.4分支。
3.3 创建RedisClient以执行Redis指令集
import redis_sdk.client.api.*
import redis_sdk.client.commands.*
import redis_sdk.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
}
3.4 利用RedisClient进行Redis命令的操作执行
import redis_sdk.client.api.*
import redis_sdk.client.commands.*
import redis_sdk.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")
}
}
![]()
redis-sdk项目由北京宝兰德软件股份有限公司的中间件团队负责实现与维护。如需技术支持或意见反馈,请通过Issue提出。
本项目遵循Apache License 2.0协议,我们欢迎您提交PR或以任何形式参与贡献力量。
本项目的commiter为:@hapinwater