过去我所有的数据库需求都是由 sqlite 解决的。现在设计一个可能很大的数据库,我研究了“分布式事务”。我该如何编程?我发现了一些解释什么是分布式事务的结果,但没有解释如何对其进行编程。
我知道在代码中我有一些交易,我可能想将它们分成更大的交易。我使用.NET。我该怎么做,比如创建一个用户,他的 PK 在一个数据库中,而他的用户信息(如姓名和设置)在另一个数据库中。这可能是一个单独的问题,但如果我有两个功能。一个更新媒体描述,另一个更新可能位于同一服务器或不同服务器上的内容。我如何嵌套这些事务并只在最后提交?
我有一个网络应用程序,它接收将订单保存在数据库中的请求。我想写入 2 个不同的数据库 - 一个 Cassandra 实例和一个 PostgreSQL 实例。我使用纯 Java 和 JDBC(带有 apache DBUtis),前面有一个轻量级 Web 应用程序库。
我不确定的是如何跨两个数据库实现事务性,即如果对其中一个数据库的写入失败,则回滚另一个写入并将错误消息放入错误日志中。
Java中有什么机制可以实现这一点吗?我知道两阶段提交这样的事情,这就是我在这里要寻找的吗?还有其他选择吗?
例如 amazon.com;他们依赖于微服务架构,并且订单和付款可能是单独的微服务,但是当您在 amazon.com 上结帐订单时,您最终可以看到订单 ID 和详细信息。如果这不是最终一致性方法,那是什么?也许是2PC?
我正在概括我的问题;如果最终一致性不适合业务事务(最终用户应该看到事务结束的结果)但单独的微服务有意义(例如订单和付款)怎么办?如何处理即时一致性?
顺序一致性
任何执行的结果都是一样的,就好像所有处理器的操作都是按某种顺序执行的,每个处理器的操作都按照其程序指定的顺序出现在这个序列中。
我是分布式系统的新手,在这种情况下执行是什么意思,请以简单的方式解释这个定义?
我无法弄清楚为什么 TransactionScope 正在启动分布式事务(未在 SQL Server 上配置)。我想改用本地事务,当两个数据库位于同一个 SQL Server 实例中时可以使用本地事务。我的代码有什么问题,我该如何修复它?我可以强制 Transaction Scope 首先尝试本地事务吗?
数据库
应用程序设置.json
{
"ConnectionStrings": {
"DefaultConnection": "Data Source=DESKTOP;Initial Catalog=test;Integrated Security=True",
"Test2Connection": "Data Source=DESKTOP;Initial Catalog=test2;Integrated Security=True"
}
}
Run Code Online (Sandbox Code Playgroud)
startup.cs注册 TestContext 和 Test2Context
services.AddDbContext<TestContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddDbContext<Test2Context>(options =>
options.UseSqlServer(Configuration.GetConnectionString("Test2Connection")));
services.AddTransient<ICustomerRepository, CustomerRepository>();
services.AddTransient<IMaterialRepository, MaterialRepository>();
// This service inject TestContext and Test2Context
services.AddTransient<ICustomerService, CustomerService>();
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
Run Code Online (Sandbox Code Playgroud)
使用 TestContext 的CustomerRepository
public class CustomerRepository : ICustomerRepository
{
private readonly TestContext _context;
public CustomerRepository(TestContext context)
{
_context = context;
}
public Customer Retrieve(int id) …Run Code Online (Sandbox Code Playgroud) sql-server transactionscope distributed-transactions dbcontext entity-framework-core
当我们需要更改两个系统中的数据时,双写入就会出现问题:数据库(SQL 或 NoSQL)和 Apache Kafka(例如)。必须可靠地/自动地更新数据库并发布消息。最终一致性是可以接受的,但不一致是不能接受的。
如果没有两阶段提交 (2PC),双写入会导致不一致。
但在大多数情况下,2PC 并不是一个选择。
事务发件箱是一种微服务架构模式,其中单独的消息中继进程将插入数据库的事件发布到消息代理。
并行运行的多个消息中继进程会导致发布重复项(2 个进程读取 OUTBOX 表中的相同记录)或无序(如果每个进程只读取 OUTBOX 表的一部分)。
单个消息中继进程也可能多次发布消息。消息中继可能会在处理 OUTBOX 记录之后但在记录它已完成此操作的事实之前崩溃。当消息中继重新启动时,它将再次发布相同的消息。
如何在事务发件箱模式中实现消息中继,以便将重复消息或无序的风险降至最低,并且该概念适用于所有 SQL 和 NoSQL 数据库?
2phase-commit distributed-transactions duplicates microservices outbox-pattern
我们在一台机器上遇到问题,并显示错误消息:
"服务器XXX上的MSDTC不可用."
代码使用TransactionScope来包装一些LingToSql数据库代码; 交易中还有一些原始的Ado.net.
由于只访问了一个sql数据库(2005),为什么要使用分布式事务呢?
(我不想知道如何启用MSDTC,因为代码需要在服务器上使用其当前设置)
sql-server ado.net transactionscope distributed-transactions linq-to-sql
我想确认实体框架的ObjectContext.Connection.BeginTransaction()方法返回的事务是否使用MSDTC(Microsoft分布式事务处理协调器)的支持?
有没有办法在没有MSDTC支持的情况下使用交易?
msdtc entity-framework transactions distributed-transactions objectcontext
有一个消息队列域.此域可能适用于某些消息队列技术.在这种特殊情况下,它绑定到Windows Azure Service Bus.
某些项目具有注册Windows Azure Service Bus主题(基本上是消息队列)的操作.
注册新的消息队列意味着:
在背景之上,如果域事务成功结束并且Windows Azure Service Bus主题注册正常工作,它应该可以正常工作.
但是,如果域事务成功结束但Windows Azure Service Bus无法注册主题 - 即消息队列 - 会发生什么?
是的,你是一个破碎的域名.
如果在域事务启动之前进行Windows Azure Service Bus主题注册会发生什么?好吧,如果一切顺利,没问题.但现在问题已经被颠倒了:如果Windows Azure Service Bus主题被正确注册但后来域事务失败会发生什么?
是的,第二种情况比第一种情况要好,因为操作已经注册了一个无用的消息队列,但域名不知道它.现在主要的问题是,不确定数量的事务可能会失败,并且未知数量的消息队列将一无所获.
试想一下,如果这是一个严肃而庞大的商业服务:许多无用的消息队列和一个系统管理员(一个人)每月删除无用的消息队列.
由于我发现选择使用无用的消息队列比拥有破坏的域更好,我选择以这种方式继续前进,但是... 有Windows Azure任何类型的分布式事务机制以包含任何远程对象在原子事务中创建,包括其他特定于域的操作?,如果没有-可惜我认为,这是实际情况-你将如何解决这个情况?
我正在寻找这样的东西,因为我真的不喜欢有一个根本无法处理其用例的域名.我宁愿避免这种情况,让域名正常运行并控制一切.
我发现了一些关于这个主题的有趣链接:
大家好我们已经开始使用事务范围,下面是代码片段.我们需要了解的是,在每次使用连接后,我们的底线是否会处理/关闭特定连接?所以,自关闭以来,transaction.complete如何运作?
using (TransactionScope transScope = new TransactionScope())
{
try
{
string myConnStringLocal = "User Id=***;Password=****;Host=" + globalSettings.settingLocalIP + ";Database=" + globalSettings.settingLocalDB;
using (MySqlConnection connectionLocal = new MySqlConnection(myConnStringLocal))
{
try{
connectionLocal.Open();
}
Catch(Exception e)
{
}
finally{
connectionLocal.Close();
}
}
string myConnStringCentral = "User Id=***;Password=*****;Host=" + globalSettings.settingCentralIP + ";Database=" + globalSettings.settingCentralDB;
using (MySqlConnection connectionCentral = new MySqlConnection(myConnStringCentral))
{
try{
connectionCentral.Open();
}
Catch(Exception e)
{
}
finally{
connectionCentral.Close();
}
}
string myConnStringCentralCopy = "User Id=*****;Password=*****;Host=" + globalSettings.settingCentralCopyIP + ";Database=" + globalSettings.settingCentralCopyDB;
using …Run Code Online (Sandbox Code Playgroud) .net ×2
sql-server ×2
ado.net ×1
azure ×1
c# ×1
c#-5.0 ×1
consistency ×1
dbcontext ×1
distributed ×1
duplicates ×1
java ×1
linq-to-sql ×1
msdtc ×1
postgresql ×1
transactions ×1