Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to implement distributed Lock with redis and shedlock

2025-02-24 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Internet Technology >

Share

Shulou(Shulou.com)06/02 Report--

How to use redis and shedlock to achieve distributed locks, many novices are not very clear about this, in order to help you solve this problem, the following editor will explain for you in detail, people with this need can come to learn, I hope you can gain something.

1. Introduction of jar package

Org.springframework.boot

Spring-boot-starter-web

Org.springframework.boot

Spring-boot-starter-test

Test

Org.junit.vintage

Junit-vintage-engine

Org.springframework.boot

Spring-boot-starter-data-redis

Net.javacrumbs.shedlock

Shedlock-provider-redis-spring

2.3.0

Org.apache.commons

Commons-pool2

2.0

Net.javacrumbs.shedlock

Shedlock-spring

2.3.0

Org.projectlombok

Lombok

Com.github.xiaoymin

Swagger-bootstrap-ui

1.9.6

Io.springfox

Springfox-swagger2

2.9.2

Org.aspectj

Aspectjweaver

1.9.2

2. Configuration file # redis for redis

Redis.host=192.168.1.6

Redis.password=

Redis.port=6379

Redis.taskScheduler.poolSize=100

Redis.taskScheduler.defaultLockMaxDurationMinutes=10

Redis.default.timeout=10

RedisCache.expireTimeInMilliseconds=1200000

Configuration class package com.example.redis_demo_limit.redis

Import io.lettuce.core.ClientOptions

Import io.lettuce.core.resource.ClientResources

Import io.lettuce.core.resource.DefaultClientResources

Import net.javacrumbs.shedlock.core.LockProvider

Import net.javacrumbs.shedlock.provider.redis.spring.RedisLockProvider

Import net.javacrumbs.shedlock.spring.ScheduledLockConfiguration

Import net.javacrumbs.shedlock.spring.ScheduledLockConfigurationBuilder

Import org.apache.commons.pool2.impl.GenericObjectPoolConfig

Import org.springframework.beans.factory.annotation.Value

Import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean

Import org.springframework.context.annotation.Bean

Import org.springframework.context.annotation.Configuration

Import org.springframework.context.annotation.Primary

Import org.springframework.data.redis.connection.RedisConnectionFactory

Import org.springframework.data.redis.connection.RedisPassword

Import org.springframework.data.redis.connection.RedisStandaloneConfiguration

Import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory

Import org.springframework.data.redis.connection.lettuce.LettucePoolingClientConfiguration

Import org.springframework.data.redis.core.RedisTemplate

Import java.time.Duration

@ Configuration

Public class RedisConfig {

@ Value ("${redis.host}")

Private String redisHost

@ Value ("${redis.port}")

Private int redisPort

@ Value ("${redis.password}")

Private String password

@ Value ("${redis.taskScheduler.poolSize}")

Private int tasksPoolSize

@ Value ("${redis.taskScheduler.defaultLockMaxDurationMinutes}")

Private int lockMaxDuration

@ Bean (destroyMethod = "shutdown")

ClientResources clientResources () {

Return DefaultClientResources.create ()

}

@ Bean

Public RedisStandaloneConfiguration redisStandaloneConfiguration () {

RedisStandaloneConfiguration redisStandaloneConfiguration =

New RedisStandaloneConfiguration (redisHost, redisPort)

If (password! = null & &! password.trim () .equals (")) {

RedisPassword redisPassword = RedisPassword.of (password)

RedisStandaloneConfiguration.setPassword (redisPassword)

}

Return redisStandaloneConfiguration

}

@ Bean

Public ClientOptions clientOptions () {

Return ClientOptions.builder ()

.disconnectedBehavior (ClientOptions.DisconnectedBehavior.REJECT_COMMANDS)

.autoReconnect (true) .build ()

}

@ Bean

LettucePoolingClientConfiguration lettucePoolConfig (ClientOptions options, ClientResources dcr) {

Return LettucePoolingClientConfiguration.builder () .poolConfig (new GenericObjectPoolConfig ()

.clientOptions (options) .clientResources (dcr). Build ()

}

@ Bean

Public RedisConnectionFactory connectionFactory (

RedisStandaloneConfiguration redisStandaloneConfiguration

LettucePoolingClientConfiguration lettucePoolConfig) {

Return new LettuceConnectionFactory (redisStandaloneConfiguration, lettucePoolConfig)

}

@ Bean

@ ConditionalOnMissingBean (name = "redisTemplate")

@ Primary

Public RedisTemplate redisTemplate (

RedisConnectionFactory redisConnectionFactory) {

RedisTemplate template = new RedisTemplate ()

Template.setConnectionFactory (redisConnectionFactory)

Return template

}

@ Bean

Public LockProvider lockProvider (RedisConnectionFactory connectionFactory) {

Return new RedisLockProvider (connectionFactory)

}

@ Bean

Public ScheduledLockConfiguration taskSchedulerLocker (LockProvider lockProvider) {

Return ScheduledLockConfigurationBuilder.withLockProvider (lockProvider)

.withPoolSize (tasksPoolSize) .withDefaultLockAtMostFor (Duration.ofMinutes (lockMaxDuration))

.build ()

}

}

Operation class package com.example.redis_demo_limit.redis

Public interface DataCacheRepository {

Boolean add (String collection, String hkey, T object, Long timeout)

Boolean delete (String collection, String hkey)

T find (String collection, String hkey, Class tClass)

Boolean isAvailable ()

/ * *

* redis lock

*

* @ param key

* @ param second

* @ return

, /

Boolean lock (String key, String value, Long second)

Object getValue (String key)

/ * *

* redis unlock

*

* @ param key

* @ return

, /

Void unLock (String key)

Void setIfAbsent (String key, long value, long ttl)

Void increment (String key)

Long get (String key)

Void set (String key, long value, long ttl)

Void set (Object key, Object value, long ttl)

Object getByKey (String key)

Void getLock (String key, String clientID) throws Exception

Void releaseLock (String key, String clientID)

Boolean hasKey (String key)

}

Implementation class

Package com.example.redis_demo_limit.redis

Import com.fasterxml.jackson.databind.ObjectMapper

Import lombok.extern.slf4j.Slf4j

Import org.slf4j.Logger

Import org.slf4j.LoggerFactory

Import org.springframework.beans.factory.annotation.Autowired

Import org.springframework.beans.factory.annotation.Value

Import org.springframework.data.redis.core.RedisTemplate

Import org.springframework.data.redis.core.ValueOperations

Import org.springframework.data.redis.support.atomic.RedisAtomicLong

Import org.springframework.stereotype.Repository

Import java.time.Duration

Import java.util.TimeZone

Import java.util.concurrent.TimeUnit

@ Slf4j

@ Repository

Public class CacheRepository implements com.example.redis_demo_limit.redis.DataCacheRepository {

Private static final ObjectMapper OBJECT_MAPPER

Private static final TimeZone DEFAULT_TIMEZONE = TimeZone.getTimeZone ("UTC")

Static {

OBJECT_MAPPER = new ObjectMapper ()

OBJECT_MAPPER.setTimeZone (DEFAULT_TIMEZONE)

}

Logger logger = LoggerFactory.getLogger (CacheRepository.class)

@ Autowired

RedisTemplate template; / / and we're in business

@ Value ("${redis.default.timeout} 00")

Long defaultTimeOut

Public boolean addPermentValue (String collection, String hkey, T object) {

Try {

String jsonObject = OBJECT_MAPPER.writeValueAsString (object)

Template.opsForHash () .put (collection, hkey, jsonObject)

Return true

} catch (Exception e) {

Logger.error ("Unable to add object of key {} to cache collection'{}': {}", hkey, collection

E.getMessage ()

Return false

}

}

@ Override

Public boolean add (String collection, String hkey, T object, Long timeout) {

Long localTimeout

If (timeout = = null) {

LocalTimeout = defaultTimeOut

} else {

LocalTimeout = timeout

}

Try {

String jsonObject = OBJECT_MAPPER.writeValueAsString (object)

Template.opsForHash () .put (collection, hkey, jsonObject)

Template.expire (collection, localTimeout, TimeUnit.SECONDS)

Return true

} catch (Exception e) {

Logger.error ("Unable to add object of key {} to cache collection'{}': {}", hkey, collection

E.getMessage ()

Return false

}

}

@ Override

Public boolean delete (String collection, String hkey) {

Try {

Template.opsForHash () .delete (collection hkey)

Return true

} catch (Exception e) {

Logger.error ("Unable to delete entry {} from cache collection'{}': {}", hkey, collection

E.getMessage ()

Return false

}

}

@ Override

Public T find (String collection, String hkey, Class tClass) {

Try {

String jsonObj = String.valueOf (template.opsForHash () .get (collection, hkey))

Return OBJECT_MAPPER.readValue (jsonObj, tClass)

} catch (Exception e) {

If (e.getMessage ()) = = null) {

Logger.error ("Entry'{} 'does not exist in cache", hkey)

} else {

Logger.error ("Unable to find entry'{}'in cache collection'{}': {}", hkey, collection

E.getMessage ()

}

Return null

}

}

@ Override

Public Boolean isAvailable () {

Try {

Return template.getConnectionFactory () .getConnection () .ping ()! = null

} catch (Exception e) {

Logger.warn ("Redis server is not available at the moment.")

}

Return false

}

@ Override

Public Boolean lock (String key, String value, Long second) {

Boolean absent = template.opsForValue () .setIfAbsent (key, value, second, TimeUnit.SECONDS)

Return absent

}

@ Override

Public Object getValue (String key) {

Return template.opsForValue () get (key)

}

@ Override

Public void unLock (String key) {

Template.delete (key)

}

@ Override

Public void increment (String key) {

RedisAtomicLong counter = new RedisAtomicLong (key, template.getConnectionFactory ())

Counter.incrementAndGet ()

}

@ Override

Public void setIfAbsent (String key, long value, long ttl) {

ValueOperations ops = template.opsForValue ()

Ops.setIfAbsent (key, value, Duration.ofSeconds (ttl))

}

@ Override

Public Long get (String key) {

RedisAtomicLong counter = new RedisAtomicLong (key, template.getConnectionFactory ())

Return counter.get ()

}

@ Override

Public void set (String key, long value, long ttl) {

RedisAtomicLong counter = new RedisAtomicLong (key, template.getConnectionFactory ())

Counter.set (value)

Counter.expire (ttl, TimeUnit.SECONDS)

}

@ Override

Public void set (Object key, Object value, long ttl) {

Template.opsForValue () .set (key, value, ttl, TimeUnit.SECONDS)

}

@ Override

Public Object getByKey (String key) {

Return template.opsForValue () get (key)

}

@ Override

Public void getLock (String key, String clientID) throws Exception {

Boolean lock = false

/ / retry 3 times, retry once every 1 second

For (int j = 0; j

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Internet Technology

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report