深入了解分布式锁 导学篇
Posted 南方有东靡
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了深入了解分布式锁 导学篇相关的知识,希望对你有一定的参考价值。
文章简介
该文章基于超卖为为主线 ,解决在多线程的情况下解决超卖问题的解决方案 ,并且对其各个解决方案方案的优缺点进行分析。
文章内容 介绍
该文章刚开始以超卖问题为主线 先介绍单机本地储存情况下通过JVM本地锁去解决超卖问题,接着深入企业场景 数据在mysql 的情况下如何解决高并发对mysql数据库中进行有序操作防止出现脏读的问题,接着引入 非关系型数据情况下 如何处理集群 服务和线程之间 操作有序性的问题 通过redis 乐观锁和redis hash+lua 脚本 zookeeper 节点性质去处理。
学习成果
可以一定程度上基本的分布式锁的原理和使用有着较为深入的理解 熟练使用redis 和 zookeeper 进行分布式锁的实现 并且对高并发下超卖问题有着深入理解。
文章重点
该文章主要以以下几大方面 解决超卖问题的解决方案 :
1、基于JVM本地机制:基于Lock和synchorinzed 关键字 实现在单机且无数据库情况下解决超卖问题。
2、基于Mysql的锁机制:悲观锁机制、乐观锁机制 利用mysql 基于save delete update insert 等操作的原子性进行解决超卖问题。
3、基于redis 本身的乐观锁机制解决超卖问题 基于exec watch mulitic 等命令行为基础解决超卖的问题。
4、 在多服务情况下redis 分布式解决 超卖 基于 redisson 框架实现分布式情况下超卖 可重入的问题,基于hash+lua 脚本手动实现分布式锁的加锁 解锁和可重入锁 自动续期的问题。
5、基于Zookeeper 原始框架下 实现分布式情况下超卖问题。 通过创造临时节点不可重复原理实现自旋锁, 基于临时可序列化节点+监听机制实现Zookeeper的堵塞锁。
6、基于Mysql实现分布式锁(企业没有用过)通过id 加lockname 进行锁的排他,通过设置ThreadId 和 serverd 进行具体业务记录 通过locationTime进行定时任务的记录。
技术构成
1、环境要求:jdk1.8,Maven3.0+
2、开发工具 idea nginx
3、 测试工具 :jmeter
4、该项目Maven 开发环境
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>distribution-Lock-Learning</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>distribution-Lock-Learning</name>
<description>distribution-Lock-Learning</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.1</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>3.16.1</version>
</dependency>
<dependency>
<groupId>net.coobird</groupId>
<artifactId>thumbnailator</artifactId>
<version>0.4.11</version>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.6</version>
</dependency>
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.7.0</version>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>4.3.0</version>
<exclusions>
<exclusion>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>4.3.0</version>
<exclusions>
<exclusion>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.2.2.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>8</source>
<target>8</target>
</configuration>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
<repository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/snapshot</url>
<releases>
<enabled>false</enabled>
</releases>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
<pluginRepository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/snapshot</url>
<releases>
<enabled>false</enabled>
</releases>
</pluginRepository>
</pluginRepositories>
</project>
用Kotlin撸一个图片压缩插件ImageSlimming-导学篇
简述: 很久没有发布Kotlin的实战相关的内容,这段时间在折腾Intellij IDEA的插件开发,折腾出了几个小插件,因为最近公司业务分离,原来堆在基础业务那边模块,都以模块的形式抽离出来,独立仓库管理。那么就是各种打包,jenkins打包配置模块特别麻烦,所以想着是否可以开发一个AndroidStudio插件,我可以写代码和构建发布包同时进行,想想都美滋滋,所以才去研究了下插件的开发。摸清插件开发套路后,其实也觉得挺简单,然后发现很多地方都可以用插件自动化实现,顿时有种发现新大陆赶脚。这次我要讲是如何从零开始,使用Kotlin撸一个AndroidStudio图片压缩插件,本系列文章总三篇:《用Kotlin撸一个图片压缩插件ImageSlimming-导学篇》、《用Kotlin撸一个图片压缩插件ImageSlimming-插件基础篇》、《用Kotlin撸一个图片压缩插件ImageSlimming-实战篇》
一、为什么要撸一个图片压缩插件?
我们在项目开发过程中常会使用图片,一般开发者都不会直接把设计切的图片放入到项目中,而是会去压缩一下,那么一般会去TinyPng网页端压缩一遍,你一般会先把要压缩的图片拖进去,然后又一张张把图片点击下载下来,是不是感觉特别的浪费时间,是不是需要把浪费的时间省下来,然后就愉快地早点下班啦。如果你还没有使用过TinyPng,那么这个插件也许适合你。
然后这段时间正研究插件,所以决定试试,其实很简单的。因为TinyPng提供develop api,可以方便实现图片压缩。这次插件也就是利用了它的API开发的。
二、插件的基本描述
ImageSlimming是一个基于TinyPng API开发的图片压缩的IDEA工具插件,采用的是Kotlin语言开发以及Java Swing框架设计UI界面。可运行在AndroidStudio,Intellij IDEA,WebStorm等JetBrains全家桶系列IDE中。
三、插件支持的功能
1、支持整个目录中的图片批量压缩,只需要指定图片源目录和压缩的输出目录即可
2、支持单张或者选定多张图片文件进行压缩
3、支持png,jpg格式图片
4、支持输入目录和输出目录二次选择功能,减少繁琐指定相同的目录
5、支持指定输入文件的前缀,也即是批量文件添加前缀名,以及前缀名二次选择功能
6、图片压缩过程中,仍然继续coding, 工作并行执行
四、插件开发使用到的技术点
1、Intellij Idea 插件开发基础知识
2、插件开发中执行一个后台线程任务Task.Backgroundable的使用
3、Intellij Idea open api 的使用
4、Kotlin 开发基础知识
5、Kotlin中扩展函数的封装
6、Kotlin中Lambda表达式的使用
7、Kotlin中函数式API的使用
8、Kotlin中IO操作API的使用
9、Java中Swing UI框架的基本使用
10、TinyPng API基本使用
五、插件的使用步骤
1、首先,按照Plugin通用安装方式,安装好对应的插件,可以直接在jetbrains仓库中搜索ImageSlimming,安装重启即可。
重启后发现有如图插件,就说明安装成功。2、然后点击插件,第一次需要你填入TinyPng APIKEY,由于插件图片压缩主要借助于TinyPng Api, 所以需要使用者去TinyPng官网申请 https://tinypng.com/developers
3、输入申请到ApiKey后,插件会自动验证KEY的合法性,检测通过后会弹出压缩图片界面
4、选择源目录也就是原图片目录,输出目录也就是压缩后图片存放目录,当然也可以指定特定某张或某些图片文件作为输入源,
5、是否指定输出文件前缀名,该功能主要适用于在Android中多模块开发的时候,每个模块图片资源名不能重复,所以每个模块图片前缀不一样,这里可以指定输出文件前缀。
6、点击OK就开始压缩了,此时压缩过程你可以继续你的coding,最后压缩完毕会以对话框提示。
7、压缩结果
8、为了减少指定输入输出目录次数以及文件前缀的次数,会把每次用户使用过的目录给缓存起来,以及下次直接选择使用,也就是前面说的二次选择功能。
六、插件源码和插件包下载
插件包下载: https://github.com/BayMikyou/ImageSlimming/blob/feature-develop/ImageSlimming.zip
以上是关于深入了解分布式锁 导学篇的主要内容,如果未能解决你的问题,请参考以下文章