Spring Boot 整合 Redis 正确的实现分布式锁

前言

最近在做分块上传的业务,使用到了Redis来维护上传过程中的分块编号。

每上传完成一个分块就获取一下文件的分块集合,加入新上传的编号,手动接口测试下是没有问题的,前端通过并发上传调用就出现问题了,并发的get再set,就会存在覆盖写现象,导致最后的分块数据不对,不能触发分块合并请求。

遇到并发二话不说先上锁,针对执行代码块加了一个JVM锁之后问题就解决了。

仔细一想还是不太对,项目是分布式部署的,做了负载均衡,一个节点的代码被锁住了,请求轮询到其他节点还是可以进行覆盖写,并没有解决到问题啊

没办法,只有用上分布式锁了。之前对于分布式锁的理论还是很熟悉的,没有比较好的应用场景就没写过具体代码,趁这个机会就学习使用一下分布式锁。

理论

分布式锁是控制分布式系统之间同步访问共享资源的一种方式。是为了解决分布式系统中,不同的系统或是同一个系统的不同主机共享同一个资源的问题,它通常会采用互斥来保证程序的一致性

在这里插入图片描述
通常的实现方式有三种:

  • 基于 MySQL 的悲观锁来实现分布式锁,这种方式使用的最少,这种实现方式的性能不好,且容易造成死锁,并且MySQL本来业务压力就很大了,再做锁也不太合适
  • 基于 Redis 实现分布式锁,单机版可用setnx实现,多机版建议用Radission
  • 基于 ZooKeeper 实现分布式锁,利用 ZooKeeper 顺序临时节点来实现

为了确保分布式锁可用,我们至少要确保锁的实现同时满足以下四个条件:

  • 互斥性。在任意时刻,只有一个客户端能持有锁。
  • 不会发生死锁。即使有一个客户端在持有锁的期间崩溃而没有主动解锁,也能保证后续其他客户端能加锁。
  • 具有容错性。只要大部分的Redis节点正常运行,客户端就可以加锁和解锁。
  • 解铃还须系铃人。加锁和解锁必须是同一个客户端,客户端自己不能把别人加的锁给解了。

本文就使用的是Redis的setnx实现,如果Redis是多机版的可以去了解下Radssion,封装的就特别的好,也是官方推荐的

代码

1. 加依赖

引入Spring Boot和Redis整合的快速使用依赖

  <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
  </dependency>

2. 加配置

application.properties中加入Redis连接相关配置

spring.redis.host=xxx
spring.redis.port=6379
spring.redis.database=0
spring.redis.password=xxx
spring.redis.timeout=10000

# 设置jedis连接池
spring.redis.jedis.pool.max-active=50
spring.redis.jedis.pool.min-idle=20

3. 重写Redis的序列化规则

默认使用的JDK的序列化,不自己设置一下Redis中的数据是看不懂的

/**
 * @author Chkl
 * @create 2020/6/7
 * @since 1.0.0
 */
@Component
public class RedisConfig {
   
    /**
     * 改造RedisTemplate,重写序列化规则,避免存入序列化内容看不懂
     * @param connectionFactory
     * @return
     */
    @Bean
    public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
   
        RedisTemplate redisTemplate 
  • 4
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值