如何确保所有事情都完成,或者 none 完成?
How to ensure either all things are done, or none is done?
标题可能会产生误导(老实说,我想不出更好的标题)所以请阅读我的解释:
假设我们正在尝试创建用户并更新缓存:
- 创建用户并插入数据库。
- 用创建的用户更新缓存。
或
我们正在尝试在创建用户后发布事件(例如在微服务中)
- 创建用户并插入数据库。
- 使用创建的用户发布活动。
或
我们正在努力做 n
件事,我们希望确保全部完成或 none。
- 创建用户并插入数据库。
- 更新缓存。
- 发送电子邮件。
- 发送短信。
- 发布活动,...(不胜枚举)
在没有失败的完美世界中,我们可以按顺序编写它们,仅此而已,但是当我们在用户创建完成后出现失败时会发生什么? (在添加到缓存或发送事件等之前)
这些例子是为缓存例子编造的:
const data = {
id: 1
};
const user = database.createUser(data);
// Power goes out here (or any kind of failure)
cache.setCache(user);
至此,我们成功创建了用户,但未能更新缓存。
让我们再举一个使用数据库事务的例子:
const data = {
id: 1
};
const transaction = database.startTransaction();
try {
const user = database.createUser(data);
cache.setCache(user);
// Power goes out here (or any kind of failure)
transaction.commit();
} catch(err) {
transaction.rollback();
}
在这里,我们已经成功更新了缓存,但由于失败而从未创建用户。
感谢您的宝贵时间。
使用微服务时,我们习惯使用的常见 ACID 事务将不适用。相反,您可以查看 BASE 交易。
看这里:https://www.johndcook.com/blog/2009/07/06/brewer-cap-theorem-base/
An alternative to ACID is BASE:
- Basic Availability
- Soft-state
- Eventual consistency
Rather than requiring consistency after every transaction, it is enough for the database to eventually be in a consistent state. (Accounting systems do this all the time. It’s called “closing out the books.”) It’s OK to use stale data, and it’s OK to give approximate answers.
从技术上讲,这意味着您必须找到一种干净的方法来处理失败,例如在失败的情况下发送事件(这意味着您创建的用户应该从缓存中删除,或者事件发送一封电子邮件,说有一个错误)。
我们经常在订单或支付系统中看到这样的例子,您可以在其中收到一封电子邮件,说订单无法处理。
标题可能会产生误导(老实说,我想不出更好的标题)所以请阅读我的解释:
假设我们正在尝试创建用户并更新缓存:
- 创建用户并插入数据库。
- 用创建的用户更新缓存。
或
我们正在尝试在创建用户后发布事件(例如在微服务中)
- 创建用户并插入数据库。
- 使用创建的用户发布活动。
或
我们正在努力做 n
件事,我们希望确保全部完成或 none。
- 创建用户并插入数据库。
- 更新缓存。
- 发送电子邮件。
- 发送短信。
- 发布活动,...(不胜枚举)
在没有失败的完美世界中,我们可以按顺序编写它们,仅此而已,但是当我们在用户创建完成后出现失败时会发生什么? (在添加到缓存或发送事件等之前)
这些例子是为缓存例子编造的:
const data = {
id: 1
};
const user = database.createUser(data);
// Power goes out here (or any kind of failure)
cache.setCache(user);
至此,我们成功创建了用户,但未能更新缓存。
让我们再举一个使用数据库事务的例子:
const data = {
id: 1
};
const transaction = database.startTransaction();
try {
const user = database.createUser(data);
cache.setCache(user);
// Power goes out here (or any kind of failure)
transaction.commit();
} catch(err) {
transaction.rollback();
}
在这里,我们已经成功更新了缓存,但由于失败而从未创建用户。
感谢您的宝贵时间。
使用微服务时,我们习惯使用的常见 ACID 事务将不适用。相反,您可以查看 BASE 交易。
看这里:https://www.johndcook.com/blog/2009/07/06/brewer-cap-theorem-base/
An alternative to ACID is BASE:
- Basic Availability
- Soft-state
- Eventual consistency
Rather than requiring consistency after every transaction, it is enough for the database to eventually be in a consistent state. (Accounting systems do this all the time. It’s called “closing out the books.”) It’s OK to use stale data, and it’s OK to give approximate answers.
从技术上讲,这意味着您必须找到一种干净的方法来处理失败,例如在失败的情况下发送事件(这意味着您创建的用户应该从缓存中删除,或者事件发送一封电子邮件,说有一个错误)。
我们经常在订单或支付系统中看到这样的例子,您可以在其中收到一封电子邮件,说订单无法处理。