前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >还不会用乐观锁吗?Spring Cloud Alibaba组合Mybatis-Plus真香

还不会用乐观锁吗?Spring Cloud Alibaba组合Mybatis-Plus真香

作者头像
35岁程序员那些事
发布2022-09-23 17:49:02
1860
发布2022-09-23 17:49:02
举报
文章被收录于专栏:35岁程序员那些事

当我们想要在业务中引入“乐观锁”时,应该要思考清楚它的概念,为了更加形象的理解“乐观锁”,我们可以先看一下认识下悲观锁。

什么是悲观锁

顾名思义,悲观锁是基于一种悲观的态度来防止一切数据冲突,它是以一种预防的姿态,并在修改数据之前把数据锁住,然后再对数据进行读写。在它释放锁之前任何线程都不能对其数据进行操作,直到持有锁的线程释放锁之后,其它线程才能通过竞争去获取到悲观锁,自动对数据进行加锁,然后才可以对数据进行操作;

很多技术类的文章中,也将“悲观锁”叫做“互斥锁”或者“排它锁”。

悲观锁的特点:可以完全保证数据的独占性和正确性,因为每次请求都会先对数据进行加锁, 然后进行数据操作,最后再解锁,而加锁释放锁的过程会造成消耗,所以性能不高;

在Java中最常见的悲观锁就是synchronized和ReentrantLock,前者是隐式加锁,后者是显式加锁。

代码语言:javascript
复制
Object lock=new Object();
    public void test1(){
    synchronized (lock){
        //添加需要加锁的逻辑
    }

ReentrantLock reentrantLock=new ReentrantLock();
    public void test2(){
        reentrantLock.lock();
        try {
            //添加需要加锁的逻辑
        }catch (Exception e){
        }finally{
            reentrantLock.unlock();
        }
    }

在数据库中,比如MySQL,我们可以通过添加“for update”加一个行锁,当然也可以叫“排它锁”。

代码语言:javascript
复制
###添加一个悲观锁
SELECT * FROM user WHERE id=3 FOR UPDATE;

什么是乐观锁

顾名思义,乐观锁是对于数据冲突保持一种乐观态度,操作数据时不会对操作的数据进行加锁(这使得多个线程可以并行的对数据进行操作),只有到数据提交的时候才通过一种机制来验证数据是否存在冲突(一般实现方式是通过加版本号然后进行版本号的对比方式实现);

特点:乐观锁是一种并发类型的锁,其本身不对数据进行加锁而是通过业务实现锁的功能。那么不对数据进行加锁就意味着允许多个请求同时访问数据,同时也省掉了对数据加锁和解锁的过程,这种方式因为节省了悲观锁加锁的操作,所以可以一定程度的的提升性能。不过在并发非常高的情况下,会导致大量的请求冲突,冲突导致大部分操作无功而返而浪费资源,所以在高并发的场景下,乐观锁的性能反而不如悲观锁。

在Java中,我们也可以将读写锁ReentrantReadWriteLock当作乐观锁的一种变种,当然最经典的乐观锁就是Java中的CAS,Java的JUC中用到乐观锁的地方,几乎都是用CAS实现的。

在MySQL中,最常见的乐观锁就是“版本号”,并在需要加乐观锁的表中添加一个字段用来记录版本号,比如最常见的就是“version字段”。

Spring Cloud Alibaba组合Mybatis-Plus真香

一般情况下,业务服务中使用的乐观锁最多的业务场景就是数据库,也就是添加“version”字段。如果是所有的表都要添加乐观锁,那么软件开发人员需要在所有的业务服务中,添加一遍乐观锁的逻辑,比如版本号的校验等等,太麻烦了。

使用Spring Cloud Alibaba组合Mybatis-Plus,添加乐观锁就只需要几行代码就行。

第一步,在数据库的业务表中添加一个“version”字段;

第二步,以Spring Cloud Alibaba作为基础框架,初始化一个微服务;

第三步,在微服务中添加如下pom依赖。

代码语言:javascript
复制
<!—引入Mybatis Plus-->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.5.1</version>
</dependency>
<!—引入Mybatis-->

 <dependency>
    <groupId>org.mybatis</groupId>
     <artifactId>mybatis</artifactId>
     <version>3.5.6</version>
 </dependency>
 <!—引入适配Spring Framework的mybatis spring-->
 <dependency>
     <groupId>org.mybatis</groupId>
     <artifactId>mybatis-spring</artifactId>
     <version>2.0.6</version>
 </dependency>

第四步,添加乐观锁的拦截器,比如我在项目中使用如下代码。

代码语言:javascript
复制
@Configuration
@MapperScan("com.alibaba.cloud.youxia.mapper")
public class MybatisPlusOptLockerConfig {
    /**
     * 1. 注入一个Mybatis Plus的拦截器MybatisPlusInterceptor,并绑定一个子拦截器。
          OptimisticLockerInnerInterceptor
     * 2. OptimisticLockerInnerInterceptor是用来实现乐观锁的核心类
     * @return
     */
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        //1.新建一个拦截器对象MybatisPlusInterceptor
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        //2.添加子拦截器OptimisticLockerInnerInterceptor
        interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
        //3.返回给Spring Framework的IOC容器
        return interceptor;
    }

第五步,在实体类中添加version字段,比如我在项目中使用如下代码。

代码语言:javascript
复制
@Data
@TableName(value = "user")
public class Example2ProductEntity implements Serializable {
    static final long serialVersionUID = -232434345545442L;
    /**
     * 1.乐观锁的版本号
     * 2.如果注释掉这一行代码,则乐观锁失效
     * 3.需要在数据库表中,添加一个version字段
    */
    @Version
    private Integer version;
}

完成上面五步,乐观锁就添加成功了,你就可以在业务服务中使用它了,关于乐观锁的原理,这里就不分析了。

当然如果还想提效,可以将乐观锁的拦截器,封装成一个Starter组件,这样业务都不用在每个服务中添加一遍了。

当然还可以提效,那就是下沉Dao层代码,这样业务服务几乎一行代码都不用改,就可以实现乐观锁,简单吧。

Spring Cloud Alibaba组合Mybatis-Plus真香

总结

咱们程序员在熟悉一个技术之前,一定要学会高效的去用,只有用了之后,才会去分析原理。

公众号初衷

知识输出是笔者的初衷,借助知识输出,能够认识更多的牛人,能够和牛人沟通,也是自己技术提升的一个机会。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-03-06,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 架构随笔录 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
数据库
云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档