【RabbitMq/Springboot】利用RabbitMq实现跨库转账的原理性实现
本文涉及RabbitMq版本3.7.18,Springboot版本:2.5.4。
之前我们探讨了单库转账,这回准备来实现一个跨库转账,实现声明这只是原理性实现,不是最终版本。
实现的想法是在A机的本地账户扣款,然后把远程账户和加款金额发到队列里,B机接到消息后更新本地库的对应账户。
A机为T440p,资金转出账户001,消息生产者和RabbitMq都在里面;B机为T14,转入账户002、消息消费者在里面。
A机实现分以下几步:
1.准备远程转账函数
@Component public class AccountService { @Resource private AccountMapper amapper=null; @Autowired private RabbitMqMsgSender mqSender; @Transactional(rollbackFor=Exception.class) public void remoteTransfer(int amount,String fromAccount,String remoteAcccount) throws TransferException{ int count=amapper.add(-amount, fromAccount); if(count==0) { throw new TransferException("对转出账户:"+fromAccount+"操作,更新记录数为0.只有可能是该账户不存在。"); } mqSender.send(remoteAcccount+"/"+amount); } }
可以看到原来给转入加款的部分被替换成了往消息队列里发消息,消息格式为:远程账户/加款金额。
2.在测试函数中执行
@SpringBootTest class MyBankApplicationTests { @Autowired private AccountService aService; @Test void test() { try { aService.remoteTransfer(100, "001", "002"); } catch (Exception e) { e.printStackTrace(); } } }
这个也可以点击页面按钮通过Ajax调用函数什么的,为了简便就直接在测试类里做了。
3.看看数据库情况:
看001账户被扣款一百,至少本地是对的。
B机实现分以下几步:
1.收到消息后对数据库进行处理
import javax.annotation.Resource; import org.springframework.amqp.rabbit.annotation.RabbitHandler; import org.springframework.amqp.rabbit.annotation.RabbitListener; import org.springframework.stereotype.Component; import com.hy.mybank.mapper.AccountMapper; @Component @RabbitListener(queues="queue01") public class RabbitMqMsgReceiver { @Resource private AccountMapper amapper=null; @RabbitHandler public void QueueReceive(String receivedMsg) { System.out.println("收到消息:"+receivedMsg); String[] arr=receivedMsg.split("[//]"); String toAccount=arr[0]; int amount=Integer.parseInt(arr[1]); amapper.add(amount, toAccount); } }
这边的处理也简单,直接劈分消息,第一个元素为转入账户,第二个元素为金额,进行数据操作即可。
值得注意的是,QueueReceive函数一旦出现任何异常,队列里的消息是不会丢失的。我在劈分receivedMsg后写错序号,导致下标越界异常,但队列里面的消息还在,虽然它已经被取到劈分过了,这说明这个函数一有异常,消息是会被退回队列的。加上队列里消息存储机制,可以说安全性至少有两层。
2.add函数
@Mapper public interface AccountMapper { @Update("Update account set balance=balance+#{count} where customer_id=#{customer_id}") int add(int count,String customer_id); }
这个函数就是操作数据库的SQL,没啥好说的。
3.数据库情况
可以看到002账户增加了100元,这个帐是平的了。
以上即为跨库转账的原理性实现,这个实现当然是有漏洞的,比如转入账户不存在,转出账户的钱岂不是消失了,怎么保证远程转账的原子性,是接下来需要思考的问题。
-END-
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)
2014-09-10 【Canvas与旗帜】红白蓝黄星正方形旗帜(用于制作120*120图标)