Kafka/RocketMQ事务消息对比

一、Kafka事务消息

Kafka的事务概念类似于数据库提供的事务,即经典的ACID,原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)和持久性(Durability)。保证多条消息原子性地写入到目标分区,同时也能保证Consumer只能看到事务成功提交的消息。

事务消息实现

设置事务型Producer,需要满足两个要求:

  • 开启enable.idempotence = true
  • 设置Producer端参数transctional. id。最好为其设置一个有意义的名字。
producer.initTransactions();
try {
  producer.beginTransaction();
  producer.send(record1);
  producer.send(record2);
  producer.commitTransaction();
} catch (KafkaException e) {
  producer.abortTransaction();
}

和普通Producer代码相比,事务型Producer的显著特点是调用了一些事务API,如initTransaction、beginTransaction、commitTransaction和abortTransaction,它们分别对应事务的初始化、事务开始、事务提交以及事务终止。

这段代码能够保证Record1和Record2被当作一个事务统一提交到Kafka,要么它们全部提交成功,要么全部写入失败。实际上即使写入失败,Kafka也会把它们写入到底层的日志中,也就是说Consumer还是会看到这些消息。因此在Consumer端,读取事务型Producer发送的消息需要设置isolation.level参数的值。当前这个参数有两个取值:

  • read_uncommitted:这是默认值,表明Consumer能够读取到Kafka写入的任何消息,不论事务型Producer提交事务还是终止事务,其写入的消息都可以读取。很显然,如果你用了事务型Producer,那么对应的Consumer就不要使用这个值。
  • read_committed:表明Consumer只会读取事务型Producer成功提交事务写入的消息。当然了,它也能看到非事务型Producer写入的所有消息。

二、RocketMQ事务消息

RocketMQ事务不同与Kafka事务,它是基于2PC的方案实现的分布式事务,分两阶段提交事务消息,同时增加一个补偿逻辑来处理二阶段超时或者失败的消息。

image
1. 事务消息示例
public static void main(String[] args) throws MQClientException, UnsupportedEncodingException {
    final ExecutorService executorService = new ThreadPoolExecutor(2, 5, 100, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(2000), new ThreadFactory() {
        @Override
        public Thread newThread(Runnable r) {
            Thread thread = new Thread(r);
            thread.setName("client-transaction-msg-check-thread");
            return thread;
        }
    });
    TransactionMQProducer producer = new TransactionMQProducer("myGroup");
    producer.setExecutorService(executorService);
    producer.setTransactionListener(new TransactionListener() {
        @Override
        public LocalTransactionState executeLocalTransaction(Message msg, Object arg) {
            // 执行本地事务
            try {
                // 执行本地事务创建订单
                executeLocal(arg);  // TODO
                // 如果没抛异常说明执行成功,提交事务消息
                return LocalTransactionState.COMMIT_MESSAGE;
            } catch (Throwable t) {
                // 失败则直接回滚事务消息
                return LocalTransactionState.ROLLBACK_MESSAGE;
            }
        }

        @Override
        public LocalTransactionState checkLocalTransaction(MessageExt msg) {
            // 回查本地事务结果
            // 查询本地事务执行结果,若存在则提交事务 COMMIT_MESSAGE
            // 若不存在,可能是本地事务失败了,也可能是本地事务还在执行,所以返回 UNKNOW
            boolean isLocalSuss = checkLocal(msg.g
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码农老K

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值