shedLock ahora solo ejecuta el método de una instancia a la vez + redis implementa tareas de tiempo distribuidas

Dirección original: https://blog.csdn.net/qq_32182637/article/details/111871188

https://blog.csdn.net/qq_35913663/article/details/124910631

escrito en frente

Este artículo es solo un registro y resumen de mi propia práctica después de referirme a otros artículos recientes.Todavía hay muchas deficiencias en la escena y los detalles, que necesitan ser complementados y corregidos.

descripción general

ShedLock solo hace una cosa. Garantiza que las tareas programadas se ejecuten como máximo una vez a la vez. Si una tarea se ejecuta en un nodo, adquiere un bloqueo que impide la ejecución de la misma tarea desde otro nodo (o subproceso). Tenga en cuenta que si una tarea ya se ejecutó en un nodo, la ejecución en otros nodos no esperará, simplemente la omitirá.

Actualmente, se admiten tareas programadas de Spring coordinadas a través de Mongo, bases de datos JDBC, Redis, Hazelcast o ZooKeeper. Se esperan mecanismos de sincronización y coordinación adicionales en el futuro.

ShedLock necesita usar la anotación @SchedulerLock para implementar bloqueos para un método determinado. Los escenarios distribuidos son los escenarios principales y típicos para su aplicación, pero esto no significa que ShedLock solo se pueda usar en entornos distribuidos. Depende de su comprensión de su principios Cómo usarlo.

Breve análisis del principio ShedLock

El principio de ShedLock es muy simple. Primero observe la clase de anotación @SchedulerLock:

@Objetivo({TipoElemento.MÉTODO, TipoElemento.ANOTATION_TYPE})

@Retención(RetenciónPolicy.RUNTIME)

@interfaz pública SchedulerLock {

    Cadena nombre() por defecto "";

    long lockAtMostFor() por defecto -1L;

    Cadena lockAtMostForString() por defecto "";

    long lockAtLeastFor() por defecto -1L;

    Cadena lockAtLeastForString() por defecto "";

}

1

2

3

4

5

6

7

8

9

10

11

12

13

De acuerdo con la clase de anotación, podemos saber

Se puede usar en métodos (ElementType.METHOD), que es una forma común de anotación

Se puede usar en otras clases de anotación (ElementType.ANNOTATION_TYPE). No sé cómo aplicar esta situación. Lo probé brevemente, pero no tiene el efecto deseado.

El atributo de nombre indica el nombre del bloqueo, que distingue entre mayúsculas y minúsculas

lockAtMostFor toma el bloqueo durante más tiempo, en milisegundos

lockAtMostForString El tiempo más largo para ocupar el candado, tipo de carácter, "PT1S" significa 1 segundo, "PT1M" significa 1 minuto, si se establece al mismo tiempo que el atributo lockAtMostFor, prevalecerá lockAtMostFor

lockAtLeastFor El tiempo mínimo para ocupar la cerradura, en milisegundos

lockAtLeastForString El tiempo más corto de ocupación del candado, tipo de carácter, "PT1S" significa 1 segundo, "PT1M" significa 1 minuto, si se establece al mismo tiempo que el atributo lockAtLeastFor, prevalecerá lockAtLeastFor

La implementación de ShedLock se basa en el almacenamiento externo, incluidas las bases de datos convencionales, las cachés Redis, etc.

Nombre de campo Descripción

nombre El nombre del bloqueo, valor único, mayúsculas y minúsculas

lock_until La hora de finalización de la ocupación del bloqueo =locked_at +lockAtMostFor

bloqueado_at comienza a ocupar el tiempo de bloqueo

bloqueado_por ocupante, generalmente nombre de host

Al observar el código fuente, se puede encontrar que cuando se necesita adquirir un bloqueo, intentará insertar un registro en la tabla de shedlock y el nombre se usa como clave principal. Si no hay un bloqueo con el mismo nombre, el se insertará el registro y la cerradura se ocupará con éxito

INSERTAR EN shedlock(nombre, bloquear_hasta, bloqueado_en, bloqueado_por) VALORES(?, ?, ?, ?)

1

Si ya existe un bloqueo con el mismo nombre, se violará la restricción única de la clave principal y la inserción fallará. En este momento, intentará filtrar los registros con el mismo nombre de bloqueo en la tabla de bloqueo y tendrá sido liberado (bloqueo_hasta<hora actual). Si hay registros que cumplen con las condiciones, actualice el registro de registros y ocupó con éxito el bloqueo

ACTUALIZAR shedlock SET lock_until =?,locked_at=?,locked_by=? DONDE nombre = ? Y lock_until <= ?

1

Si no se pueden filtrar registros elegibles, significa que la adquisición del bloqueo ha fallado y se abandonará la tarea de ejecución.

Una vez completada la ejecución del método de tarea, si el tiempo actual no ha excedido el tiempo lock_until, el tiempo lock_until del registro actualizado está bloqueado_en+bloquearAlMenosPor, es decir, la duración de ocupar el bloqueo se cambia a la duración mínima

Además, debe tenerse en cuenta que ShedLock es un mecanismo de bloqueo basado en el tiempo. En un escenario distribuido, si se implementan diferentes nodos en diferentes hosts, el tiempo del host se utilizará de forma predeterminada. En este momento, es necesario enfatizar la sincronización de tiempo entre los hosts. Por supuesto, en la versión superior del paquete de dependencia, proporcionará el tiempo del host para configurar el almacenamiento externo, como el tiempo del host de la base de datos

Para obtener más detalles, consulte otro artículo "Principio de bloqueo distribuido de SchedulerLock"

ShedLock+Mysql

Primero necesitas importar dependencias

<!--Esta dependencia es el paquete de dependencia central de shedlock, que está en contacto con Spring y, a veces, la versión incorrecta hará que falle-->

<dependencia>

   <groupId>net.javacrumbs.shedlock</groupId>

    <artifactId>cobertizo-resorte</artifactId>

    <versión>2.2.0</versión>

</dependencia>

<!--Requerido para acceder a la base de datos-->

<dependencia>

    <groupId>net.javacrumbs.shedlock</groupId>

    <artifactId>shedlock-provider-jdbc-template</artifactId>

    <versión>2.2.0</versión>

</dependencia>

1

2

3

4

5

6

7

8

9

10

11

12

Crear tablas de base de datos

CREAR TABLA cobertizo (

  nombre varchar (64) COLLATE utf8mb4_bin NO NULO,

  lock_until timestamp(3) NO NULO,

  bloqueado_en marca de tiempo (3) NO NULO PREDETERMINADO CURRENT_TIMESTAMP (3),

  bloqueado_por varchar (255) COLLATE utf8mb4_bin NO NULO,

  CLAVE PRINCIPAL (nombre)

) MOTOR = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_bin;

1

2

3

4

5

6

7

Implementar una clase de configuración para proporcionar un LockProvider

importar net.javacrumbs.shedlock.core.LockProvider;

importar net.javacrumbs.shedlock.provider.jdbctemplate.JdbcTemplateLockProvider;

import net.javacrumbs.shedlock.spring.annotation.EnableSchedulerLock;

importar org.springframework.context.annotation.Bean;

importar org.springframework.context.annotation.Configuration;

importar org.springframework.jdbc.core.JdbcTemplate;

importar org.springframework.scheduling.annotation.EnableScheduling;

importar javax.sql.DataSource;

import static net.javacrumbs.shedlock.provider.jdbctemplate.JdbcTemplateLockProvider.Configuration.builder;

@Configuración

@EnableScheduling

@EnableSchedulerLock(defaultLockAtMostFor = "PT30S")

Configuración del programador de clase pública {

    @Frijol

    lockProvider public LockProvider(fuente de datos fuente de datos) {

//Puede personalizar la fuente de datos, lo que puede considerarse una consideración, y generalmente no usa esto

        org.apache.tomcat.jdbc.pool.DataSource dataSource1 = new org.apache.tomcat.jdbc.pool.DataSource();

        dataSource1.setUrl("jdbc:mysql://127.0.0.1:3601/ICSP?useUnicode=true&characterEncoding=utf8&useSSL=false");

        fuente de datos1.setUsername("tom");

        fuente de datos1.setPassword("tommy");

        LockProvider lockProvider= new JdbcTemplateLockProvider(constructor()

        //Especifique el nombre de la tabla

                .withTableName("cobertizo")

                //Especifique la fuente de datos, generalmente use dataSource en lugar de la fuente de datos definida manualmente

                .withJdbcTemplate(nueva JdbcTemplate(fuente de datos1))

                //Especifique el nombre del campo de la tabla, la cantidad de campos es fija, solo se puede cambiar el nombre y solo la versión superior de la dependencia shedlock-provider-jdbc-template proporciona este elemento de configuración

// .withColumnNames(new JdbcTemplateLockProvider.ColumnNames("nombre","bloquear_hasta","bloqueado_en","bloqueado_por"))

//Utilice la hora de la base de datos, solo la versión superior de la dependencia shedlock-provider-jdbc-template proporciona este elemento de configuración

// .usandoDbTime()

//La función es desconocida, solo la dependencia de versión superior shedlock-provider-jdbc-template proporciona este elemento de configuración

// .withLockedByValue("mivalor")

//La función es desconocida, solo la dependencia de versión superior shedlock-provider-jdbc-template proporciona este elemento de configuración

// .conNivelDeAislamiento(1)

                .construir());

        return proveedorcerradura;

    }

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

dieciséis

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

Con respecto a la configuración anterior, se necesitan algunas instrucciones complementarias:

@EnableScheduling debe agregarse solo cuando se usan tareas programadas, que también es el escenario de aplicación más típico de shedlock

La anotación @EnableSchedulerLock elimina la posibilidad de establecer el tiempo más largo y más corto predeterminado para ocupar la cerradura.También hay un parámetro de modo, y los valores que se pueden configurar son:

descripción del valor

EnableSchedulerLock.InterceptMode.PROXY_SCHEDULER se usa con @Scheduled

EnableSchedulerLock.InterceptMode.PROXY_METHOD se usa solo en el método, lo que significa que siempre que se llame al método, intentará ocupar el bloqueo, que es otro escenario de uso de shedlock

La versión Shedlock-provider-jdbc-template agrega la comparación del método JdbcTemplateLockProvider.Configuration.builder

Método Agregar versión

4.1.0 .con nombres de columna

.withLockedByValue

4.9.0 .usandoDbTime

4.27.0 .con nivel de aislamiento

4. Si usa una versión superior dependiente de shedlock-provider-jdbc-template, también debe usar una versión superior de la versión dependiente de shedlock-spring, de lo contrario, se informará un error durante la ejecución. Y si se usa una versión más alta de dependencia de shedlock-spring, es posible que también deba coincidir con la versión de dependencia del contexto de spring (solo una suposición, qué dependencia no se ha confirmado). version hará que al registrar una Tarea, la tarea no se configure como LockabaleRunable, sino como ScheduledMethodRunable ordinario, el impacto directo es que el shedlock de la tarea programada fallará.

Acabo de encontrar un problema aquí, pero no sé cómo resolverlo. Si sabe que desea usar shedlock-provider-jdbc-template versión 4.27.0 y superior, puede usar otros paquetes dependientes. Bienvenido informar

Luego puede usar la anotación @SchedulerLock

ShedLock+Redis

1. archivo pom

Redis debe tener:

<dependencia>

    <groupId>org.springframework.boot</groupId>

    <artifactId>spring-boot-starter-data-redis</artifactId>

</dependencia>

artículos requeridos shedlock:

<dependencia>

    <groupId>net.javacrumbs.shedlock</groupId>

    <artifactId>cobertizo-resorte</artifactId>

    <versión>4.19.1</versión>

</dependencia>

Opciones de Shedlock (aquí se usa redis, también se pueden usar otras bases de datos, consulte el sitio web oficial https://github.com/lukas-krecan/ShedLock para obtener más detalles):

<dependencia>

    <groupId>net.javacrumbs.shedlock</groupId>

    <artifactId>shedlock-provider-redis-spring</artifactId>

    <versión>2.5.0</versión>

</dependencia>

————————————————

@Configuración

@EnableScheduling

@EnableSchedulerLock(defaultLockAtMostFor = "10m")

clase pública ShedLockConfig {

    @Recurso

    RedisTemplate<Cadena, Objeto> redisTemplate;

    @Frijol

    proveedor de bloqueo público proveedor de bloqueo () {

        devolver nuevo RedisLockProvider(redisTemplate.getConnectionFactory());

    }

}

@Slf4j

@Componente

Clase pública TaskRun {

    @Programado(cron = "0 0 */1 * *?")

    @SchedulerLock(nombre = "fylr")

    fylr vacío público () {

        System.out.println("ejecutar...");

    }

}

ShedLock+Mongo

Para ser agregado

Bloqueo de cobertizo+Guardián del zoológico

Para ser agregado

————————————————

Declaración de derechos de autor: este artículo es un artículo original del bloguero de CSDN "Zhao Jiaen", siguiendo el acuerdo de derechos de autor CC 4.0 BY-SA. Adjunte el enlace de la fuente original y esta declaración para su reimpresión.

Enlace original: https://blog.csdn.net/qq_35913663/article/details/124910631

Supongo que te gusta

Origin blog.csdn.net/zhongguowangzhan/article/details/127312995
Recomendado
Clasificación