首页>教程>Dapr教程>Dapr状态管理高级特性

需要支持?

如果通过文档没办法解决您的问题,请提交工单获取我们的支持!

Dapr状态管理高级特性

内容纲要

Dapr 状态管理的高级特性有:

  • 并发
  • 一致性
  • 事务性

状态管理高级特性之并发控制

设计分析

dapr state 目前要求操作的并发控制有两个: FirstWrite 和 LastWrite。

const (
	FirstWrite = "first-write"
	LastWrite  = "last-write"
)

LastWrite (Last Write Win模式)就简单了,每个写操作都只需要简单的执行即可,无需考虑是否并发。事实上就是不做并发控制。

FirstWrite (First Write Win模式)复杂一些,当有多个操作进行并发写时,只有第一个能成功。因此,必须有机制能够在执行写操作时判断从上次读到这次写,期间 state 数据没有被修改。也就是需要实现 CAS操作:CAS = Compare And Set。

Dapr state 的设计是引入一个名为 ETag 的机制:

  • ETag 是一个整型,每个状态都会关联一个 ETag
  • 每次创建或修改 state 时,ETag都会递增
  • 进行写操作时:先读取现有state,拿到当前的ETag;在提交写操作时,传入之前的ETag。底层 state store的实现应该在执行写操作之前检查ETag是否匹配。

具体到各个操作:

  1. Save state
    • grpc API:在请求的SaveStateRequest中通过 etag 字段提供
    • HTTP API:在请求的json内容中通过etag字段提供
  2. Get state
    • grpc API:在应答的 GetStateResponse 中通过 etag 字段提供
    • HTTP API:在应答的 ETag header中提供
  3. Get Bulk
    • grpc API:在应答的 GetBulkStateResponse 中通过 etag 字段提供
    • HTTP API:在应答的json中通过 etag 字段提供
  4. Delete State
    • grpc API:在请求的 DeleteStateRequest 中通过 etag 字段提供
    • HTTP API:通过请求的 If-Match header提供

实现分析

Redis实现

redis 为了实现 state 要求的 etag,就必须在常规的key/value存储模型上增加 key/etag 的存储,实现方式就是 key / map as value,将一个 map 作为value(刚好redis本身也支持map结构)。然后在map中存储 data / version 等多个信息:

  • key=version,存储ETag需要的version
  • key=data,存储state的实际数据

读取state的时候将整个map as value读取,然后分别取data和version即可。

但写操作会比较麻烦, redis 本身不直接提供对多个字段的原子操作方式,因此在save和delete操作时需要通过LUA脚本来完成。

  • concurrency 设置为 first-write :需要通过 etag 实现 CAS (Compare And Set)
  • concurrency 设置为 last-write :忽略 etag,即使请求设置了也要重置

状态管理高级特性之一致性

设计分析

dapr state 目前对操作的一致性要求有两个: strong 和 eventual。

const (
	Strong     = "strong"
	Eventual   = "eventual"
)

eventual 就简单了,每个写操作都只需要简单的执行即可,后续的同步等操作由底层实现自行保证。

FirstWrite (First Write Win模式)复杂一些,当有多个操作进行并发写时,只有第一个能成功。因此,必须有机制能够在执行写操作时判断从上次读到这次写,期间 state 数据没有被修改。也就是需要实现 CAS操作:CAS = Compare And Set。

Dapr state 的设计是引入一个名为 ETag 的机制:

  • ETag 是一个整型,每个状态都会关联一个 ETag
  • 每次创建或修改 state 时,ETag都会递增
  • 进行写操作时:先读取现有state,拿到当前的ETag;在提交写操作时,传入之前的ETag。底层 state store的实现应该在执行写操作之前检查ETag是否匹配。

具体到各个操作:

  1. Save state
    • grpc API:在请求的SaveStateRequest中通过 etag 字段提供
    • HTTP API:在请求的json内容中通过etag字段提供
  2. Get state
    • grpc API:在应答的 GetStateResponse 中通过 etag 字段提供
    • HTTP API:在应答的 ETag header中提供
  3. Get Bulk
    • grpc API:在应答的 GetBulkStateResponse 中通过 etag 字段提供
    • HTTP API:在应答的json中通过 etag 字段提供
  4. Delete State
    • grpc API:在请求的 DeleteStateRequest 中通过 etag 字段提供
    • HTTP API:通过请求的 If-Match header提供

实现分析

Redis实现 

redis 为了实现 state 要求的 etag,就必须在常规的key/value存储模型上增加 key/etag 的存储,实现方式就是 key / map as value,将一个 map 作为value(刚好redis本身也支持map结构)。然后在map中存储 data / version 等多个信息:

  • key=version,存储ETag需要的version
  • key=data,存储state的实际数据

读取state的时候将整个map as value读取,然后分别取data和version即可。

但写操作会比较麻烦, redis 本身不直接提供对多个字段的原子操作方式,因此在save和delete操作时需要通过LUA脚本来完成。

  • concurrency 设置为 first-write :需要通过 etag 实现 CAS (Compare And Set)
  • concurrency 设置为 last-write :忽略 etag,即使请求设置了也要重置

状态管理高级特性之事务性

设计分析

如果 state store 要支持事务,则要求实现 TransactionalStore 接口:

type TransactionalStore interface {
   // Init方法是和普通store接口一致的
   Init(metadata Metadata) error
   // 增加的是 Multi 方法
   Multi(request *TransactionalStateRequest) error
}

Runtime ExecuteStateTransaction 方法会调用 state store 的 multi 方法。

实现分析

Redis实现

dapr redis state store的事务实现,是通过 redis-go 封装的 TxPipeline 实现的。

TODO:

  • redis-go 如何实现的
  • redis如何实现事务?multi?

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
今日签到
有新私信 私信列表
搜索