Garnet API
IGarnetApi 接口包含暴露给公共 API 的操作符,这些操作符最终对 Garnet 中存储的键执行操作。它继承自 IGarnetReadApi(只读命令接口)和 IGarnetAdvancedApi(高级 API 调用)。
要向 API 添加新的操作符或命令,如果该命令执行只读操作,则在 IGarnetReadApi 接口中添加新的方法签名;否则,在 IGarnetApi 中添加。
向 Garnet 添加新命令
如果您正在尝试为特定的 Garnet 服务器实例添加命令,请参阅自定义命令
要向 Garnet 添加新命令,请按照以下步骤操作:
- 如果您的命令作用于一个对象(例如 List、SortedSet 等),请在
Garnet.server/Objects/[ObjectName]/[ObjectName]Object.cs
中为[ObjectName]Operation
枚举添加一个新的枚举值。
否则,请在Garnet.server/Resp/RespCommand.cs
中为RespCommand
枚举添加一个新的枚举值。 - 将新命令名称的解析逻辑添加到
Garnet.server/Resp/RespCommand.cs
。如果命令具有固定数量的参数,则将解析逻辑添加到 FastParseCommand 方法中。否则,将解析逻辑添加到 FastParseArrayCommand 方法中。 - 如果命令执行只读操作,则向 IGarnetReadApi 添加新的方法签名;否则,向 IGarnetApi 添加(
Garnet.server/API/IGarnetAPI.cs
)。 - 向 RespServerSession 类添加一个新方法。此方法将从网络缓冲区解析命令,调用存储层 API(在步骤 #3 中声明的方法),并将 RESP 格式的响应写入网络缓冲区(请注意,RespServerSession 类分布在多个 .cs 文件中,特定于对象的命令将位于
Garnet.server/Resp/Objects/[ObjectName]Commands.cs
下,而其他命令将根据命令类型位于Garnet.server/Resp/[Admin|Array|Basic|etc...]Commands.cs
下)。 - 回到
Garnet.server/Resp/RespCommand.cs
,分别将新命令案例添加到 ProcessBasicCommands 或 ProcessArrayCommands 方法中,调用在步骤 #4 中添加的方法。 - 向 StorageSession 类添加一个新方法。此方法是存储层的一部分。此存储 API 仅执行 RMW 或读取操作调用,它封装了 Tsavorite API。(请注意,StorageSession 类分布在多个 .cs 文件中,对象存储操作将位于
Garnet.server/Storage/Session/ObjectStore/[ObjectName]Ops.cs
下,而主存储操作主要位于Garnet.server/Storage/Session/MainStore/MainStoreOps.cs
下,但有一些例外)。
要实现新命令的存储级别逻辑,请根据新命令类型遵循以下指南:- 单键对象存储命令:如果您要添加一个对单个对象进行操作的命令,此方法的实现将只是一个
[Read|RMW]ObjectStoreOperation[WithOutput]
调用,该调用反过来将调用Garnet.server/Objects/[ObjectName]/[ObjectName]Object.cs
中的Operate
方法,您需要在其中为命令添加一个新的案例,并在Garnet.server/Objects/[ObjectName]/[ObjectName]ObjectImpl.cs
中添加特定于对象的命令实现。 - 多键对象存储命令:如果您要添加一个对多个对象进行操作的命令,您可能需要创建一个事务,在其中您将适当地锁定键(使用
TransactionManager
实例)。然后,您可以对多个对象进行操作(例如使用GET
和SET
操作)。 - 主存储命令:如果您要添加一个对主存储进行操作的命令,您需要调用 Tsavorite 的
Read
或RMW
方法。如果您正在调用RMW
,您将需要在Garnet.server/Storage/Functions/MainStore/RMWMethods.cs
中实现新命令的初始化和就地/复制更新功能。
- 单键对象存储命令:如果您要添加一个对单个对象进行操作的命令,此方法的实现将只是一个
- 如果命令支持在事务上下文中调用,请在
TransactionManager.GetKeys
方法中为命令添加一个新的案例,并返回命令所需的相应键锁(Garnet.server/Transaction/TxnKeyManager.cs
)。 - 添加测试以在有效和无效条件下运行命令并检查其输出,如果适用,同时使用
SE.Redis
和LightClient
进行测试。对于对象命令,将测试添加到Garnet.test/Resp[ObjectName]Tests.cs
。对于其他命令,根据命令类型添加到Garnet.test/RespTests.cs
或Garnet.test/Resp[AdminCommands|etc...]Tests.cs
。 - 将新支持的命令文档添加到
website/docs/commands/
下的相应 markdown 文件中,并在website/docs/commands/api-compatibility.md
中指定该命令为受支持。 - 按照下一个部分添加命令信息
在开始实现命令逻辑之前,添加一个调用新命令的基本测试,这样在后续调试和实现缺失逻辑时会更容易。
添加命令信息
Garnet 中每个受支持的 RESP 命令都应该在 Garnet.server/Resp/RespCommandsInfo.json
中有一个条目,指定命令的信息。
命令的信息可以手动添加,但我们建议使用 CommandInfoUpdater
工具来更新 JSON 文件(可在 playground/
下找到)。
CommandInfoUpdater
工具计算 Garnet.server/Resp/RespCommandsInfo.json
中现有命令与 CommandInfoUpdater/SupportedCommands.cs
中指定命令之间的差异。然后,它会根据需要尝试添加/删除命令信息。
仅限 Garnet 命令的信息从 CommandInfoUpdater/GarnetCommandsInfo.json
中检索,其他 RESP 命令的信息从外部 RESP 服务器中检索(您需要本地运行或有权访问该服务器才能运行此工具)。
要向 Garnet 添加命令信息,请按照以下步骤操作:
- 将受支持的命令及其受支持的子命令(如果适用)添加到
CommandInfoUpdater/SupportedCommands.cs
。 - 如果您正在添加特定于 Garnet 的命令,请将其信息添加到
CommandInfoUpdater/GarnetCommandsInfo.json
。 - 在本地启动一些 RESP 服务器。
- 构建并运行该工具(有关语法帮助,请使用
-h
或--help
运行该工具)。
cd playground/CommandInfoUpdater
dotnet run -- --output ../../libs/resources