基于Redis的分布式共享锁
发布日期:2021-11-15 14:57:36 浏览次数:25 分类:技术文章

本文共 3844 字,大约阅读时间需要 12 分钟。

此文档主要演示了如何使用 Spring Boot 集成RedisTemplate实现分布式锁。

application.yml

spring:  redis:    host: localhost    # 连接超时时间(记得添加单位,Duration)    timeout: 10000ms    # Redis默认情况下有16个分片,这里配置具体使用的分片    # database: 0    lettuce:      pool:        # 连接池最大连接数(使用负值表示没有限制) 默认 8        max-active: 8        # 连接池最大阻塞等待时间(使用负值表示没有限制) 默认 -1        max-wait: -1ms        # 连接池中的最大空闲连接 默认 8        max-idle: 8        # 连接池中的最小空闲连接 默认 0        min-idle: 0

pom.xml

基于 Spring Boot 引入redis

org.springframework.boot
spring-boot-starter-data-redis
org.apache.commons
commons-pool2

RedisConfig

基于Spring Boot 的 redis配置

/** * redis配置 * @author xiehengxing * @date 2020/7/29 18:30 */@Configuration@AutoConfigureAfter(RedisAutoConfiguration.class)@EnableCachingpublic class RedisConfig {
/** * 默认情况下的模板只能支持RedisTemplate
,也就是只能存入字符串,因此支持序列化 */ @Bean public RedisTemplate
redisCacheTemplate(LettuceConnectionFactory redisConnectionFactory) {
RedisTemplate
template = new RedisTemplate<>(); template.setKeySerializer(new StringRedisSerializer()); template.setValueSerializer(new GenericJackson2JsonRedisSerializer()); template.setConnectionFactory(redisConnectionFactory); return template; } /** * 配置使用注解的时候缓存配置,默认是序列化反序列化的形式,加上此配置则为 json 形式 */ @Bean public CacheManager cacheManager(RedisConnectionFactory factory) {
// 配置序列化 RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig(); RedisCacheConfiguration redisCacheConfiguration = config.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer())).serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer())); return RedisCacheManager.builder(factory).cacheDefaults(redisCacheConfiguration).build(); }}

RedisLock

分布式共享锁的实现

/** * 分布式共享锁 * @author xiehengxing * @date 2020/8/2 10:40 */@Slf4j@Componentpublic class RedisLock {
@Autowired private RedisTemplate redisTemplate; /** * 共享锁默认时长(秒) */ private static final long TIMEOUT = 60; /** * 超时时长(秒) */ private static final long OVERTIME = 6; /** * 获取锁 * @param key * @param requestId * @return */ public boolean lock(String key, String requestId){
long startTime = System.currentTimeMillis(); for(;;) {
boolean locked = redisTemplate.opsForValue().setIfAbsent(key, requestId, TIMEOUT, TimeUnit.SECONDS); if (locked) {
return true; } if ((System.currentTimeMillis() - startTime)/1000 > OVERTIME) {
return false; } try {
Thread.sleep(300); } catch (InterruptedException e) {
log.error("线程被中断" + Thread.currentThread().getId(), e); } } } /** * 使用lua脚本解锁 * @param key * @param requestId * @return */ public boolean unlock(String key, String requestId) {
if (StringUtils.isEmpty(key) || StringUtils.isEmpty(requestId)){
return false; } DefaultRedisScript
redisScript = new DefaultRedisScript(); //用于解锁的lua脚本位置 redisScript.setScriptText( "if redis.call('get', KEYS[1]) == ARGV[1] then " + "return redis.call('del', KEYS[1]) " + "else " + "return 0" + "end"); redisScript.setResultType(Long.class); //没有指定序列化方式,默认使用上面配置的 Object result = redisTemplate.execute(redisScript, Collections.singletonList(key), requestId); return result.equals(Long.valueOf(1)); }}

转载地址:https://blog.csdn.net/qq_39739458/article/details/107974476 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:基于Redis的实时排行榜
下一篇:Django过滤器常用方法

发表评论

最新留言

表示我来过!
[***.240.166.169]2024年04月25日 20时40分37秒

关于作者

    喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!

推荐文章