微服务中心化数据库模型

Microservices centralized database model

目前我们有一些 microservice,它们有自己的数据库模型和迁移,由 GORM Golang 包提供。我们有一个很大的旧 MySQL 数据库,这违反了微服务法,但我们无法替换它。恐怕当微服务数量开始增长时,我们将迷失在众多数据库模型中。当我在微服务中添加一个新列时,我只需在终端中键入 service migrate(因为有一个用于 运行 和迁移命令的 cli),它会刷新数据库。

管理它的最佳做法是什么。例如我有 1000 个微服务,当有人刷新模型时,没有人会输入 service migrate。我在考虑一个集中式数据库服务,我们只需添加一个新列,它将存储所有模型和所有迁移。唯一的问题是服务如何了解数据库模型的变化。这就是我们在服务中存储用户的方式:

type User struct {
    ID        uint           `gorm:"column:id;not null" sql:"AUTO_INCREMENT"`
    Name      string         `gorm:"column:name;not null" sql:"type:varchar(100)"`
    Username  sql.NullString `gorm:"column:username;not null" sql:"type:varchar(255)"`
}

func (u *User) TableName() string {
    return "users"
}

如果我正确理解你的问题,在我看来可能有多种方法可以实现这一点。

一种解决方案是在数据库中的某处设置一个架构版本,您的微服务会定期检查该版本。当您的数据库架构更改时,您可以增加架构版本。因此,如果服务注意到数据库模式版本高于服务的当前模式版本,它可以在 gorm 允许的代码中迁移模式。

其他选项可能取决于您如何 运行 您的微服务。例如,如果您 运行 他们使用一些编排平台(例如 Kubernetes),您可以在服务初始化时将迁移代码放在 运行 的某个地方。然后,一旦您更新架构,您就可以强制滚动刷新容器,这反过来会触发迁移。

如果我对你的问题的理解是正确的,那么你仍在尝试使用一个 MySQL 实例,但有许多微服务。

有几种方法可以使 SQL 系统正常工作:

  1. 您可以创建一个 microservice-type 来处理来自数据库的数据 inserts/reads 并利用 connection pooling。并让您的其余服务通过这些服务处理所有数据 read/writes。这肯定会给您的所有 writes/reads 增加一些额外的延迟,并且可能会在规模上出现问题。

  2. 您可以尝试寻找一个 multi-master SQL 解决方案(例如 CitusDB),它可以轻松扩展并且您可以为您的数据库使用一个中央架构,并且只需确保处理数据插入的边缘情况(de-deuping 等)

  3. 您可以使用 data-streaming 架构,如 Kafka or AWS Kinesis 将您的数据传输到您的微服务,并确保它们仅通过这些流处理数据。这样,您就可以 de-couple 您的数据库中的数据。

我认为最好的方法是#3。这样,您就不必在微服务架构的计算层考虑存储。

不确定您为微服务使用的是什么服务,但是 StdLib 会强制执行一些转换(例如,仅通过 HTTP 传输数据)以帮助人们全神贯注。 AWS Lambda 还可以很好地与 Kinesis 配合使用,作为启动函数的源,这有助于 #3 方法。

免责声明:我是 StdLib 的创始人。

根据您的用例,MySQL 集群使用的 MySQL Cluster might be an option. Two phase commits 使频繁写入变得不切实际,但如果写入性能不是大问题,那么我希望 MySQL 集群会比连接池或排队黑客更有效。当然值得考虑。