最近要实现的需求: BI 的 etl 模块,就是 2 个数据库同步数据,A 服务 A 库读数据,B 服务 B 库存数据,这个过程会很长,期间发生异常,或者人为手动取消这个过程,B 库里存的数据就要全部回滚。 其中数据库不限,目前支持的有 mysql,Postgres,oracle,sqlserver, 这个功能类似用 navicat 来同步两个数据库里表的操作
流程图如下,想问我要带上 redis 事务,和用 feign 的 hystrix 的回退模式,怎么做较好? 目前所有的 2 个微服务间的数据异常回滚操作都是用 try-catch,catch 里调用失败要执行的操作在代替事务,都是手动在 Connection.commit,Connection.rollback,我觉得这样不太对,但又不知道要怎么写,真的脑壳痛。。。 https://www.processon.com/view/link/5d4262d5e4b0b3e4dcdaba77
1
Breadykid OP 不是伸手党啊各位,对这块不会,不知道怎么实现,目前的实现经不起压测
|
2
jybox 2019-08-07 17:20:42 +08:00
两阶段提交
|
4
zhaorunze 2019-08-07 17:32:49 +08:00
领导上次技术分享说过思路,就是利用 redis,但是经不起细细推敲。seata 有一个控制中心,利用 redis 如果没有控制中心,会多很多复杂的操作。
|
5
snappyone 2019-08-07 17:36:30 +08:00
这个图看的晕啊
|
6
vmskipper 2019-08-07 17:44:25 +08:00
数据同步 库 A 10 亿 导入库 B 如果第 9 亿条失败 要回滚。。。 数据同步开源工具那么多
|
7
kkkkkrua 2019-08-07 18:10:44 +08:00
为什么我感觉复杂化了,是我理解错了吗?
当 B 库插入发生异常时候,清空掉所有数据不就可以了吗,为啥要分布式事务 如果是在已有基础上做增量插入的话,把当前 B 库的数据新增表,然后插入,再用数据库事务迁移过去。 |
8
rayu 2019-08-07 20:33:13 +08:00 via Android
之前面试被问住了,反问之后说用 kafka
|
9
liprais 2019-08-07 20:39:20 +08:00 via iPhone
往 b 里面写的时候批量导入开事务就行了
|
10
agostop 2019-08-08 08:54:46 +08:00
大概想了一下,弄个唯一的事务 ID 作为 key,每次提交 B 库的时候使用数据库事务保证完整性;
写入成功把这个 ID 提交给中间件,让中间件去同步; 中间件处理后,写入 A 数据库时依旧靠数据库事务,如果写入 A 库失败,根据事务 ID 删除 B 库存储条目 |
11
hantsy 2019-08-08 08:58:17 +08:00
对于微服务,
1. 天下没有免费的午餐。微服务开发难度很大,运维会面临空前的挑战。业务领域没弄清的话,或者你的项目没经历 DDD 建模, DevOps 空白或者不到位,没有实现自动化部署,不要盲目上微服务。马大叔文章也是建议从 Monolithic 开始,微服务是个演进的过程。 2. 跨服务的事务(不再是传统事务,传统事务处理不适合了。传统事务时间都很短。而微服务牵涉到多个服务,可能跨度几天,比如旅游订票流程,先预付了机票酒店,结果等了两天没出机票,对账后,全部一一退回),实现数据最终一致性的难度很大。可行的方法,1. 基于消息模型可以自己实现,相关的服务监听相应的事件(作用 RabbitMQ/kafka 等,比如,place order, cancel order, 等),实现上比较自由 , 2 也可以使用一些现有的工具架构定义 Saga 模型 ,在一个很长的运行单元中,每一步操作提供一个 Compensation 任务(回退操作),这种更易管理,更健壮。https://medium.com/@tomasz_96685/saga-pattern-and-microservices-architecture-d4b46071afcf |
12
mineqiqi 2019-08-08 09:22:05 +08:00
啥意思,只有 b 库的数据全部落盘才会同步到 a 库,还是边落库边同步,然后如果数据落盘异常全部数据回滚? 不论是哪种场景 这么多的数据只要有异常就全部回滚这种操作都是不合理的,一开始设计的时候就有问题
|
13
jk1030 2019-08-08 09:33:39 +08:00
kafka ack
|
14
agostop 2019-08-08 09:34:09 +08:00
不全部回滚会造成脏数据的吧
|
15
cyhulk 2019-08-08 11:16:20 +08:00
这个问题感觉完全不是分布式事务的范畴,B 落库的过程非常长,甚至可以人为干预关闭,如果真的是分布式事务,你这个请求的占用时间太长了,完全不如说你提供回退的接口或者通过消息队列自动触发,你自己做好回退的消息
|
16
gaius 2019-08-08 12:25:30 +08:00
不是同步调 B 的话,A 库保存消息和一个状态就好,用定时任务或者队列消费做下事务控制完成后再去做确认。人工取消不是太懂,也可以 B 写一个 cancel 方法吧。 csv 文件放哪就好,数据库存路径。
|