Cajitas que piensan

Write Ahead Log

Basado en los apuntes de Unmesh Joshi

Guardar los datos en disco es siempre un proceso costoso, sin importar el tipo de estructura que usemos para guardar la información, por lo cual estos sistemas tienen que ir acumulando y bajando a disco periódicamente para ser mas performante. Al tener información “para guardar” en disco pero ya confirmada como guardada al cliente, tenemos un potencial peligro de que se pierda en caso de que el proceso muera antes de escribir en disco.

Incluso luego de hacer una escritura en un archivo en disco, por como funcionan las cache del Sistema operativo (en linux los archivos están cacheados en memoria en page cache y los bloques de disco en buffer cache porque se asume que uno lee lo que acaba de escribir normalmente), por lo cual pueden pasar 30 segundos sin una escritura real a disco.

Para afrontar este problema, se utiliza el concepto de WAL (Write Ahead Log), donde cada operación que se desea realizar en el motor de datos, primero se guarda en un log (en el cual solo se appendea información para hacerlo mas optimo) solo guardando en el los cambios de estado pero no la estructura de datos que utiliza nuestro motor en disco. El WAL permite mantener la atomicidad y durabilidad de las escrituras.

Utilizar un WAL permite dar durabilidad a los datos pero significa que hasta que el servidor levante y cargue todo el WAL en memoria, no estará operativo. Para solucionar esto deberíamos tener replicado en varios servidores el WAL y tener multiples servidores genera nuevos problemas.

Wal

Solo luego de escribir en el WAL es que se escribe en la representación en memoria. Estos logs permiten al proceso que muere, al reiniciar, levantar en memoria todo lo que hay en el WAL de inicio a fin y seguir funcionando como lo hacia hasta la caída.

Ejemplo de como se vería un log para un cambio que implica A, B y C

intending to apply A
intending to apply B
intending to apply C

Esto puede verse tanto en nosql como sql, ejemplo los journal de Postgres o Mysql.

Bien ahora tenemos un gran log con toda la historia de operaciones que se realizo en el storage, pero ¿que sucede cuando queremos borrar lo que ya no es necesario de este archivo?

Borrar lineas particulares de un archivo no es eficiente, lo mejor seria truncar o borrar todo el archivo, por lo cual ahi entra otro concepto Segmented Log

Estos conceptos en los storage que usamos:

  • Cassandra
    • Al WAL se le llama commit log
  • Mariadb
    • Es el innodb redo log y se puede ver como ib_logfileN segun la numeración.
  • MongoDB
    • Algunas condiciones para bajar a disco
      • Cada x tiempo (storage.journal.commitIntervalMs)
      • Cada 100mb (crea uno nuevo y baja el actual)
      • Si la operación de escritura lo fuerza ( j: true)
  • ElasticSearch
    • Se le llama translog, y cuando se baja a disco es en un Lucene commit, luego de esta operación se crea una nueva generación de translog