在 Active-Active 数据库中存储 JSON

Active-Active 数据库的 JSON 支持和冲突解决规则。

RedisJSON v2.2 为 Active-Active Redis Enterprise 数据库 添加了对 JSON 的支持。

该设计基于 Kleppmann 和 Beresford 的 无冲突复制 JSON 数据类型,但实现中包含一些更改。此外,还从这篇论文中改编了多个 冲突解决规则 示例。

创建活动-活动 JSON 数据库

要在活动-活动数据库中使用 JSON,您必须在创建数据库期间启用 JSON。

活动-活动 Redis Cloud 数据库默认情况下添加 JSON。有关详细信息,请参阅 Redis Cloud 文档中的 创建活动-活动数据库

在 Redis Enterprise 软件中,JSON 默认情况下未为活动-活动数据库启用。要在 Redis Enterprise 软件中创建活动-活动 JSON 数据库,

  1. 请参阅 Redis Enterprise 软件文档中的 创建活动-活动地理复制数据库,了解先决条件和详细步骤。

  2. 在“创建活动-活动数据库”屏幕的“功能”部分中,选择“JSON”。

    Select JSON from the Capabilities section.
    注意
    当您选择“JSON”时,“搜索和查询”也会默认选中,以允许您索引和查询 JSON 文档。如果您不想使用这些附加功能,可以取消选中“搜索和查询”复选框。
  3. 配置其他数据库设置。

  4. 选择“创建”。

命令差异

某些 JSON 命令在活动-活动数据库中工作方式不同。

JSON.CLEAR

JSON.CLEAR 重置 JSON 数组和对象。它支持活动-活动数据库中不同实例对 JSON 文档的并发更新,并允许合并结果。

冲突解决规则

使用活动-活动数据库,两个不同的实例有可能同时尝试对同一数据运行写入操作。如果发生这种情况,当副本尝试彼此同步这些更改时,可能会出现冲突。冲突解决规则决定数据库如何处理冲突操作。

有两种类型的冲突解决

  1. 合并

    • 操作是关联的。

    • 合并两个操作的结果。

  2. 胜出

    • 操作不是关联的。

    • 一个操作在冲突中获胜并设置值。

    • 忽略失败的操作。

以下冲突解决规则显示了活动-活动数据库如何为各种 JSON 命令解决冲突。

为键分配不同的类型

冲突

两个实例同时将不同类型的 value 分配给 JSON 文档中的同一个键。

例如

实例 1 将一个对象分配给 JSON 文档中的一个键。

实例 2 将一个数组分配给同一个键。

解析类型

胜出

解析规则

ID 最小的实例获胜,因此在给定示例中,键将成为一个对象。

示例

时间 描述 实例 1 实例 2
t1 将同一个键设置为对象或数组 JSON.SET doc $.a '{}' JSON.SET doc $.a '[]'
t2 将数据添加到对象和数组 JSON.SET doc $.a.x '“y”'

结果
{"a": {"x": "y"}}
JSON.SET doc $.a '["z"]'

结果
{“a”: ["z"]}
t3 活动-活动同步 – 同步 – – 同步 –
t4 实例 1 获胜 JSON.GET doc $

结果
{"a": {"x": "y"}}
JSON.GET doc $

结果
{"a": {"x": "y"}}

创建与创建

冲突

两个实例同时使用 JSON.SET 将新的 JSON 文档分配给同一个键。

解析类型

胜出

解析规则

ID 最小的实例获胜。

示例

时间 描述 实例 1 实例 2
t1 创建新的 JSON 文档 JSON.SET doc $ '{"field": "a"}' JSON.SET doc $ '{"field": "b"}'
t2 活动-活动同步 – 同步 – – 同步 –
t3 实例 1 获胜 JSON.GET doc $

结果
{"field": "a"}
JSON.GET doc $

结果
{"field": "a"}

创建与更新

冲突

实例 1 创建一个新的文档,并使用 JSON.SET 将其分配给现有键。

实例 2 使用 JSON.SET 更新同一键的现有内容。

解析类型

胜出

解析规则

创建新文档的操作获胜。

示例

时间 描述 实例 1 实例 2
t1 文档存在于两个实例上 JSON.GET doc $

结果
{"field1": "value1"}
JSON.GET doc $

结果
{"field1": "value1"}
t2 实例 1 创建一个新文档;实例 2 更新现有文档 JSON.SET doc $ '{"field2": "value2"}' JSON.SET doc $.field1 '[1, 2, 3]'
t3 活动-活动同步 – 同步 – – 同步 –
t4 实例 1 获胜 JSON.GET doc .

结果
{"field2": "value2"}
JSON.GET doc .

结果
{"field2": "value2"}

删除与创建

冲突

实例 1 使用 JSON.DEL 删除 JSON 文档。

实例 2 使用 JSON.SET 创建新的 JSON 文档并将其分配给实例 1 删除的键。

解析类型

胜出

解析规则

文档创建比删除获胜。

示例

时间 描述 实例 1 实例 2
t1 文档存在于两个实例上 JSON.GET doc $

结果
{"field1": "value1"}
JSON.GET doc $

结果
{"field1": "value1"}
t2 实例 1 删除文档;实例 2 创建一个新文档 JSON.DEL doc JSON.SET doc $ '{"field1": "value2"}'
t3 活动-活动同步 – 同步 – – 同步 –
t4 实例 2 获胜 JSON.GET doc $

结果
{"field1": "value2"}
JSON.GET doc $

结果
{"field1": "value2"}

删除与更新

冲突

实例 1 使用 JSON.DEL 删除 JSON 文档。

实例 2 使用 JSON.SET 更新同一文档的内容。

解析类型

胜出

解析规则

文档删除比更新获胜。

示例

时间 描述 实例 1 实例 2
t1 文档存在于两个实例上 JSON.GET doc $

结果
{"field1": "value1"}
JSON.GET doc $

结果
{"field1": "value1"}
t2 实例 1 删除文档;实例 2 更新它 JSON.DEL doc JSON.SET doc $.field1 '[1, 2, 3]'
t3 活动-活动同步 – 同步 – – 同步 –
t4 实例 1 获胜 JSON.GET doc $

结果
(nil)
JSON.GET doc $

结果
(nil)

更新与更新

冲突

实例 1 使用 JSON.SET 更新 JSON 文档内的字段。

实例 2 使用不同的值更新同一字段。

解析类型

胜出

解析规则

ID 最小的实例获胜。

示例

时间 描述 实例 1 实例 2
t1 文档存在于两个实例上 JSON.GET doc $

结果
{"field": "a"}
JSON.GET doc $

结果
{"field": "a"}
t2 使用不同的数据更新同一个字段 JSON.SET doc $.field "b" JSON.SET doc $.field "c"
t3 活动-活动同步 – 同步 – – 同步 –
t4 实例 1 获胜 JSON.GET doc $

结果
{"field": "b"}
JSON.GET doc $

结果
{"field": "b"}

更新与清除

v2.2 之前的 RedisJSON 版本有两种不同的方法来重置 JSON 对象的内容

  • 分配新的空 JSON 对象

    JSON.SET doc $.colors '{}'
    

    如果您使用这种方法,它不能与并发更新合并。

  • 对于每个键,使用 JSON.DEL 删除它

    JSON.DEL doc $.colors.blue
    

    使用这种方法,它可以将重置与并发更新合并。

从 RedisJSON v2.2 开始,您可以使用 JSON.CLEAR 命令重置 JSON 文档,而无需手动删除每个键。这种方法还允许合并并发更新。

分配空对象

冲突

实例 1 使用 JSON.SET 将“red”添加到现有的“colors”对象。

实例 2 为“colors”分配一个新的空对象。

解析类型

胜出

解析规则

文档创建比更新获胜,因此结果将为空对象。

示例

时间 描述 实例 1 实例 2
t1 文档存在于两个实例上 JSON.GET doc $

结果
{"colors": {"blue": "#0000ff"}}
JSON.GET doc $

结果
{"colors": {"blue": "#0000ff"}}
t2 实例 1 添加一个新的颜色;实例 2 将颜色重置为一个空对象 JSON.SET doc $.colors.red ‘#ff0000’ JSON.SET doc $.colors ‘{}’
t3 实例 2 添加一个新的颜色 JSON.SET doc $.colors.green ‘#00ff00’
t4 JSON.GET doc $

结果
{"colors": {"blue": "#0000ff", "red": "#ff0000"}}
JSON.GET doc $

结果
{"colors": {"green": "#00ff00"}}
t5 活动-活动同步 – 同步 – – 同步 –
t6 实例 2 获胜 JSON.GET doc $

结果
{"colors": {"green": "#00ff00"}}
JSON.GET doc $

结果
{"colors": {"green": "#00ff00"}}

使用 JSON.CLEAR

冲突

实例 1 使用 JSON.SET 将“red”添加到现有的“colors”对象。

实例 2 使用 JSON.CLEAR 清除“colors”对象,并将“green”添加到“colors”。

解析类型

合并

解析规则

合并所有操作的结果。

示例

时间 描述 实例 1 实例 2
t1 文档存在于两个实例上 JSON.GET doc $

结果
{"colors": {"blue": "#0000ff"}}
JSON.GET doc $

结果
{"colors": {"blue": "#0000ff"}}
t2 实例 1 添加一个新的颜色;实例 2 重置颜色 JSON.SET doc $.colors.red ‘#ff0000’ JSON.CLEAR doc $.colors
t3 JSON.GET doc $

结果
{"colors": {"blue": "#0000ff", "red": "#ff0000"}}
JSON.GET doc $

结果
{"colors": {}}
t4 实例 2 添加一个新的颜色 JSON.SET doc $.colors.green ‘#00ff00’
t5 JSON.GET doc $

结果
{"colors": {"green": "#00ff00"}}
t6 活动-活动同步 – 同步 – – 同步 –
t7 合并两个实例的结果 JSON.GET doc $

结果
{"colors": {"red": "#ff0000", "green": "#00ff00"}}
JSON.GET doc $

结果
{"colors": {"red": "#ff0000", "green": "#00ff00"}}

更新与更新数组

冲突

两个实例使用不同的内容更新同一个现有数组。

解析类型

合并

解析规则

合并数组上所有操作的结果。保留每个实例的原始元素顺序。

示例

时间 描述 实例 1 实例 2
t1 文档存在于两个实例上 JSON.GET doc $

结果
'["a", "b", "c"]'
JSON.GET doc $

结果
'["a", "b", "c"]'
t2 实例 1 删除一个数组元素;实例 2 添加一个元素 JSON.ARRPOP doc $ 1

结果
["a", "c"]
JSON.ARRINSERT doc $ 0 ‘“y”’

结果
["y", "a", "b", "c"]
t3 两个实例都将另一个元素添加到数组 JSON.ARRINSERT doc $ 1 ‘“x”’

结果
["a", "x", "c"]
JSON.ARRINSERT doc $ 2 ‘“z”’

结果
["y", "a", "z", "b", "c"]
t4 活动-活动同步 – 同步 – – 同步 –
t5 合并来自两个实例的结果 JSON.GET doc $

结果
["y", "a", "x", "z", "c"]
JSON.GET doc $

结果
["y", "a", "x", "z", "c"]

更新与删除数组元素

冲突

实例 1 使用 JSON.ARRPOP 从 JSON 数组中删除一个元素。

实例 2 更新实例 1 删除的同一个元素。

解析类型

胜出

解析规则

删除比更新获胜。

示例

时间 描述 实例 1 实例 2
t1 文档存在于两个实例上 JSON.GET doc $

结果
{“todo”: [{“title”: “buy milk”, “done”: false}]}
JSON.GET doc $

结果
{“todo”: [{“title”: “buy milk”, “done”: false}]}
t2 实例 1 删除一个数组元素;实例 2 更新同一个元素 JSON.ARRPOP doc $.todo 0 JSON.SET doc '$.todo[0]["done"]' 'true'’
t3 JSON.GET doc $

结果
{“todo”: []}
JSON.GET doc $

结果
[{“title”: “buy milk”, “done”: true}]}
t4 活动-活动同步 – 同步 – – 同步 –
t5 实例 1 获胜 JSON.GET doc $

结果
doc = {“todo”: []}
JSON.GET doc $

结果
doc = {“todo”: []}

更新与更新对象

冲突

两个实例都使用不同的内容更新同一个现有对象。

解析类型

合并

解析规则

合并对象上所有操作的结果。

示例

时间 描述 实例 1 实例 2
t1 文档存在于两个实例上 JSON.GET doc $

结果
'{"grocery": []}'
JSON.GET doc $

结果
'{"grocery": []}'
t2 将新元素添加到数组 JSON.ARRAPPEND doc $.grocery ‘“eggs”’ JSON.ARRAPPEND doc $.grocery ‘“milk”’
t3 将新元素添加到数组 JSON.ARRAPPEND doc $.grocery ‘“ham”’ JSON.ARRAPPEND doc $.grocery ‘“flour”’
t4 JSON.GET doc $

结果
{"grocery":["eggs", "ham"]}
JSON.GET doc $

结果
{"grocery":["milk", "flour"]}
t5 活动-活动同步 – 同步 – – 同步 –
t6 合并来自两个实例的结果 JSON.GET doc .

结果
{"grocery":["eggs","ham","milk", "flour"]}
JSON.GET doc .

结果
{"grocery":["eggs","ham","milk", "flour" ]}
RATE THIS PAGE
Back to top ↑