¿Cuál es el mejor enfoque para almacenar registros de auditoría / historial de cambios en DynamoDB?
El propósito es construir un servicio de registro de auditoría para almacenar el historial de cambios de una aplicación. La siguiente información será almacenada:
- srcId
- srcTable
- changedAt
- changes
- user
Por ejemplo, para el cambio de nombre de usuario del id = 10 de la tabla perfil se guardará así:
srcId = 10,
srcTable = ‘profile’,
changedAt = timestamp,
changes: { name: { old: old-value, new: new-value } },
user: el-id-de-usuario-que-realizó-la-acción-de-cambio
Se intenta construir el sistema basado en aws lambda, dynamodb.
Inicialmente se pensó en usar srcId como clave de ordenamiento y srcTable como clave de partición. Pero como puede haber múltiples entradas para el mismo par srcId/srcTable, donde changedAt será diferente. Alguna sugerencia sobre cómo debería ser la clave de índice o clave primaria para obtener el mejor rendimiento.
PD: consultas esperadas
- la mayoría de las consultas serán para obtener la lista de cambios para el par srcId/srcTable [ ~90% ]
- encontrar el historial de cambios para srcTable [ 5% ~ 7% ]
- encontrar los cambios realizados por el usuario [ 3% ~ 5% ]
(los valores porcentuales se perciben aproximadamente sobre el comportamiento esperado)
davy.ai
Diseño Propuesto del Servicio de Registro de Auditoría
Para almacenar el historial de cambios de una aplicación, podemos utilizar
AWS Lambda
yDynamoDB
. Un posible diseño para la tabla que almacenará la información del registro de auditoría es:srcTable
– identifica la tabla de la aplicación donde se produjo el cambio.srcId#changedAt
– identifica el registro en la tabla y la marca de tiempo en que se produjo el cambio.#
es solo un separador para crear una clave de ordenamiento compuesta.changes
– un mapa que almacena los valores antiguos y nuevos para cada atributo modificado en el registro.user
– identifica al usuario que realizó la acción de cambio.Utilizando este diseño, podremos recuperar eficientemente los registros del registro de auditoría para un par
srcId/srcTable
dado para aproximadamente el 90% de las consultas esperadas.Para recuperar los registros del registro de auditoría para un par
srcId/srcTable
dado, podemos utilizar la operaciónQuery
en DynamoDB. Esta operación nos permitirá filtrar los registros porsrcTable
ysrcId
, y utilizandobegins_with
, podemos recuperar solo los registros para unsrcId
específico. Esto nos dará la lista de cambios para ese registro en orden cronológico inverso (el último cambio primero). Luego podemos utilizar una funciónLambda
para analizar el mapa dechanges
y generar una salida más amigable para el usuario (por ejemplo, una lista de nombres de atributos con valores antiguos y nuevos).Para recuperar los registros del registro de auditoría para una
srcTable
dada, podemos utilizar la operaciónScan
en DynamoDB. Esta operación nos permitirá filtrar los registros porsrcTable
y recuperar todos los registros para esa tabla. Sin embargo, debido a problemas de rendimiento, necesitamos limitar el número de registros recuperados, ya que las operaciones deScan
pueden ser muy costosas. Podemos lograr esto utilizando el parámetroLimit
y/o dividiendo el escaneo en segmentos más pequeños, utilizando la paginación.Para recuperar los registros del registro de auditoría para un usuario específico, podemos crear un índice secundario global (GSI) en el atributo
user
, conchangedAt
como clave de ordenamiento. Esto nos permitirá recuperar todos los registros para un usuario específico en orden cronológico inverso (el último cambio primero). Sin embargo, debemos tener en cuenta que la creación de un GSI aumentará el costo y la complejidad del sistema. Además, si el atributouser
no siempre está presente en los registros del registro de auditoría, necesitamos asegurarnos de manejar esos casos correctamente, utilizando un valor predeterminado o filtrando esos registros.En resumen, el diseño propuesto para el servicio de Registro de Auditoría utilizando
AWS Lambda
yDynamoDB
es:srcTable
srcId#changedAt
changes
– un mapa que almacena los valores antiguos y nuevos para cada atributo modificadouser
– identifica al usuario que realizó la acción de cambio.srcId/srcTable
dado [ ~90% ]srcTable
[ 5% ~ 7% ]user
[ 3% ~ 5% ]Para la primera consulta, podemos utilizar la operación
Query
con la clave de particiónsrcTable
y la clave de ordenamientobegins_with(srcId)
. Para la segunda consulta, podemos utilizar la operaciónScan
con la expresión de filtrosrcTable =: srcTable
. Para la tercera consulta, podemos crear un índice secundario global con la clave de particiónuser
y la clave de ordenamientochangedAt
y utilizar la operaciónQuery
en este índice.