xxd763795151 commented on issue #2661:
URL: https://github.com/apache/rocketmq/issues/2661#issuecomment-782049365


   > > 如果第1条消息offset是0,那第0条消息呢。
   > 
   > 
![image](https://user-images.githubusercontent.com/29321745/108502222-6effb700-72ed-11eb-9672-4db712f4f364.png)
   > 不好意思,上面图的点位标的有点问题,图在画细一点。可以把consumeQueue每条消息的结构画进去。消息的起始物理偏移量physical 
offset(long 8字节)+消息大小size(int 4字节)+tagsCode(long 
8字节),每条数据的大小为20个字节。使用byteBuffer来存储。
   > 
如果是第一条消息,那么它的起始position就是0x20,byteBuffer.getLong()就可以获取到第一条消息的物理位置。那么第二条消息的起始position就是1x20,以此类推。如果按照你那样来算,第5条消息是5的话,起始position就是5x20,再通过byteBuffer.getLong()来获取消息的物理位置,就会发生BufferUnderflowException异常了。
   > 
![image](https://user-images.githubusercontent.com/29321745/108504420-cce1ce00-72f0-11eb-88d1-3a09c6d5f7a1.png)
   > 
   > 
重置消费位点确实会发生你说的那个问题,只能重置到倒数第二条。但是mq已经提供了解决办法,如果药重置全部的消息,时间戳哪里设置-1,就不会走getOffsetInQueueByTime这个方法了。
   > 
   > 如果你想到解决办法,也可以提pr,一起学习
   
   @panzhi33 是的,我之前尝试提交个pr,修复这个问题,但是感觉风险太大,最终没有提交本地代码,也把这个pr关了。
   
当时的思路是这样的,在最后返回的时候加上一个CQ_STORE_UNIT_SIZE,保证每次返回的时候,当前查到的消息的偏移上加上一。因为如果没有消息的话,直接就返回0了,不会走到这一步。如果走到这个地方,就会返回我们平常说的消息位点的这个实际值。
   ```
   return (mappedFile.getFileFromOffset() + offset + CQ_STORE_UNIT_SIZE) / 
CQ_STORE_UNIT_SIZE;
   ```
   
然后将几处涉及到根据这个偏移来获取物理position的地方进行修改,就是将查询的offset再减1。改完之后,我发现,改动的地方有点多,我根本无法确认所有修改的地方都没有问题,也没时间进行测试,风险太高,就没提交最终代码,并把pr也关了。
   也无法猜测最初作者是怎么思考的,这个地方计算的offset的为什么不是实际消息的位点,所以就把这个issue留了下来。


----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
[email protected]


Reply via email to