微服务+redis 事务解决方案

2019-08-07 16:45:03 +08:00
 Breadykid

最近要实现的需求: 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

3431 次点击
所在节点    程序员
23 条回复
Breadykid
2019-08-07 17:05:05 +08:00
不是伸手党啊各位,对这块不会,不知道怎么实现,目前的实现经不起压测
jybox
2019-08-07 17:20:42 +08:00
两阶段提交
Breadykid
2019-08-07 17:28:23 +08:00
@jybox 不能引入 seata 之类的框架,手动实现二阶段怎么搞哇?
zhaorunze
2019-08-07 17:32:49 +08:00
领导上次技术分享说过思路,就是利用 redis,但是经不起细细推敲。seata 有一个控制中心,利用 redis 如果没有控制中心,会多很多复杂的操作。
snappyone
2019-08-07 17:36:30 +08:00
这个图看的晕啊
vmskipper
2019-08-07 17:44:25 +08:00
数据同步 库 A 10 亿 导入库 B 如果第 9 亿条失败 要回滚。。。 数据同步开源工具那么多
kkkkkrua
2019-08-07 18:10:44 +08:00
为什么我感觉复杂化了,是我理解错了吗?
当 B 库插入发生异常时候,清空掉所有数据不就可以了吗,为啥要分布式事务
如果是在已有基础上做增量插入的话,把当前 B 库的数据新增表,然后插入,再用数据库事务迁移过去。
rayu
2019-08-07 20:33:13 +08:00
之前面试被问住了,反问之后说用 kafka
liprais
2019-08-07 20:39:20 +08:00
往 b 里面写的时候批量导入开事务就行了
agostop
2019-08-08 08:54:46 +08:00
大概想了一下,弄个唯一的事务 ID 作为 key,每次提交 B 库的时候使用数据库事务保证完整性;
写入成功把这个 ID 提交给中间件,让中间件去同步;
中间件处理后,写入 A 数据库时依旧靠数据库事务,如果写入 A 库失败,根据事务 ID 删除 B 库存储条目
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
mineqiqi
2019-08-08 09:22:05 +08:00
啥意思,只有 b 库的数据全部落盘才会同步到 a 库,还是边落库边同步,然后如果数据落盘异常全部数据回滚? 不论是哪种场景 这么多的数据只要有异常就全部回滚这种操作都是不合理的,一开始设计的时候就有问题
jk1030
2019-08-08 09:33:39 +08:00
kafka ack
agostop
2019-08-08 09:34:09 +08:00
不全部回滚会造成脏数据的吧
cyhulk
2019-08-08 11:16:20 +08:00
这个问题感觉完全不是分布式事务的范畴,B 落库的过程非常长,甚至可以人为干预关闭,如果真的是分布式事务,你这个请求的占用时间太长了,完全不如说你提供回退的接口或者通过消息队列自动触发,你自己做好回退的消息
gaius
2019-08-08 12:25:30 +08:00
不是同步调 B 的话,A 库保存消息和一个状态就好,用定时任务或者队列消费做下事务控制完成后再去做确认。人工取消不是太懂,也可以 B 写一个 cancel 方法吧。 csv 文件放哪就好,数据库存路径。
Breadykid
2019-08-09 09:36:03 +08:00
@vmskipper 就是不给用其他工具啊
Breadykid
2019-08-09 09:36:47 +08:00
@mineqiqi 就是全部落盘才会同步到 a 库的需求呢
Breadykid
2019-08-09 09:43:52 +08:00
@kkkkkrua 意思是建临时表吗
Breadykid
2019-08-09 09:46:40 +08:00
@liprais 数据库事务还是别的?可以具体点嘛?

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/589876

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX