# 状态

Kuiper 支持有状态的规则流。Kuiper 中有两种状态：

1. 窗口操作和可回溯源的内部状态。
2. 对流上下文扩展公开的用户状态，可参考 [状态存储](../extension/overview.md#state-storage)。

# 容错

默认情况下，所有状态仅驻留在内存中，这意味着如果流异常退出，则状态将消失。

为了使状态容错，Kuipler 需要将状态检查点放入永久性存储中，以便在发生错误后恢复。

## 启用检查点

将规则选项 qos 设置为1或2将启用检查点。 通过设置 checkpointInterval 选项配置检查点间隔时间。

当在流处理应用程序中出现问题时，可能会造成结果丢失或重复。 对于 qos 的3个选项，其对应行为将是：

1. 最多一次（0）：Kuiper 不会采取任何行动从问题中恢复
2. 至少一次（1）：没有任何结果丢失，但是您可能会遇到重复的结果
3. 恰好一次（2）：没有丢失或重复任何结果

考虑到 Kuiper 通过回溯和重播源数据流从错误中恢复，将理想情况描述为恰好一次时，并不意味着每个事件都会被恰好处理一次。 相反，这意味着每个事件将只会对由 Kuiper 管理的状态造成一次影响。

如果您不需要“恰好一次”，则可以通过使用 AT_LEAST_ONCE 配置 Kuiper，进而获得一些更好的效果。

## 恰好一次端到端

### 源考虑

要获得流的端到端 qos，源必须是可回溯的。这意味着在恢复之后，可以依据检查点偏移量将源恢复，并重新发送数据，这样就可以从上次错误中重放整个流。

对于扩展源，用户必须实现 api.Rewindable 接口以及默认的 api.Source 接口。 Kuiper 将在内部处理回溯。

```go
type Rewindable interface {
	GetOffset() (interface{}, error)
	Rewind(offset interface{}) error
}
```

### 目标考虑

我们不能保证目标仅接收一次数据。 如果在检查点期间发生错误，则某些已经发送到目标的状态不会被检查到。 这些状态将被重放，因为它们没有被检查而无法恢复。 在这种情况下，目标可能会多次接收它们。

要实施“恰好一次”，用户必须针对各种目标系统量身定制重复数据消除功能。