返回顶部
首页 > 资讯 > 精选 >Redis分布式锁遇到的序列化问题有哪些
  • 792
分享到

Redis分布式锁遇到的序列化问题有哪些

2023-06-14 09:06:49 792人浏览 八月长安
摘要

这篇文章主要介绍Redis分布式锁遇到的序列化问题有哪些,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!问题排查既然是释放锁有问题,那就先看看释放锁的代码吧。释放锁释放锁使用了 lua 脚本,代码逻辑和 Lua 脚本如

这篇文章主要介绍Redis分布式遇到的序列化问题有哪些,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!

问题排查

既然是释放锁有问题,那就先看看释放锁的代码吧。

释放锁

释放锁使用了 lua 脚本,代码逻辑和 Lua 脚本如下:

释放锁示例代码

public Object release(String key, String value) { Object existedValue = stringRedisTemplate.opsForValue().get(key); log.info("key:{}, value:{}, redis旧值:{}", key, value, existedValue);  DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>(COMPARE_AND_DELETE, Long.class); return stringRedisTemplate.execute(redisScript, Collections.singletonList(key), value);}

释放锁使用的 Lua 脚本

if redis.call('get',KEYS[1]) == ARGV[1]then return redis.call('del',KEYS[1])else return 0end;

删除脚本中,会先获取 Redis key 的旧值,并与入参 value 比较,二者相等时才会删除。
如果释放成功,也就是 Redis 缓存删除成功,返回值为 1,否则失败返回为 0。
乍一看代码似乎没啥问题,测一下试试?
不过既然要释放锁,在此之前肯定要加锁,先看看加锁的逻辑吧。

加锁

说到加锁这里的逻辑,代码里有两种实现方式:

示例代码一

public Object lock01(String key, String value) { log.info("lock01, key={}, value={}", key, value); return redisTemplate.opsForValue().setIfAbsent(key, value, LOCKED_TIME, TimeUnit.SECONDS);}

示例代码二

public Object lock02(String key, String value) { log.info("lock02, key={}, value={}", key, value); return stringRedisTemplate.opsForValue().setIfAbsent(key, value, LOCKED_TIME, TimeUnit.SECONDS);}

其实它们的区别就在于前者使用了 RedisTemplate,而后者使用的是 StringRedisTemplate。

Q: 等等……为什么会有两个 template??
A: 憋说了,是我挖的坑,RedisTemplate 是我加的……现在回想都没想明白当初为什么这样搞,可能真是脑子一时抽风了。

测试一下这两个方法?

测试一下

使用两种方式分别加锁,其中:lock01 为 k1 和 v1,lock02 为 k2 和 v2。
分别看下 k1、k2 的值(使用工具:RDM, Redis Desktop Manager):

Redis分布式锁遇到的序列化问题有哪些

Redis分布式锁遇到的序列化问题有哪些

可以看到 v1 是有双引号的,而 v2 没有。
猜测应该是序列化的问题,看看 Redis 配置?

RedisTemplate 配置

加锁那里可以看到,k1 使用了 RedisTemplate,而 k2 是 StringRedisTemplate,它们两个的配置有什么区别呢?
其中 RedisTemplate 的配置是自定义的,如下:

@Configuration@AutoConfigureAfter(RedisAutoConfiguration.class)public class RedisConfig { @Bean public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) { RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>(); redisTemplate.setConnectionFactory(redisConnectionFactory); // 使用 Jackson2JSONRedisSerialize 替换默认序列化 Jackson2jsonRedisSerializer<Object> jackson2JsonRedisSerializer  = new Jackson2JsonRedisSerializer<>(Object.class); ObjectMapper objectMapper = new ObjectMapper(); objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); objectMapper.configure(DeserializationFeature.FaiL_ON_UNKNOWN_PROPERTIES, false); jackson2JsonRedisSerializer.setObjectMapper(objectMapper); // 设置 key、value 的序列化规则(尤其是 value) redisTemplate.seTKEySerializer(new StringRedisSerializer()); redisTemplate.setValueSerializer(jackson2JsonRedisSerializer); redisTemplate.afterPropertiesSet(); return redisTemplate; }}

StringRedisTemplate 的配置是 SpringBoot 默认的,即:

@Configuration@ConditionalOnClass({RedisOperations.class})@EnableConfigurationProperties({RedisProperties.class})@Import({LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class})public class RedisAutoConfiguration { public RedisAutoConfiguration() { } @Bean @ConditionalOnMissingBean public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) throws UnknownHostException { StringRedisTemplate template = new StringRedisTemplate(); template.setConnectionFactory(redisConnectionFactory); return template; }}

PS: springBoot 版本为 2.1.13.RELEASE

点进去 StringRedisTemplate 看下:

public class StringRedisTemplate extends RedisTemplate<String, String> {  public StringRedisTemplate() { // 注意这里的序列化设置 setKeySerializer(RedisSerializer.string()); setValueSerializer(RedisSerializer.string()); setHashKeySerializer(RedisSerializer.string()); setHashValueSerializer(RedisSerializer.string()); } // ...}

注意下序列化设置,继续跟进,看到底是什么方式:

public interface RedisSerializer<T> { static RedisSerializer<String> string() { return StringRedisSerializer.UTF_8; }}
public class StringRedisSerializer implements RedisSerializer<String> { public static final StringRedisSerializer UTF_8 = new StringRedisSerializer(StandardCharsets.UTF_8); // ...}

可以看到,StringRedisTemplate 的 key 和 value 默认都是用 StringRedisSerializer(StandardCharsets.UTF_8) 进行序列化的。

而 RedisTemplate 的 key 使用 StringRedisSerializer,value 使用的是 Jackson2JsonRedisSerializer 序列化(至于为什么用这个,这里就不是我写的了)。
到这里,基本可以定位到问题所在了:就是 RedisTemplate 的 value 序列化和 StringRedisTemplate 不一致。

如果改成一致就可以了吗?验证一下试试。

验证推论

把 RedisTemplate 的 value 序列化方式修改为 StringRedisSerializer:

@Configuration@AutoConfigureAfter(RedisAutoConfiguration.class)public class RedisConfig { @Bean public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) { RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();   // ... redisTemplate.setKeySerializer(new StringRedisSerializer()); redisTemplate.setValueSerializer(new StringRedisSerializer()); // ... return redisTemplate; }}

再调用两种加锁逻辑,看下 k1、k2 的值:

Redis分布式锁遇到的序列化问题有哪些

Redis分布式锁遇到的序列化问题有哪些

可以看到,v1 的双引号没了,释放锁的服务也能正常删掉了。
嗯,就是这里的问题。
至于两者序列化的源码,有兴趣的盆友们可以继续研究,这里就不再深入探讨了。

以上是“Redis分布式锁遇到的序列化问题有哪些”这篇文章的所有内容,感谢各位的阅读!希望分享的内容对大家有帮助,更多相关知识,欢迎关注编程网精选频道!

--结束END--

本文标题: Redis分布式锁遇到的序列化问题有哪些

本文链接: https://lsjlt.com/news/269396.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • Redis分布式锁遇到的序列化问题有哪些
    这篇文章主要介绍Redis分布式锁遇到的序列化问题有哪些,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!问题排查既然是释放锁有问题,那就先看看释放锁的代码吧。释放锁释放锁使用了 Lua 脚本,代码逻辑和 Lua 脚本如...
    99+
    2023-06-14
  • 详解Redis 分布式锁遇到的序列化问题
    场景描述 最近使用 Redis 遇到了一个类似分布式锁的场景,跟 Redis 实现分布式锁类比一下,就是释放锁失败,也就是缓存删不掉。又踩了一个 Redis 的坑…… 这是什么个情...
    99+
    2024-04-02
  • RedisTemplate下Redis分布式锁引发的系列问题有哪些
    这篇文章主要介绍了RedisTemplate下Redis分布式锁引发的系列问题有哪些,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。     首先...
    99+
    2023-06-14
  • Redis中怎么序列化分布式锁
    今天就跟大家聊聊有关Redis中怎么序列化分布式锁,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。问题排查既然是释放锁有问题,那就先看看释放锁的代码吧...
    99+
    2024-04-02
  • Redis分布式锁有哪些
    Redis分布式锁有哪些?这个问题可能是我们日常学习或工作经常见到的。希望通过这个问题能让你收获颇深。下面是小编给大家带来的参考内容,让我们一起来看看吧!我们通常使用的synchronized或者Lock都...
    99+
    2024-04-02
  • redis分布式锁的坑有哪些
    这篇“redis分布式锁的坑有哪些”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“redis分布式锁的坑有哪些”文章吧。1 非...
    99+
    2023-07-02
  • Go系统遇到的锁问题有哪些
    本篇内容介绍了“Go系统遇到的锁问题有哪些”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!底层依赖 sync...
    99+
    2024-04-02
  • redis分布式锁的作用有哪些
    防止多个客户端同时操作同一个资源,保证数据的一致性和完整性。 避免资源的并发访问导致的竞态条件和错误。 控制对共享资源的...
    99+
    2024-04-09
    redis
  • Redis分布式锁的实现方式有哪些
    分布式锁是控制分布式系统之间同步访问共享资源的一种方式。在分布式系统中,常常需要协调他们的动作。如果不同的系统或是同一个系统的不同主机之间共享了一个或一组资源,那么访问这些资源的时候,往往需要互斥来防止彼此...
    99+
    2024-04-02
  • redis中的分布式锁有哪些特点
    本篇内容主要讲解“redis中的分布式锁有哪些特点”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“redis中的分布式锁有哪些特点”吧! ...
    99+
    2023-04-14
    redis
  • 使用Redis可能遇到的问题有哪些
    这篇文章主要介绍使用Redis可能遇到的问题有哪些,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!这篇文章,我想和你聊一聊在使用 Redis 时,可能会踩到的「坑」。如果你在使用 Re...
    99+
    2024-04-02
  • 详解RedisTemplate下Redis分布式锁引发的系列问题
          自己的项目因为会一直抓取某些信息,但是本地会和线上经常一起跑,造成冲突。这其实就是我们常说的分布式集群的问题了,本地和线...
    99+
    2024-04-02
  • Redis实现分布式锁的方法有哪些
    今天小编给大家分享一下Redis实现分布式锁的方法有哪些的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。1. 单机数据一致性单...
    99+
    2023-07-02
  • zk和redis分布式锁有哪些区别
    这篇文章给大家分享的是有关zk和redis分布式锁有哪些区别的内容。小编觉得挺实用的,因此分享给大家做个参考。一起跟随小编过来看看吧。 Redis实现分布式锁根据lockKey区进行setnx(s...
    99+
    2024-04-02
  • Redis支持的序列化格式有哪些
    Redis支持的序列化格式有: RESP(REdis Serialization Protocol):Redis自定义的序列化协议...
    99+
    2024-04-30
    Redis
  • 使用Spring Session管理分布式会话时遇到的反序列化问题怎么解决
    这篇文章主要介绍“使用Spring Session管理分布式会话时遇到的反序列化问题怎么解决”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“使用Spring Sess...
    99+
    2024-04-02
  • 如何解决redis分布式锁的问题
    这篇文章主要为大家展示了“如何解决redis分布式锁的问题”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“如何解决redis分布式锁的问题”这篇文章吧。分布式锁在...
    99+
    2024-04-02
  • 解决python-redis-lock分布式锁的问题
    python-redis-lock 官方文档 不错的博文可参考 问题背景 在使用celery执行我们的异步任务时,为了提高效率,celery可以开启多个进程来启动对应的worke...
    99+
    2024-04-02
  • Redis专题(3):锁的基本概念到Redis分布式锁实现
    拓展阅读:Redis闲谈(1):构建知识图谱 Redis专题(2):Redis数据结构底层探秘 近来,分布式的问题被广泛提及,比如分布式事务、分布式框架、ZooKeeper、SpringCloud等等。本文...
    99+
    2024-04-02
  • 小程序开发中遇到的问题有哪些
    这篇文章主要介绍小程序开发中遇到的问题有哪些,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!小程序面试题bindtap和catchtap的区别是什么?bind事件绑定不会阻止冒泡事件向上冒泡,catch事件绑定可以阻止...
    99+
    2023-06-14
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作