0

我有一条原始消息,我在服务中使用它来在各个地方存储数据

我的信息是这样的:

message Matrix {
  double width = 1;
  double height = 2;
  repeated double entries = 3;
}

我的团队认为Matrix消息太大,将类型更改为float似乎是实现有效负载大小减小的一种简单方法。但是,当我将原型定义更改为使用float而不是double此处,并尝试读取旧数据(在 Python 阅读器中)时,它看起来已损坏。

我能想到的一个选项是为每个字段添加一个新的浮动选项:

message Matrix {
  oneof r_oneof {
    double width_d = 1;
    float width_f = 4;
  }
  oneof c_oneof {
    double height_d = 2;
    float height_f = 5;
  }
  oneof e_oneof {
    repeated double entries_d = 3;
    repeated float entries_f = 6;
  }
}

然后我的反序列化代码可以检查每个 oneof 字段是否是doubleorfloat字段。这可行,但感觉就像一个笨重的设计模式。

在此示例中,是否有另一种方法可以向后兼容旧数据?

4

1 回答 1

1

我认为你的想法是正确的。只要有以旧格式存储的数据,您就希望保持旧字段及其字段编号不变。协议缓冲区的一大优点是未设置的字段基本上是免费的,因此您可以添加任意数量的新字段以促进迁移。

我要做的是添加一组新float字段并重命名这些double字段,同时保留它们的字段编号:

message Matrix {
  // Values in these fields should be transitioned to floats
  double deprecated_width = 1;
  double deprecated_height = 2;
  repeated double deprecated_entries = 3;

  float width = 4;
  float height = 5;
  repeated float entries = 6;
}

每当您Matrix从持久存储中读取 a 时,将任何值从不推荐使用的字段移动到不推荐使用的字段并写回结果。这应该有助于增量迁移到浮动。

我将提到您可能已经知道的另一件事:协议缓冲区不关心字段名称。只有字段编号对序列化和反序列化很重要。这意味着只要操作它们的代码同样更新,就可以自由地重命名字段。

在迁移完成后的某个时间点删除迁移代码并删除已弃用的字段但保留其字段编号:

message Matrix {
  reserved 1, 2, 3;
  float width = 4;
  float height = 5;
  repeated float entries = 6;
}

这可以确保旧格式的任何杂散消息在反序列化时爆炸,而不是导致数据损坏。

希望这可以帮助!

于 2020-05-07T05:38:02.943 回答