分布式锁【分布式锁概述、业务介绍、创建SpringBoot项目】(一)-全面详解(学习总结---从入门到深化)

简介: 分布式锁【分布式锁概述、业务介绍、创建SpringBoot项目】(一)-全面详解(学习总结---从入门到深化)

分布式锁概述



为什么需要分布式锁


在单机部署的系统中,使用线程锁来解决高并发的问题,多线程访问共享变量的问题达到数据一致性,如使用synchornized、 ReentrantLock等。


但是在后端集群部署的系统中,程序在不同的JVM虚拟机中运行, 且因为synchronized或ReentrantLock都只能保证同一个JVM进程 中保证有效,所以这时就需要使用分布式锁了。


什么是分布式锁


分布式锁其实就是,控制分布式系统不同进程共同访问共享资源的 一种锁的实现。如果不同的系统或同一个系统的不同主机之间共享 了某个临界资源,往往需要互斥来防止彼此干扰,以保证一致性。


分布式锁的特点


分布式锁问题_业务介绍


案列介绍


技术选型


创建表


创建订单表

CREATE TABLE `t_order`  (
  `id` varchar(255) CHARACTER SET utf8 COLLATE
utf8_general_ci NOT NULL,
  `order_status` int(1) NULL DEFAULT NULL
COMMENT '订单状态 1 待支付 2已支付',
  `receiver_name` varchar(255) CHARACTER SET
utf8 COLLATE utf8_general_ci NULL DEFAULT NULL
COMMENT '收货人名字',
  `receiver_mobile` varchar(255) CHARACTER SET
utf8 COLLATE utf8_general_ci NULL DEFAULT NULL
COMMENT '收货人手机',
  `order_amount` decimal(10, 2) NULL DEFAULT
NULL COMMENT '订单价格',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE
= utf8_general_ci ROW_FORMAT = Dynamic;


创建商品表

CREATE TABLE `product`  (
  `id` int(11) NOT NULL,
  `product_name` varchar(255) CHARACTER SET
utf8 COLLATE utf8_general_ci NULL DEFAULT NULL
COMMENT '商品名字',
  `price` decimal(10, 2) NULL DEFAULT NULL
COMMENT '商品价格',
  `count` bigint(50) UNSIGNED NULL DEFAULT NULL
COMMENT '库存',
  `product_desc` varchar(255) CHARACTER SET
utf8 COLLATE utf8_general_ci NULL DEFAULT NULL
COMMENT '商品描述',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE
= utf8_general_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of product
-- ----------------------------
INSERT INTO `product` VALUES (1001,'拯救者',100.00, 5,'好用实惠', 1);


创建订单商品关联表

CREATE TABLE `order_item`  (
  `id` varchar(255) CHARACTER SET utf8 COLLATE
utf8_general_ci NOT NULL,
  `order_id` varchar(36) CHARACTER SET utf8
COLLATE utf8_general_ci NULL DEFAULT NULL
COMMENT '订单ID',
  `produce_id` int(11) NULL DEFAULT NULL
COMMENT '商品ID',
  `purchase_price` decimal(10, 2) NULL DEFAULT
NULL COMMENT '购买价格',
  `purchase_num` int(11) NULL DEFAULT NULL
COMMENT '购买数量',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE
= utf8_general_ci ROW_FORMAT = Dynamic;


分布式锁问题_创建SpringBoot项目



引入依赖

   <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.4.2</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-generator</artifactId>
            <version>3.5.2</version>
        </dependency>
        <!-- 模板引擎 -->
        <dependency>
            <groupId>org.apache.velocity</groupId>
            <artifactId>velocity-engine-core</artifactId>
            <version>2.0</version>
        </dependency>
    </dependencies>


修改配置文件

spring:
 application:
   name: lock
 datasource:
   url: jdbc:mysql://192.168.66.100:3306/distribute?serverTimezone=UTC
   username: root
   password01: 123456
   driver-class-name: com.mysql.cj.jdbc.Driver
server:
 port: 9091


编写主启动类

@Slf4j
@MapperScan("com.tong.lock.mapper")
@SpringBootApplication
public class LockdemoApplication {
    public static void main(String[] args) {
       SpringApplication.run(LockdemoApplication.class, args);
        log.info("************** 分布式锁 **************");
   }
}


代码生成


使用Mybaits Plus生成订单表、商品表、订单商品关联表的相关代码。

package com.tong.lock.utils;
import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import java.util.Arrays;
import java.util.List;
public class CodeGenerator {
 public static void main(String[] args) {
      FastAutoGenerator.create("jdbc:mysql://192.168.66.100:3306/distribute", "root", "123456")
               .globalConfig(builder -> {
                    builder.author("itbaizhan")// 设置作者
                           .commentDate("MMdd") // 注释日期格式
                           .outputDir(System.getProperty("user.dir")+ "/src/main/java/") // 指定输出目录
                           .fileOverride(); //覆盖文件
               })
                // 包配置
               .packageConfig(builder -> {
                  builder.parent("com.itbaizhan.lock") // 包名前缀
                           .entity("entity")//实体类包名
                           .mapper("mapper")//mapper接口包名
                           .service("service"); //service包名
               })
               .strategyConfig(builder -> {
                    List<String> strings = Arrays.asList("t_order");
                    // 设置需要生成的表名
                    builder.addInclude(strings)
                            // 开始实体类配置
                           .entityBuilder()
                            // 开启lombok模型
                           .enableLombok()
                            //表名下划线转驼峰
                           .naming(NamingStrategy.underline_to_camel)
                            //列名下划线转驼峰
                           .columnNaming(NamingStrategy.underline_to_camel);
               })
               .execute();
   }
}


编写创建订单接口

public interface ITOrderService extends IService<TOrder> {
    /**
     * 创建订单
     * @return
     */
    String createOrder(Integer productId,Integer count);
}


实现创建订单接口

package com.tong.lock.service.impl;
import com.tong.lock.entity.OrderItem;
import com.tong.lock.entity.Product;
import com.tong.lock.entity.TOrder;
import com.tong.lock.mapper.OrderItemMapper;
import com.tong.lock.mapper.ProductMapper;
import com.tong.lock.mapper.TOrderMapper;
import com.tong.lock.service.ITOrderService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.concurrent.locks.ReentrantLock;
/**
* <p>
* 服务实现类
* </p>
*
* @author tong
* @since 05-25
*/
@Service
public class TOrderServiceImpl extends ServiceImpl<TOrderMapper, TOrder> implements ITOrderService {
    @Resource
    OrderItemMapper orderItemMapper;
    @Resource
    ProductMapper productMapper;    
    /**
     * 创建订单
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public  String createOrder(Integer productId,Integer count) {
  // 1、根据商品id查询商品信息
            Product product = productMapper.selectById(productId);
            // 2、判断商品是否存在
            if (product == null){
                throw new RuntimeException("购买商品不存在:" + productId + "不存在");
           }
            // 3、校验库存
            if( count > product.getCount() ){
                throw   new RuntimeException("商品" + productId + "仅剩" + product.getCount() + "件,无法购买");
           }
            // 4、计算库存
            Integer leftCount = product.getCount() - count;
            // 5、更新库存
            product.setCount(leftCount);
            productMapper.updateById(product);
            // 6、 创建订单
            TOrder order = new TOrder();
            order.setOrderStatus(1);//待处理
            order.setReceiverName("张三");
            order.setReceiverMobile("18587781068");
            order.setOrderAmount(product.getPrice().multiply(new BigDecimal(count)));//订单价格
            baseMapper.insert(order);
            // 7、 创建订单和商品关系数据
            OrderItem orderItem = new OrderItem();
            orderItem.setOrderId(order.getId());
            orderItem.setProduceId(product.getId());
            orderItem.setPurchasePrice(product.getPrice());
            orderItem.setPurchaseNum(count);
            orderItemMapper.insert(orderItem);
            return order.getId();
   }
}


编写创建订单api接口

@RestController
@RequestMapping("/order")
public class OrderController {
    @Autowired
    private ITOrderService iOrderService;
    /**
     * 创建订单
     * @param productId 商品id
     * @param count 商品数量
     * @return
     */
    @PostMapping("/create")
    public String createOrder(Integer productId,Integer count){
      return iOrderService.createOrder(productId,count);
   }
}


测试订单

相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。 &nbsp; 相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情:&nbsp;https://www.aliyun.com/product/rds/mysql&nbsp;
目录
相关文章
|
10月前
|
NoSQL Java 调度
分布式锁与分布式锁使用 Redis 和 Spring Boot 进行调度锁(不带 ShedLock)
分布式锁是分布式系统中用于同步多节点访问共享资源的机制,防止并发操作带来的冲突。本文介绍了基于Spring Boot和Redis实现分布式锁的技术方案,涵盖锁的获取与释放、Redis配置、服务调度及多实例运行等内容,通过Docker Compose搭建环境,验证了锁的有效性与互斥特性。
876 0
分布式锁与分布式锁使用 Redis 和 Spring Boot 进行调度锁(不带 ShedLock)
|
10月前
|
存储 算法 安全
“卧槽,系统又崩了!”——别慌,这也许是你看过最通俗易懂的分布式入门
本文深入解析分布式系统核心机制:数据分片与冗余副本实现扩展与高可用,租约、多数派及Gossip协议保障一致性与容错。探讨节点故障、网络延迟等挑战,揭示CFT/BFT容错原理,剖析规模与性能关系,为构建可靠分布式系统提供理论支撑。
468 2
|
JSON 分布式计算 大数据
springboot项目集成大数据第三方dolphinscheduler调度器
springboot项目集成大数据第三方dolphinscheduler调度器
778 3
|
Java 关系型数据库 数据库连接
Spring Boot项目集成MyBatis Plus操作PostgreSQL全解析
集成 Spring Boot、PostgreSQL 和 MyBatis Plus 的步骤与 MyBatis 类似,只不过在 MyBatis Plus 中提供了更多的便利功能,如自动生成 SQL、分页查询、Wrapper 查询等。
1077 2
|
Java 关系型数据库 MySQL
springboot项目集成dolphinscheduler调度器 实现datax数据同步任务
springboot项目集成dolphinscheduler调度器 实现datax数据同步任务
1089 2
|
分布式计算 Java 大数据
springboot项目集成dolphinscheduler调度器 可拖拽spark任务管理
springboot项目集成dolphinscheduler调度器 可拖拽spark任务管理
593 2
|
12月前
|
Java 测试技术 Spring
简单学Spring Boot | 博客项目的测试
本内容介绍了基于Spring Boot的博客项目测试实践,重点在于通过测试驱动开发(TDD)优化服务层代码,提升代码质量和功能可靠性。案例详细展示了如何为PostService类编写测试用例、运行测试并根据反馈优化功能代码,包括两次优化过程。通过TDD流程,确保每项功能经过严格验证,增强代码可维护性与系统稳定性。
429 0
|
12月前
|
存储 Java 数据库连接
简单学Spring Boot | 博客项目的三层架构重构
本案例通过采用三层架构(数据访问层、业务逻辑层、表现层)重构项目,解决了集中式开发导致的代码臃肿问题。各层职责清晰,结合依赖注入实现解耦,提升了系统的可维护性、可测试性和可扩展性,为后续接入真实数据库奠定基础。
866 0
|
分布式计算 大数据 Java
springboot项目集成大数据第三方dolphinscheduler调度器 执行/停止任务
springboot项目集成大数据第三方dolphinscheduler调度器 执行/停止任务
345 0
|
负载均衡 Java Spring
SpringBoot学习笔记-14:第十四章-SpringBoot 与分布式(2)
SpringBoot学习笔记-14:第十四章-SpringBoot 与分布式
236 0