跳到主要内容

服务器端事务

自定义事务允许添加新事务并将其注册到 Garnet。然后可以从任何 Garnet 客户端调用此注册事务,以在 Garnet 服务器上执行事务。

开发自定义服务器端事务

CustomTransactionProcedure 是所有自定义事务的基类。要开发新事务,必须扩展此基类,然后包含自定义逻辑。新自定义事务中有三个方法需要实现

  • Prepare<TGarnetReadApi>(TGarnetReadApi api, ref CustomProcedureInput procInput)
  • Main<TGarnetApi>(TGarnetApi api, ref CustomProcedureInput procInput, ref MemoryResult<byte> output)
  • Finalize<TGarnetApi>(TGarnetApi api, ref CustomProcedureInput procInput, ref MemoryResult<byte> output)

Prepare 方法的实现必须使用下面描述的可用实用方法设置将参与事务的键。Main 方法是执行实际操作的地方,因为在 Prepare 方法中为设置的键所需的锁已获取。Main 方法还会生成事务的输出。解锁键之后是 Finalize 阶段,它可以包含对存储的任何非事务性读写操作,并且也可以写入输出。Finalize 还允许用户编写复杂的非事务性脚本:Prepare 应该简单地返回 false,而 Main 则留空不实现。

这些是开发自定义事务的辅助方法。

  • AddKey(ArgSlice key, LockType type, bool isObject) 此方法用于将指定键添加到锁定集。它接受三个参数:key(要添加的键)、type(要应用的锁类型)和 isObject(一个布尔值,指示该键是否表示一个对象)。
  • RewindScratchBuffer(ref ArgSlice slice) 如果临时缓冲区包含给定的 ArgSlice,此方法负责回退(弹出)临时缓冲区的最后一个条目。它接受对 ArgSlice 参数的引用,并返回一个布尔值,指示回退操作是否成功。
  • CreateArgSlice(ReadOnlySpan<byte> bytes) 此方法用于从给定的 ReadOnlySpan<byte> 在临时缓冲区中创建 ArgSlice。它接受 ReadOnlySpan<byte> 参数,表示参数,并返回 ArgSlice 对象。
  • CreateArgSlice(string str) 此方法与前一个方法类似,但它从给定字符串以 UTF8 格式在临时缓冲区中创建 ArgSlice。它接受字符串参数并返回 ArgSlice 对象。
  • GetNextArg(ref CustomProcedureInput procInput, ref int offset) 此方法用于从指定偏移量的输入中检索下一个参数。它接受表示输入的 ArgSlice 参数和对 int 偏移量的引用。它返回表示参数作为跨度的 ArgSlice 对象。该方法在内部读取带有长度标头的指针以提取参数。这些成员函数提供了实用和便捷的方法,用于在 CustomTransactionProcedure 类中操作和处理事务数据、临时缓冲区和输入参数。

注意 当在 IGarnetApi 上多次调用具有大输出的 API 时,可能会耗尽内部缓冲区容量。如果预期会出现此类使用场景,则可以按如下所述重置缓冲区。

  • 使用 IGarnetApi.GetScratchBufferOffset 检索初始缓冲区偏移量
  • IGarnetApi 上调用必要的 API
  • 使用 IGarnetApi.ResetScratchBuffer(offset) 将缓冲区重置回原来的位置

自定义事务的注册通过在 Garnet 服务器对象的 RegisterAPI 对象上调用 NewTransactionProc(string name, int numParams, Func<CustomTransactionProcedure> proc) 方法来完成,并附带其名称、参数数量以及返回自定义事务类实例的方法。
也可以从客户端注册自定义事务(作为管理员命令,前提是代码已存在于服务器上),方法是使用 REGISTERCS 命令(请参阅自定义命令)。

执行

自定义事务由 TransactionManager 类中的 RunTransactionProc 方法执行。可以通过使用自定义事务详细信息调用 RUNTXP 命令或使用注册时使用的自定义事务名称来调用此方法。

初始阶段通过调用自定义事务的 Prepare 方法执行,该方法使用 AddKey 方法添加需要锁定的键。如果 Prepare 方法返回 false 而失败,则调用事务管理器的 Reset(false) 以重置自身。否则,它会继续执行调用 TransactionManager 类的 Run 方法的下一步。请参阅上面对该方法的描述。如果 Run 方法失败,事务管理器也会被重置。

下一步,它将继续调用自定义事务的 Main 方法实现,该方法执行事务的核心逻辑。成功完成后,它将继续记录事务信息。另一方面,如果 Main 方法通过抛出异常而失败,则会调用 Reset(true) 以解锁任何锁定的键并重置自身。

无论实际事务成功与否,Finalize 阶段都会在最后被调用。如前所述,它可以包含对存储的非事务性逻辑,并且可以生成输出。