RocketMQ源码分析之事务消息(2)

broker处理事务结束的请求,先判断当前broker的角色是否是从节点

if (BrokerRole.SLAVE == brokerController.getMessageStoreConfig().getBrokerRole()) {
    response.setCode(ResponseCode.SLAVE_NOT_AVAILABLE);
    LOGGER.warn("Message store is slave mode, so end transaction is forbidden. ");
    return response;
}

判断当前这次请求的是否来自于broker的事务检查,未知状态的话直接返回空不作处理,事务提交状态和事务回滚状态需要做额外初始,当请求时直接请求过来的,默认就是false,处理方式也类似。

if (requestHeader.getFromTransactionCheck()) {
    switch (requestHeader.getCommitOrRollback()) {
        case MessageSysFlag.TRANSACTION_NOT_TYPE: {
            LOGGER.warn("Check producer[{}] transaction state, but it's pending status."
                    + "RequestHeader: {} Remark: {}",
                RemotingHelper.parseChannelRemoteAddr(ctx.channel()),
                requestHeader.toString(),
                request.getRemark());
            return null;
        }

        case MessageSysFlag.TRANSACTION_COMMIT_TYPE: {
            LOGGER.warn("Check producer[{}] transaction state, the producer commit the message."
                    + "RequestHeader: {} Remark: {}",
                RemotingHelper.parseChannelRemoteAddr(ctx.channel()),
                requestHeader.toString(),
                request.getRemark());

            break;
        }

        case MessageSysFlag.TRANSACTION_ROLLBACK_TYPE: {
            LOGGER.warn("Check producer[{}] transaction state, the producer rollback the message."
                    + "RequestHeader: {} Remark: {}",
                RemotingHelper.parseChannelRemoteAddr(ctx.channel()),
                requestHeader.toString(),
                request.getRemark());
            break;
        }
        default:
            return null;
    }
} else {
    switch (requestHeader.getCommitOrRollback()) {
        case MessageSysFlag.TRANSACTION_NOT_TYPE: {
            LOGGER.warn("The producer[{}] end transaction in sending message,  and it's pending status."
                    + "RequestHeader: {} Remark: {}",
                RemotingHelper.parseChannelRemoteAddr(ctx.channel()),
                requestHeader.toString(),
                request.getRemark());
            return null;
        }

        case MessageSysFlag.TRANSACTION_COMMIT_TYPE: {
            break;
        }

        case MessageSysFlag.TRANSACTION_ROLLBACK_TYPE: {
            LOGGER.warn("The producer[{}] end transaction in sending message, rollback the message."
                    + "RequestHeader: {} Remark: {}",
                RemotingHelper.parseChannelRemoteAddr(ctx.channel()),
                requestHeader.toString(),
                request.getRemark());
            break;
        }
        default:
            return null;
    }
}

当是提交事务状态时

OperationResult result = new OperationResult();
if (MessageSysFlag.TRANSACTION_COMMIT_TYPE == requestHeader.getCommitOrRollback()) {
    result = this.brokerController.getTransactionalMessageService().commitMessage(requestHeader);
    if (result.getResponseCode() == ResponseCode.SUCCESS) {
        RemotingCommand res = checkPrepareMessage(result.getPrepareMessage(), requestHeader);
        if (res.getCode() == ResponseCode.SUCCESS) {
            MessageExtBrokerInner msgInner = endMessageTransaction(result.getPrepareMessage());
            msgInner.setSysFlag(MessageSysFlag.resetTransactionValue(msgInner.getSysFlag(), requestHeader.getCommitOrRollback()));
            msgInner.setQueueOffset(requestHeader.getTranStateTableOffset());
            msgInner.setPreparedTransactionOffset(requestHeader.getCommitLogOffset());
            msgInner.setStoreTimestamp(result.getPrepareMessage().getStoreTimestamp());
            RemotingCommand sendResult = sendFinalMessage(msgInner);
            if (sendResult.getCode() == ResponseCode.SUCCESS) {
                this.brokerController.getTransactionalMessageService().deletePrepareMessage(result.getPrepareMessage());
            }
            return sendResult;
        }
        return res;
    }
}

提交事务消息

public OperationResult commitMessage(EndTransactionRequestHeader requestHeader) {
    return getHalfMessageByOffset(requestHeader.getCommitLogOffset());
}

先根据存储偏移量查找准备消息

private OperationResult getHalfMessageByOffset(long commitLogOffset) {
    OperationResult response = new OperationResult();
    MessageExt messageExt = this.transactionalMessageBridge.lookMessageByOffset(commitLogOffset);
    if (messageExt != null) {
        response.setPrepareMessage(messageExt);
        response.setResponseCode(ResponseCode.SUCCESS);
    } else {
        response.setResponseCode(ResponseCode.SYSTEM_ERROR);
        response.setResponseRemark("Find prepared transaction message failed");
    }
    return response;
}

public MessageExt lookMessageByOffset(final long commitLogOffset) {
    return this.store.lookMessageByOffset(commitLogOffset);
}

判断是否获取成功,检查消息的信息是否合理,消息生产组是否是该请求的组,队列偏移量是否一致,存储偏移量是否一致


private RemotingCommand checkPrepareMessage(MessageExt msgExt, EndTransactionRequestHeader requestHeader) {
    final RemotingCommand response = RemotingCommand.createResponseCommand(null);
    if (msgExt != null) {
        final String pgroupRead = msgExt.getProperty(MessageConst.PROPERTY_PRODUCER_GROUP);
        if (!pgroupRead.equals(requestHeader.getProducerGroup())) {
            response.setCode(ResponseCode.SYSTEM_ERROR);
            response.setRemark("The producer group wrong");
            return response;
        }

        if (msgExt.getQueueOffset() != requestHeader.getTranStateTableOffset()) {
            response.setCode(ResponseCode.SYSTEM_ERROR);
            response.setRemark("The transaction state table offset wrong");
            return response;
        }

        if (msgExt.getCommitLogOffset() != requestHeader.getCommitLogOffset()) {
            response.setCode(ResponseCode.SYSTEM_ERROR);
            response.setRemark("The commit log offset wrong");
            return response;
        }
    } else {
        response.setCode(ResponseCode.SYSTEM_ERROR);
        response.setRemark("Find prepared transaction message failed");
        return response;
    }
    response.setCode(ResponseCode.SUCCESS);
    return response;
}

 

校验成功后还原原始的消息,重置topic和queueId并清除这两个属性,并把事务标志置为事务提交状态

private MessageExtBrokerInner endMessageTransaction(MessageExt msgExt) {
    MessageExtBrokerInner msgInner = new MessageExtBrokerInner();
    msgInner.setTopic(msgExt.getUserProperty(MessageConst.PROPERTY_REAL_TOPIC));
    msgInner.setQueueId(Integer.parseInt(msgExt.getUserProperty(MessageConst.PROPERTY_REAL_QUEUE_ID)));
    msgInner.setBody(msgExt.getBody());
    msgInner.setFlag(msgExt.getFlag());
    msgInner.setBornTimestamp(msgExt.getBornTimestamp());
    msgInner.setBornHost(msgExt.getBornHost());
    msgInner.setStoreHost(msgExt.getStoreHost());
    msgInner.setReconsumeTimes(msgExt.getReconsumeTimes());
    msgInner.setWaitStoreMsgOK(false);
    msgInner.setTransactionId(msgExt.getUserProperty(MessageConst.PROPERTY_UNIQ_CLIENT_MESSAGE_ID_KEYIDX));
    msgInner.setSysFlag(msgExt.getSysFlag());
    TopicFilterType topicFilterType =
        (msgInner.getSysFlag() & MessageSysFlag.MULTI_TAGS_FLAG) == MessageSysFlag.MULTI_TAGS_FLAG ? TopicFilterType.MULTI_TAG
            : TopicFilterType.SINGLE_TAG;
    long tagsCodeValue = MessageExtBrokerInner.tagsString2tagsCode(topicFilterType, msgInner.getTags());
    msgInner.setTagsCode(tagsCodeValue);
    MessageAccessor.setProperties(msgInner, msgExt.getProperties());
    msgInner.setPropertiesString(MessageDecoder.messageProperties2String(msgExt.getProperties()));
    MessageAccessor.clearProperty(msgInner, MessageConst.PROPERTY_REAL_TOPIC);
    MessageAccessor.clearProperty(msgInner, MessageConst.PROPERTY_REAL_QUEUE_ID);
    return msgInner;
}

存储最终的消息


private RemotingCommand sendFinalMessage(MessageExtBrokerInner msgInner) {
    final RemotingCommand response = RemotingCommand.createResponseCommand(null);
    final PutMessageResult putMessageResult = this.brokerController.getMessageStore().putMessage(msgInner);
    if (putMessageResult != null) {
        switch (putMessageResult.getPutMessageStatus()) {
            // Success
            case PUT_OK:
            case FLUSH_DISK_TIMEOUT:
            case FLUSH_SLAVE_TIMEOUT:
            case SLAVE_NOT_AVAILABLE:
                response.setCode(ResponseCode.SUCCESS);
                response.setRemark(null);
                break;
            // Failed
            case CREATE_MAPEDFILE_FAILED:
                response.setCode(ResponseCode.SYSTEM_ERROR);
                response.setRemark("Create mapped file failed.");
                break;
            case MESSAGE_ILLEGAL:
            case PROPERTIES_SIZE_EXCEEDED:
                response.setCode(ResponseCode.MESSAGE_ILLEGAL);
                response.setRemark("The message is illegal, maybe msg body or properties length not matched. msg body length limit 128k, msg properties length limit 32k.");
                break;
            case SERVICE_NOT_AVAILABLE:
                response.setCode(ResponseCode.SERVICE_NOT_AVAILABLE);
                response.setRemark("Service not available now.");
                break;
            case OS_PAGECACHE_BUSY:
                response.setCode(ResponseCode.SYSTEM_ERROR);
                response.setRemark("OS page cache busy, please try another machine");
                break;
            case UNKNOWN_ERROR:
                response.setCode(ResponseCode.SYSTEM_ERROR);
                response.setRemark("UNKNOWN_ERROR");
                break;
            default:
                response.setCode(ResponseCode.SYSTEM_ERROR);
                response.setRemark("UNKNOWN_ERROR DEFAULT");
                break;
        }
        return response;
    } else {
        response.setCode(ResponseCode.SYSTEM_ERROR);
        response.setRemark("store putMessage return null");
    }
    return response;
}

消息存储成功后删除之前的准备消息,创建准备队列


public static final String REMOVETAG = "d";
public boolean deletePrepareMessage(MessageExt msgExt) {
    if (this.transactionalMessageBridge.putOpMessage(msgExt, TransactionalMessageUtil.REMOVETAG)) {
        log.info("Transaction op message write successfully. messageId={}, queueId={} msgExt:{}", msgExt.getMsgId(), msgExt.getQueueId(), msgExt);
        return true;
    } else {
        log.error("Transaction op message write failed. messageId is {}, queueId is {}", msgExt.getMsgId(), msgExt.getQueueId());
        return false;
    }
}

public boolean putOpMessage(MessageExt messageExt, String opType) {
    MessageQueue messageQueue = new MessageQueue(messageExt.getTopic(),
        this.brokerController.getBrokerConfig().getBrokerName(), messageExt.getQueueId());
    if (TransactionalMessageUtil.REMOVETAG.equals(opType)) {
        return addRemoveTagInTransactionOp(messageExt, messageQueue);
    }
    return true;
}

也就是重新添加一个操作消息,操作消息的内容是准备消息的队列偏移量


private boolean addRemoveTagInTransactionOp(MessageExt messageExt, MessageQueue messageQueue) {
    Message message = new Message(TransactionalMessageUtil.buildOpTopic(), TransactionalMessageUtil.REMOVETAG,
        String.valueOf(messageExt.getQueueOffset()).getBytes(TransactionalMessageUtil.charset));
    writeOp(message, messageQueue);
    return true;
}

public static String buildOpTopic() {
    return MixAll.RMQ_SYS_TRANS_OP_HALF_TOPIC;
}

 

获取或创建操作topic的消息队列,与准备消息队列相对应。


private void writeOp(Message message, MessageQueue mq) {
    MessageQueue opQueue;
    if (opQueueMap.containsKey(mq)) {
        opQueue = opQueueMap.get(mq);
    } else {
        opQueue = getOpQueueByHalf(mq);
        MessageQueue oldQueue = opQueueMap.putIfAbsent(mq, opQueue);
        if (oldQueue != null) {
            opQueue = oldQueue;
        }
    }
    if (opQueue == null) {
        opQueue = new MessageQueue(TransactionalMessageUtil.buildOpTopic(), mq.getBrokerName(), mq.getQueueId());
    }
    putMessage(makeOpMessageInner(message, opQueue));
}

private MessageQueue getOpQueueByHalf(MessageQueue halfMQ) {
    MessageQueue opQueue = new MessageQueue();
    opQueue.setTopic(TransactionalMessageUtil.buildOpTopic());
    opQueue.setBrokerName(halfMQ.getBrokerName());
    opQueue.setQueueId(halfMQ.getQueueId());
    return opQueue;
}

构建完整的操作消息信息


private MessageExtBrokerInner makeOpMessageInner(Message message, MessageQueue messageQueue) {
    MessageExtBrokerInner msgInner = new MessageExtBrokerInner();
    msgInner.setTopic(message.getTopic());
    msgInner.setBody(message.getBody());
    msgInner.setQueueId(messageQueue.getQueueId());
    msgInner.setTags(message.getTags());
    msgInner.setTagsCode(MessageExtBrokerInner.tagsString2tagsCode(msgInner.getTags()));
    msgInner.setSysFlag(0);
    MessageAccessor.setProperties(msgInner, message.getProperties());
    msgInner.setPropertiesString(MessageDecoder.messageProperties2String(message.getProperties()));
    msgInner.setBornTimestamp(System.currentTimeMillis());
    msgInner.setBornHost(this.storeHost);
    msgInner.setStoreHost(this.storeHost);
    msgInner.setWaitStoreMsgOK(false);
    MessageClientIDSetter.setUniqID(msgInner);
    return msgInner;
}

最后存储操作消息


public boolean putMessage(MessageExtBrokerInner messageInner) {
    PutMessageResult putMessageResult = store.putMessage(messageInner);
    if (putMessageResult != null
        && putMessageResult.getPutMessageStatus() == PutMessageStatus.PUT_OK) {
        return true;
    } else {
        LOGGER.error("Put message failed, topic: {}, queueId: {}, msgId: {}",
            messageInner.getTopic(), messageInner.getQueueId(), messageInner.getMsgId());
        return false;
    }
}

当请求类型是回滚事务状态时


if (MessageSysFlag.TRANSACTION_ROLLBACK_TYPE == requestHeader.getCommitOrRollback()) {
    result = this.brokerController.getTransactionalMessageService().rollbackMessage(requestHeader);
    if (result.getResponseCode() == ResponseCode.SUCCESS) {
        RemotingCommand res = checkPrepareMessage(result.getPrepareMessage(), requestHeader);
        if (res.getCode() == ResponseCode.SUCCESS) {
            this.brokerController.getTransactionalMessageService().deletePrepareMessage(result.getPrepareMessage());
        }
        return res;
    }
}

获取需要回滚的准备消息,检查消息信息是否正确,然后执行之前类似的处理


public OperationResult rollbackMessage(EndTransactionRequestHeader requestHeader) {
    return getHalfMessageByOffset(requestHeader.getCommitLogOffset());
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值