Redis系列---【分布式锁解决方案之Redisson】

打印 上一主题 下一主题

主题 518|帖子 518|积分 1554

1.分布式锁解决方案

常用的一般有Zookeeper,Redisson,数据库。

  • Zookeeper方案使用的是CP(保证了一致性和分区容错性,牺牲了一点可用性),适合流量请求不是很大,一致性要求较高的业务场景。
  • Redisson方案使用的是AP(保证了可用性和分区容错性,牺牲了一点一致性),适合高并发场景,对一致性要求不是很高的业务场景。一致性可以人工通过脚本弥补,也可以通过redlock去解决。
2.Redission分布式锁解决方案


  • 在pom中引入Redisson坐标
  1. <dependency>
  2.   <groupId>org.redisson</groupId>
  3.   <artifactId>redisson</artifactId>
  4.   <version>3.17.3</version>
  5. </dependency>
复制代码

  • 在配置类或启动类中注入Redisson对象
  1.     @Bean
  2.     public Redisson redisson(){
  3.         //redis为单机模式
  4.         Config config = new Config();
  5.         config.useSingleServer().setAddress("redis://localhost:6379").setPassword("123456");
  6.         return (Redisson) Redisson.create(config);
  7.     }
复制代码

  • 业务代码编写
  1. package com.fast.controller;
  2. import org.redisson.Redisson;
  3. import org.redisson.api.RLock;
  4. import org.springframework.beans.factory.annotation.Autowired;
  5. import org.springframework.data.redis.core.RedisTemplate;
  6. import org.springframework.web.bind.annotation.GetMapping;
  7. import org.springframework.web.bind.annotation.RequestMapping;
  8. import org.springframework.web.bind.annotation.RestController;
  9. import java.util.UUID;
  10. import java.util.concurrent.TimeUnit;
  11. /**
  12. * @author hjw
  13. * @since 2022年06月23日 11:42:00
  14. */
  15. @RestController
  16. @RequestMapping("stock")
  17. public class StockController {
  18.     @Autowired
  19.     private RedisTemplate redisTemplate;
  20.     @Autowired
  21.     private Redisson redisson;
  22.     @GetMapping("init")
  23.     public String init() {
  24.         redisTemplate.opsForValue().set("stock", 100);
  25.         return "库存新增成功";
  26.     }
  27.     @GetMapping("sale")
  28.     public String saleGoods() {
  29.         //这样写,单机部署不会有问题,多节点就会出问题,因为synchronized只能基于jvm做加锁,多个节点属于多个jvm了
  30.         synchronized (this) {
  31.             int stock = (int) redisTemplate.opsForValue().get("stock");
  32.             if (stock > 0) {
  33.                 int i = stock - 1;
  34.                 redisTemplate.opsForValue().set("stock", i);
  35.                 System.out.println("库存剩余:" + i);
  36.             } else {
  37.                 System.out.println("库存数量不足");
  38.                 return "库存数量不足";
  39.             }
  40.         }
  41.         return "库存扣减成功";
  42.     }
  43.     @GetMapping("saleImprove")
  44.     public String saleImprove() {
  45.         //使用redisson实现分布式锁
  46.         String lockKey = "product_001";
  47. //        String clientId = UUID.randomUUID().toString();
  48.         **RLock redissonLock = redisson.getLock(lockKey);**
  49.         try {
  50.             //使用redisTemplate还需要手写子线程每隔30s*1/3=10s,根据clientId给每个线程的lockKey进行续期,防止lockKey失效后,业务未执行完,结果下个线程进来了
  51. //            Boolean result = redisTemplate.opsForValue().setIfAbsent(lockKey,clientId,30, TimeUnit.SECONDS);
  52. //            if (!result){
  53. //                return "error_code";
  54. //            }
  55.             **redissonLock.lock();**//相当于setIfAbsent(lockKey,clientId,30, TimeUnit.SECONDS);
  56.             int stock = (int) redisTemplate.opsForValue().get("stock");
  57.             if (stock > 0) {
  58.                 int i = stock - 1;
  59.                 redisTemplate.opsForValue().set("stock", i);
  60.                 System.out.println("库存剩余:" + i);
  61.             } else {
  62.                 System.out.println("库存数量不足");
  63.                 return "库存数量不足";
  64.             }
  65.         }finally {
  66.             **redissonLock.unlock();**
  67. //            if (clientId.equals(redisTemplate.opsForValue().get(lockKey))){
  68. //                redisTemplate.delete(lockKey);
  69. //            }
  70.         }
  71.         return "库存扣减成功";
  72.     }
  73. }
复制代码

  • 若想进一步优化,则可以采用1.8中ConcurrentHashMap的设计思想,分段加锁
    进一步把库存1000,进行拆分成stock1-200,stock2-200,stock3-200,stock4-200,stock5-200,然后再进行分配,第一个请求进来访问stock1,进行库存加减,第二个访问stock2进行库存加减...依此类推,分别加锁解锁,就可以大大提高并发量。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

天津储鑫盛钢材现货供应商

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表