From 4cce9b6c769a9f419c39b6d7eae9cfd37e5d5b4c Mon Sep 17 00:00:00 2001 From: olderwei Date: Wed, 27 Feb 2019 23:04:31 +0800 Subject: [PATCH] [RIP-9] Add English document to Design_Query(#901) [RIP-9] Add English document to Design_Query --- docs/en/Design_Query.md | 17 +++++++++++++++++ .../images/rocketmq_design_message_query.png | Bin 0 -> 26148 bytes 2 files changed, 17 insertions(+) create mode 100644 docs/en/Design_Query.md create mode 100644 docs/en/images/rocketmq_design_message_query.png diff --git a/docs/en/Design_Query.md b/docs/en/Design_Query.md new file mode 100644 index 00000000..6988948d --- /dev/null +++ b/docs/en/Design_Query.md @@ -0,0 +1,17 @@ +# Message Queries + +RocketMQ supports message queries by two dimensions, which are "Query Message by Message Id" and "Query Message by Message Key". + +## 1. Query Message by Message Id +The MessageId in RocketMQ has a total length of 16 bytes, including the broker address (IP address and port) and CommitLog offset. In RocketMQ, the specific approach is that the Client resolves the Broker's address (IP address and port) and the CommitLog's offset address from the MessageId. Then both of them are encapsulated into an RPC request, and finally it will be sent through the communication layer (business request code: VIEW_MESSAGE_BY_ID). The Broker reads a message by using the CommitLog offset and size to find the real message in the CommitLog and then return, which is how QueryMessageProcessor works. + +## 2. Query Message by Message Id +"Query Messages by Message Key" is mainly based on RocketMQ's IndexFile. The logical structure of the IndexFile is similar to the implementation of HashMap in JDK. The specific structure of the IndexFile is as follows: + +![](images/rocketmq_design_message_query.png) + +The IndexFile provides the user with the querying service by “Querying Messages by Message Key”. The IndexFile is stored in $HOME\store\index${fileName}, and the file name is named after the timestamp at the time of creation. The file size is fixed, which is 420,000,040 bytes (40+5million\*4+20million\*20). If the UNIQ_KEY is set in the properties of the message, then the "topic + ‘#’ + UNIQ_KEY" will be used as the index. Likewise, if the KEYS is set in the properties of the message (multiple KEYs should be separated by spaces), then the "topic + ‘#’ + KEY" will be used as the index. + +The index data contains four fields, Key Hash, CommitLog offset, Timestamp and NextIndex offset, for a total of 20 Bytes. The NextIndex offset of the index data will point to the previous index data if the Key Hash of the index data is the same as that of the previous index data. If a hash conflict occurs, then the NextIndex offset can be used as the field to string all conflicting indexes in a linked list. What the Timestamp records is the time difference between two storeTimestamps, instead of a specific time. The structure of the entire IndexFile is shown in the graph. The Header is used to store some general statistics, which needs 40 bytes. The Slot Table of 4\*5million bytes does not save the real index data, but saves the header of the singly linked list corresponding to each slot. The Index Linked List of 20\*20million is the real index data, that is, an Index File can hold 20million indexes. + +The specific method of "Query Message by Message Key" is that the topic and message key are used to find the record in the IndexFile, and then read the message from the file of CommitLog according to the CommitLog offset in this record. \ No newline at end of file diff --git a/docs/en/images/rocketmq_design_message_query.png b/docs/en/images/rocketmq_design_message_query.png new file mode 100644 index 0000000000000000000000000000000000000000..f5ca945cafc09efff90fa89d76b3935bd46355c9 GIT binary patch literal 26148 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