zoukankan      html  css  js  c++  java
  • Redisson基本用法

    原文地址:https://www.cnblogs.com/cjsblog/p/11273205.html

    Redisson基本用法

     

    1.  Redisson

    Redisson是Redis官方推荐的Java版的Redis客户端。它提供的功能非常多,也非常强大,此处我们只用它的分布式锁功能。

    https://github.com/redisson/redisson

    1.1.  基本用法

    1 <dependency>
    2    <groupId>org.redisson</groupId>
    3    <artifactId>redisson</artifactId>
    4    <version>3.11.1</version>
    5 </dependency>

    1.2.  Distributed locks and synchronizers

    RedissonClient中提供了好多种锁,还有其它很多实用的方法

    1.2.1.  Lock

    默认,非公平锁

    最简洁的一种方法

    指定超时时间 

    异步

    1.2.2  Fair Lock 

    1.2.3  MultiLock

    1.2.4  RedLock

    1.3.  示例

    pom.xml

     1 <?xml version="1.0" encoding="UTF-8"?>
     2 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     3          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     4     <modelVersion>4.0.0</modelVersion>
     5     <parent>
     6         <groupId>org.springframework.boot</groupId>
     7         <artifactId>spring-boot-starter-parent</artifactId>
     8         <version>2.1.6.RELEASE</version>
     9         <relativePath/> <!-- lookup parent from repository -->
    10     </parent>
    11     <groupId>com.cjs.example</groupId>
    12     <artifactId>cjs-redisson-example</artifactId>
    13     <version>0.0.1-SNAPSHOT</version>
    14     <name>cjs-redisson-example</name>
    15 
    16     <properties>
    17         <java.version>1.8</java.version>
    18     </properties>
    19 
    20     <dependencies>
    21         <dependency>
    22             <groupId>org.springframework.boot</groupId>
    23             <artifactId>spring-boot-starter-data-jpa</artifactId>
    24         </dependency>
    25         <dependency>
    26             <groupId>org.springframework.boot</groupId>
    27             <artifactId>spring-boot-starter-data-redis</artifactId>
    28         </dependency>
    29         <dependency>
    30             <groupId>org.springframework.boot</groupId>
    31             <artifactId>spring-boot-starter-web</artifactId>
    32         </dependency>
    33 
    34         <!-- https://github.com/redisson/redisson#quick-start -->
    35         <dependency>
    36             <groupId>org.redisson</groupId>
    37             <artifactId>redisson</artifactId>
    38             <version>3.11.1</version>
    39         </dependency>
    40 
    41 
    42         <dependency>
    43             <groupId>org.apache.commons</groupId>
    44             <artifactId>commons-lang3</artifactId>
    45             <version>3.9</version>
    46         </dependency>
    47         <dependency>
    48             <groupId>com.alibaba</groupId>
    49             <artifactId>fastjson</artifactId>
    50             <version>1.2.58</version>
    51         </dependency>
    52         <dependency>
    53             <groupId>org.apache.commons</groupId>
    54             <artifactId>commons-pool2</artifactId>
    55             <version>2.6.2</version>
    56         </dependency>
    57 
    58         <dependency>
    59             <groupId>mysql</groupId>
    60             <artifactId>mysql-connector-java</artifactId>
    61             <scope>runtime</scope>
    62         </dependency>
    63         <dependency>
    64             <groupId>org.projectlombok</groupId>
    65             <artifactId>lombok</artifactId>
    66             <optional>true</optional>
    67         </dependency>
    68     </dependencies>
    69 
    70     <build>
    71         <plugins>
    72             <plugin>
    73                 <groupId>org.springframework.boot</groupId>
    74                 <artifactId>spring-boot-maven-plugin</artifactId>
    75             </plugin>
    76         </plugins>
    77     </build>
    78 
    79 </project>
    

    application.yml

     1 server:
     2   port: 8080
     3 spring:
     4   application:
     5     name: cjs-redisson-example
     6   redis:
     7     cluster:
     8       nodes: 10.0.29.30:6379, 10.0.29.95:6379, 10.0.29.205:6379
     9     lettuce:
    10       pool:
    11         min-idle: 0
    12         max-idle: 8
    13         max-active: 20
    14   datasource:
    15     url: jdbc:mysql://127.0.0.1:3306/test
    16     username: root
    17     password: 123456
    18     driver-class-name: com.mysql.cj.jdbc.Driver
    19     type: com.zaxxer.hikari.HikariDataSource
    

    RedissonConfig.java

     1 package com.cjs.example.lock.config;
     2 
     3 import org.redisson.Redisson;
     4 import org.redisson.api.RedissonClient;
     5 import org.redisson.config.Config;
     6 import org.springframework.context.annotation.Bean;
     7 import org.springframework.context.annotation.Configuration;
     8 
     9 /**
    10  * @author ChengJianSheng
    11  * @date 2019-07-26
    12  */
    13 @Configuration
    14 public class RedissonConfig {
    15 
    16     @Bean
    17     public RedissonClient redissonClient() {
    18         Config config = new Config();
    19         config.useClusterServers()
    20                 .setScanInterval(2000)
    21                 .addNodeAddress("redis://10.0.29.30:6379", "redis://10.0.29.95:6379")
    22                 .addNodeAddress("redis://10.0.29.205:6379");
    23 
    24         RedissonClient redisson = Redisson.create(config);
    25 
    26         return redisson;
    27     }
    28 
    29 }
    

    CourseServiceImpl.java 

      1 package com.cjs.example.lock.service.impl;
      2 
      3 import com.alibaba.fastjson.JSON;
      4 import com.cjs.example.lock.constant.RedisKeyPrefixConstant;
      5 import com.cjs.example.lock.model.CourseModel;
      6 import com.cjs.example.lock.model.CourseRecordModel;
      7 import com.cjs.example.lock.repository.CourseRecordRepository;
      8 import com.cjs.example.lock.repository.CourseRepository;
      9 import com.cjs.example.lock.service.CourseService;
     10 import lombok.extern.slf4j.Slf4j;
     11 import org.apache.commons.lang3.StringUtils;
     12 import org.redisson.api.RLock;
     13 import org.redisson.api.RedissonClient;
     14 import org.springframework.beans.factory.annotation.Autowired;
     15 import org.springframework.data.redis.core.HashOperations;
     16 import org.springframework.data.redis.core.StringRedisTemplate;
     17 import org.springframework.stereotype.Service;
     18 
     19 import java.util.concurrent.TimeUnit;
     20 
     21 /**
     22  * @author ChengJianSheng
     23  * @date 2019-07-26
     24  */
     25 @Slf4j
     26 @Service
     27 public class CourseServiceImpl implements CourseService {
     28 
     29     @Autowired
     30     private CourseRepository courseRepository;
     31     @Autowired
     32     private CourseRecordRepository courseRecordRepository;
     33     @Autowired
     34     private StringRedisTemplate stringRedisTemplate;
     35     @Autowired
     36     private RedissonClient redissonClient;
     37 
     38     @Override
     39     public CourseModel getById(Integer courseId) {
     40 
     41         CourseModel courseModel = null;
     42 
     43         HashOperations<String, String, String> hashOperations = stringRedisTemplate.opsForHash();
     44 
     45         String value = hashOperations.get(RedisKeyPrefixConstant.COURSE, String.valueOf(courseId));
     46 
     47         if (StringUtils.isBlank(value)) {
     48             String lockKey = RedisKeyPrefixConstant.LOCK_COURSE + courseId;
     49             RLock lock = redissonClient.getLock(lockKey);
     50             try {
     51                 boolean res = lock.tryLock(10, TimeUnit.SECONDS);
     52                 if (res) {
     53                     value = hashOperations.get(RedisKeyPrefixConstant.COURSE, String.valueOf(courseId));
     54                     if (StringUtils.isBlank(value)) {
     55                         log.info("从数据库中读取");
     56                         courseModel = courseRepository.findById(courseId).orElse(null);
     57                         hashOperations.put(RedisKeyPrefixConstant.COURSE, String.valueOf(courseId), JSON.toJSONString(courseModel));
     58                     }
     59                 }
     60             } catch (InterruptedException e) {
     61                 e.printStackTrace();
     62             } finally {
     63                 lock.unlock();
     64             }
     65         } else {
     66             log.info("从缓存中读取");
     67             courseModel = JSON.parseObject(value, CourseModel.class);
     68         }
     69 
     70         return courseModel;
     71     }
     72 
     73     @Override
     74     public void upload(Integer userId, Integer courseId, Integer studyProcess) {
     75 
     76         HashOperations<String, String, String> hashOperations = stringRedisTemplate.opsForHash();
     77 
     78         String cacheKey = RedisKeyPrefixConstant.COURSE_PROGRESS + ":" + userId;
     79         String cacheValue = hashOperations.get(cacheKey, String.valueOf(courseId));
     80         if (StringUtils.isNotBlank(cacheValue) && studyProcess <= Integer.valueOf(cacheValue)) {
     81             return;
     82         }
     83 
     84         String lockKey = "upload:" + userId + ":" + courseId;
     85 
     86         RLock lock = redissonClient.getLock(lockKey);
     87 
     88         try {
     89             lock.lock(10, TimeUnit.SECONDS);
     90 
     91             cacheValue = hashOperations.get(cacheKey, String.valueOf(courseId));
     92             if (StringUtils.isBlank(cacheValue) || studyProcess > Integer.valueOf(cacheValue)) {
     93                 CourseRecordModel model = new CourseRecordModel();
     94                 model.setUserId(userId);
     95                 model.setCourseId(courseId);
     96                 model.setStudyProcess(studyProcess);
     97                 courseRecordRepository.save(model);
     98                 hashOperations.put(cacheKey, String.valueOf(courseId), String.valueOf(studyProcess));
     99             }
    100 
    101         } catch (Exception ex) {
    102             log.error("获取所超时!", ex);
    103         } finally {
    104             lock.unlock();
    105         }
    106 
    107     }
    108 }
    

    StockServiceImpl.java

     1 package com.cjs.example.lock.service.impl;
     2 
     3 import com.cjs.example.lock.constant.RedisKeyPrefixConstant;
     4 import com.cjs.example.lock.service.StockService;
     5 import org.apache.commons.lang3.StringUtils;
     6 import org.springframework.beans.factory.annotation.Autowired;
     7 import org.springframework.data.redis.core.HashOperations;
     8 import org.springframework.data.redis.core.StringRedisTemplate;
     9 import org.springframework.stereotype.Service;
    10 
    11 /**
    12  * @author ChengJianSheng
    13  * @date 2019-07-26
    14  */
    15 @Service
    16 public class StockServiceImpl implements StockService {
    17 
    18     @Autowired
    19     private StringRedisTemplate stringRedisTemplate;
    20 
    21     @Override
    22     public int getByProduct(Integer productId) {
    23         HashOperations<String, String, String> hashOperations = stringRedisTemplate.opsForHash();
    24         String value = hashOperations.get(RedisKeyPrefixConstant.STOCK, String.valueOf(productId));
    25         if (StringUtils.isBlank(value)) {
    26             return 0;
    27         }
    28         return Integer.valueOf(value);
    29     }
    30 
    31     @Override
    32     public boolean decrease(Integer productId) {
    33         int stock = getByProduct(productId);
    34         if (stock <= 0) {
    35             return false;
    36         }
    37         HashOperations<String, String, String> hashOperations = stringRedisTemplate.opsForHash();
    38         hashOperations.put(RedisKeyPrefixConstant.STOCK, String.valueOf(productId), String.valueOf(stock - 1));
    39         return true;
    40     }
    41 }
    

    OrderServiceImpl.java

     1 package com.cjs.example.lock.service.impl;
     2 
     3 import com.cjs.example.lock.model.OrderModel;
     4 import com.cjs.example.lock.repository.OrderRepository;
     5 import com.cjs.example.lock.service.OrderService;
     6 import com.cjs.example.lock.service.StockService;
     7 import lombok.extern.slf4j.Slf4j;
     8 import org.redisson.api.RLock;
     9 import org.redisson.api.RedissonClient;
    10 import org.springframework.beans.factory.annotation.Autowired;
    11 import org.springframework.stereotype.Service;
    12 
    13 import java.util.Date;
    14 import java.util.UUID;
    15 import java.util.concurrent.TimeUnit;
    16 
    17 /**
    18  * @author ChengJianSheng
    19  * @date 2019-07-30
    20  */
    21 @Slf4j
    22 @Service
    23 public class OrderServiceImpl implements OrderService {
    24 
    25     @Autowired
    26     private StockService stockService;
    27     @Autowired
    28     private OrderRepository orderRepository;
    29     @Autowired
    30     private RedissonClient redissonClient;
    31 
    32     /**
    33      * 乐观锁
    34      */
    35     @Override
    36     public String save(Integer userId, Integer productId) {
    37         int stock = stockService.getByProduct(productId);
    38         log.info("剩余库存:{}", stock);
    39         if (stock <= 0) {
    40             return null;
    41         }
    42 
    43         //  如果不加锁,必然超卖
    44 
    45         RLock lock = redissonClient.getLock("stock:" + productId);
    46 
    47         try {
    48             lock.lock(10, TimeUnit.SECONDS);
    49 
    50             String orderNo = UUID.randomUUID().toString().replace("-", "").toUpperCase();
    51 
    52             if (stockService.decrease(productId)) {
    53 
    54                 OrderModel orderModel = new OrderModel();
    55                 orderModel.setUserId(userId);
    56                 orderModel.setProductId(productId);
    57                 orderModel.setOrderNo(orderNo);
    58                 Date now = new Date();
    59                 orderModel.setCreateTime(now);
    60                 orderModel.setUpdateTime(now);
    61                 orderRepository.save(orderModel);
    62 
    63                 return orderNo;
    64             }
    65 
    66         } catch (Exception ex) {
    67             log.error("下单失败", ex);
    68         } finally {
    69             lock.unlock();
    70         }
    71 
    72         return null;
    73     }
    74 
    75 }
    

    OrderModel.java

     1 package com.cjs.example.lock.model;
     2 
     3 import lombok.Data;
     4 
     5 import javax.persistence.*;
     6 import java.io.Serializable;
     7 import java.util.Date;
     8 
     9 /**
    10  * @author ChengJianSheng
    11  * @date 2019-07-30
    12  */
    13 @Data
    14 @Entity
    15 @Table(name = "t_order")
    16 public class OrderModel implements Serializable {
    17 
    18     @Id
    19     @GeneratedValue(strategy = GenerationType.IDENTITY)
    20     private Integer id;
    21 
    22     @Column(name = "order_no")
    23     private String orderNo;
    24 
    25     @Column(name = "product_id")
    26     private Integer productId;
    27 
    28     @Column(name = "user_id")
    29     private Integer userId;
    30 
    31     @Column(name = "create_time")
    32     private Date createTime;
    33 
    34     @Column(name = "update_time")
    35     private Date updateTime;
    36 } 

    数据库脚本.sql

     1 SET NAMES utf8mb4;
     2 SET FOREIGN_KEY_CHECKS = 0;
     3 
     4 -- ----------------------------
     5 -- Table structure for t_course
     6 -- ----------------------------
     7 DROP TABLE IF EXISTS `t_course`;
     8 CREATE TABLE `t_course` (
     9   `id` int(11) NOT NULL AUTO_INCREMENT,
    10   `course_name` varchar(64) NOT NULL,
    11   `course_type` tinyint(4) NOT NULL DEFAULT '1',
    12   `start_time` datetime NOT NULL,
    13   PRIMARY KEY (`id`)
    14 ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4;
    15 
    16 -- ----------------------------
    17 -- Table structure for t_order
    18 -- ----------------------------
    19 DROP TABLE IF EXISTS `t_order`;
    20 CREATE TABLE `t_order` (
    21   `id` int(11) NOT NULL AUTO_INCREMENT,
    22   `order_no` varchar(256) CHARACTER SET latin1 NOT NULL,
    23   `user_id` int(11) NOT NULL,
    24   `product_id` int(11) NOT NULL,
    25   `create_time` datetime NOT NULL,
    26   `update_time` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
    27   PRIMARY KEY (`id`)
    28 ) ENGINE=InnoDB AUTO_INCREMENT=109 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
    29 
    30 -- ----------------------------
    31 -- Table structure for t_user_course_record
    32 -- ----------------------------
    33 DROP TABLE IF EXISTS `t_user_course_record`;
    34 CREATE TABLE `t_user_course_record` (
    35   `id` int(11) NOT NULL AUTO_INCREMENT,
    36   `user_id` int(11) NOT NULL,
    37   `course_id` int(11) NOT NULL,
    38   `study_process` int(11) NOT NULL,
    39   PRIMARY KEY (`id`)
    40 ) ENGINE=InnoDB AUTO_INCREMENT=103 DEFAULT CHARSET=utf8mb4;
    41 
    42 SET FOREIGN_KEY_CHECKS = 1; 

    1.4  工程结构

    https://github.com/chengjiansheng/cjs-redisson-example 

    1.5  Redis集群创建

    1.6  测试

    测试/course/upload

    测试/order/create

    2.  Spring Integration

    用法与Redisson类似

    1 <dependency>
    2     <groupId>org.springframework.boot</groupId>
    3     <artifactId>spring-boot-starter-integration</artifactId>
    4 </dependency>
    5 <dependency>
    6     <groupId>org.springframework.integration</groupId>
    7     <artifactId>spring-integration-redis</artifactId>
    8 </dependency>
     1 package com.kaishustory.base.conf;
     2 
     3 import org.springframework.context.annotation.Bean;
     4 import org.springframework.context.annotation.Configuration;
     5 import org.springframework.data.redis.connection.RedisConnectionFactory;
     6 import org.springframework.integration.redis.util.RedisLockRegistry;
     7 
     8 /**
     9  * @author ChengJianSheng
    10  * @date 2019-07-30
    11  */
    12 @Configuration
    13 public class RedisLockConfig {
    14 
    15     @Bean
    16     public RedisLockRegistry redisLockRegistry(RedisConnectionFactory redisConnectionFactory) {
    17         return new RedisLockRegistry(redisConnectionFactory, "asdf")
    18     }
    19 
    20 }
    
     1 @Autowired
     2 private RedisLockRegistry redisLockRegistry;
     3 
     4 public void save(Integer userId) {
     5 
     6     String lockKey = "order:" + userId;
     7 
     8     Lock lock = redisLockRegistry.obtain(lockKey);
     9     try {
    10         lock.lock();
    11 
    12         //todo
    13 
    14     } finally {
    15         lock.unlock();
    16     }
    17 
    18 }
    

    3.  其它

    https://github.com/redisson/redisson/wiki/8.-Distributed-locks-and-synchronizers 

    https://www.cnblogs.com/cjsblog/p/9831423.html 

  • 相关阅读:
    bzoj2728
    bzoj4574
    loj2554
    bzoj1068
    bzoj2554
    Exception in thread "main" java.lang.AbstractMethodError
    java方法重载,java方法练习题
    java面向对象
    java编辑器 IntelliJ IDEA 安装——放弃过程;eclipse,Notepad++
    java二维数组
  • 原文地址:https://www.cnblogs.com/eyesfree/p/13067132.html
Copyright © 2011-2022 走看看