Red de conocimiento informático - Problemas con los teléfonos móviles - Código fuente de RocketMQ: Introducción a MappedFile

Código fuente de RocketMQ: Introducción a MappedFile

1 Descripción general

2 Introducción a las clases MappedFileQueue y MappedFile

3 Rastreo de MappedFile

4 Grupo de almacenamiento temporal TransientStorePool

5 Preasignación de MappedFile

6 escritura de MappedFile

7 actualización de MappedFile

8 notas

El almacenamiento de RocketMQ se implementa en función de MappedFile, como CommitLog, índice de índice , ConsumeQueue, etc. Este artículo se centra en el mecanismo de implementación, incluida la introducción de la clase MappedFileQueue, la clase MappedFile, el precalentamiento, el servicio de preasignación de MappedFile AllocateMappedFileService, el vaciado de MappedFile, etc.

El almacenamiento de mensajes CommitLog, ConsumeQueue, etc. generalmente registra una gran cantidad de datos. Un MappedFile tiene un tamaño fijo (el valor predeterminado es 1G), por lo que un MappedFile no puede registrar todo el contenido, por lo que CommitLog y ConsumeQueue generalmente usan varios. MappedFiles para registrar datos. MappedFile se usa para registrar datos. RocketMQ usa MappedFileQueue para organizar una serie de MappedFile. Al final de la cola MappedFileQueue suele estar el MappedFile que se acaba de escribir o parte del espacio o que se acaba de asignar. Para cada operación de escritura, el último MappedFile. se obtendrá del final de la cola. MappedFile para escribir.

Primero, verifique la variable principal de la clase MappedFile

Porque cada vez que se escriben datos, el último MappedFile se obtendrá de MappedFileQueue, si MappedFileQueue está vacío o el El último archivo MappedFile se escribe al final de la cola, se reasignará un nuevo MappedFile. Si MappedFileQueue está vacío o el último MappedFile está lleno, se reasigna un nuevo MappedFile.

El proceso de creación de MappedFileQueue es el siguiente:

Hay dos formas de crear MappedFile. Uno se crea directamente a través de su constructor, el otro se envía a allocateMappedFileService para crear y crear de forma asíncrona el siguiente MappedFile que se utilizará.

Echemos un vistazo al primer formulario, nuevo MappedFile, nuevo MappedFile, que no utiliza TransientStorePool para la optimización, echemos un vistazo al constructor MappedFile:

Dado que MappedFile tiene Pre -asignado para que el siguiente MappedFile se pueda crear de forma asincrónica utilizando MappedFileService, y el siguiente MappedFile también se cree de forma asincrónica. allocateMappedFileService implica el grupo temporal TransientStorePool, por lo que el grupo temporal TransientStorePool se presentará brevemente a continuación.

La clase TransientStorePool es relativamente simple. Utiliza una cola Deque de doble extremo para mantener varias columnas de ByteBuffers preasignados que se asignan directamente desde el montón, mientras que DefaultMessageStore contiene instancias de objetos TransientStorePool. Si TransientStorePoolEnable está habilitado al inicio, se llama al método TransientStorePool.init en el constructor DefaultMessageStore para preasignar y poner en cola un búfer de bytes. Si la función TransientStorePool no está habilitada al inicio, no se llamará al método TransientStorePool.init y obtener el ByteBuffer de la cola devolverá un valor nulo.

Los campos principales de TransientStorePool son los siguientes:

Los métodos principales de TransientStorePool son los siguientes:

Si está utilizando TransientStorePool, el constructor utilizado para crear un MappedFile es:

Tenga en cuenta que en el servicio AllocateMappedFileService preasignado, primero intentará utilizar el servicio ServiceLogix. En el servicio AllocateMappedFileService preasignado, primero intenta cargar la implementación de MappedFile definida por el usuario usando el punto de extensión ServiceLoader, que usa un constructor de dos argumentos pero muestra una llamada al método init con el parámetro TransientStorePool para la inicialización. Al introducir el método AllocateMappedFileService.mmapOperation, verá el uso del punto de extensión ServiceLoader.

En la introducción al rastreo de MappedFile se menciona que si el servicio de preasignación de MappedFile está habilitado, al crear un MappedFile, se crearán dos MappedFiles al mismo tiempo, uno se creará sincrónicamente y se devolverá para uso real esta vez. MappedFile, el otro es un MappedFile creado de forma asincrónica en segundo plano para la próxima adquisición y guardado en MappedFileQueue. Preasigne una entrada en MappedFileQueue para this.allocateMappedFileService.putRequestAndReturnMappedFile(nextFilePath,nextNextFilePath, this.mappedFileSize). mappedFileSize);

En los parámetros anteriores, nextFilePath es el nombre y el tamaño del archivo asignado para esta solicitud, y nextNextFilePath es el nombre y el tamaño del archivo asignado que se preasignará para la siguiente solicitud. .

Aquí explicamos por qué la preasignación solo asigna un MappedFile por adelantado en función de la necesidad real de crear un MappedFile. Personalmente, entiendo que el tamaño predeterminado del MappedFile asignado es 1G, que es relativamente grande. espacio y, en general, puede admitirse durante un período de tiempo después de la asignación. Para la escritura, no es necesario preasignar demasiados MappedFiles.

Bien, ahora echemos un vistazo a la implementación del método allocateMappedFileService.putRequestAndReturnMappedFile:

Se ha introducido el método para enviar una solicitud de preasignación. La solicitud de preasignación se bloqueará en espera de ser adquirida. Actualmente es necesario crear la tarea MappedFile, entonces, ¿cómo manejar la tarea de asignación enviada? De hecho, la clase AllocateMappedFileService se extiende desde ServiceThread. Es un hilo y su método de ejecución se define de la siguiente manera:

Ya hemos introducido cómo asignar MappedFile. Tomamos BrokerController para almacenar mensajes como ejemplo. Para la operación de escritura de MappedFile, el almacenamiento de mensajes de BrokerController finalmente llama a MappedFile.appendMessage para completar la escritura:

La operación de actualización de MappedFile se divide en dos métodos: actualización sincrónica y actualización asincrónica según la configuración específica. Aquí, independientemente de la sincronización Las operaciones son similares a las asincrónicas y se completan a través de MappedFile.commit y MappedFile.flush. flush; MappedFile.flush completa el vaciado real a través de fileChannel.force o mappedByteBuffer.force (), que no se presentará aquí

Si habilitar el grupo de almacenamiento transitorio TransientStorePool no se configura por separado. TransientStorePoolEnable no se configura de forma independiente, podemos ver la implementación del método MessageStoreConfig.isTransientStorePoolEnable:

TransientStorePool se habilitará solo cuando el agente principal, el método de actualización sea asíncrono y TransientStorePool sea verdadero.