Recuerde el procesamiento concurrente de diferentes aplicaciones, utilizando transacciones mysql y bloqueos de fila.

Aprovechando las características de MySQL

nivel de aislamiento

En primer lugar, la base de datos es 5.6.70 y el nivel de aislamiento predeterminado es Lectura repetible. El nivel de aislamiento de la base de datos es Lectura repetible.
Después de que la transacción comienza hasta que finaliza, siempre se lee el mismo valor.

bloqueo de fila

La actualización tiene bloqueos de filas de forma predeterminada. La actualización de Mysql bloquea filas o tablas.

Antecedentes de los requisitos del proyecto

La instancia de premio de actividad de inicio de sesión original y la instancia de cupón generan lógica de consumo

  • Originalmente, el backend generaba instancias de premios y cupones después de que el evento se revisara exitosamente.
  • La interfaz de solicitud de registro del usuario vincula la instancia del premio y la instancia del cupón. El inventario se reduce en uno. El método consiste en consultar primero, reducir el código en uno y luego actualizar.

Ahora es necesario agregar instancias de premios y cupones para el evento de inicio de sesión.

  • Cuando se genera en segundo plano, el consumo se realiza en el lado de la interfaz y el cupón recién generado está vinculado. Esto no es bueno y puede haber problemas desconocidos. Sin embargo, debido a la existencia de la transacción, no se generará. hasta el final de la transacción será leído, así que no te preocupes
  • Problema de simultaneidad del inventario : una vez que se genera la instancia en segundo plano, el inventario original aumenta, pero la interfaz también puede reducir el inventario.

Solución

Método 1: No aconsejable

Agregue bloqueos de Redis a ambos lados, increméntelos respectivamente y finalmente actualice. Debido a la existencia del bloqueo, solo una declaración está operando en este inventario.

El siguiente es un pseudocódigo.

后台事务A{

​	redis锁A{
​			select stock;
			stock=stock+N;
​			update  stock=xx where id=1;
​	}

}



接口事务B{

​	redis锁A{
​			select stock;
			stock=stock-1;
​			update  stock=xx where id=1;
​	}

}

Era una buena idea, pero cuando lo pensé más detenidamente, descubrí que había lagunas.

  1. En el momento en que se ejecuta el bloqueo de redis A de la transacción en segundo plano A, la transacción aún no se ha enviado.
  2. Comienza a ejecutarse el bloqueo de redis A de la transacción de interfaz B. El inventario consultado en este momento no es el último después de la actualización de la transacción en segundo plano A.
  3. En este momento, la transacción en segundo plano A también se ejecutó y el inventario cambió.
  4. Cuando se ejecuta la transacción de interfaz B para actualizar, el inventario actualizado por la transacción en segundo plano A se sobrescribirá, lo que provocará que los datos se ensucien.

Método 2: deseable

Simplemente use la función de bloqueo de fila de la actualización de MySQL mencionada anteriormente. También puede usar la actualización, pero no necesita consultarla en el código y agregarla directamente en el
fondo de las adiciones y eliminaciones. Dado que la identificación es el índice, el La fila se bloqueará en lugar de la tabla.

UPDATE stockTable a SET a.currentInventory = a.currentInventory + N WHERE a.id = 1

La interfaz determina que el inventario es mayor que 0 y lo reduce directamente en 1. El código aquí puede determinar si la recopilación se realizó correctamente en función del número de filas actualizado.

UPDATE stockTable a SET a.currentInventory = a.currentInventory - 1 WHERE a.id = 1 AND a.currentInventory > 0

Esto es muy conveniente y simple, y ni siquiera necesita agregar un candado distribuido.

Supongo que te gusta

Origin blog.csdn.net/Fire_Sky_Ho/article/details/120229922
Recomendado
Clasificación