mykit-lock 之——分布式锁插件正式开源
主要测试以 Redis 单节点形式实现分布式锁
测试的入口为:io.mykit.lock.test.redis.single
使用说明
====
1、引用 mykit-lock-redis-single 说明
1)在 pom.xml 中添加如下配置:
<dependency>
<groupId>io.mykit.lock</groupId>
<artifactId>mykit-lock-redis-single</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
2)在项目的 classpath/properties 目录下配置 redis-lock.properties
在项目的 classpath/properties 目录下创建 red 《一线大厂 Java 面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义》无偿开源 威信搜索公众号【编程进阶路】 is-lock.properties(注意:配置文件的名称必须为 redis-lock.properties),文件中的配置项的 Key 必须包含以下内容:
redis.maxIdle=100
redis.minIdle=1
redis.maxTotal=1000
redis.host=127.0.0.1
redis.port=6379
3)定义需要分布式锁支持的接口
package io.mykit.lock.test.redis.single.service;
import io.mykit.lock.redis.annotation.CacheLock;
import io.mykit.lock.redis.annotation.LockedObject;
/**
@author liuyazhuang
@version 1.0.0
@date 2018/9/7 23:36
@description 商品秒杀 Service
*/
public interface SeckillService {
@CacheLock(lockedPrefix="TEST_PREFIX")
public void secKill(String arg1,@LockedObject Long arg2);
}
4)实现需要分布式锁支持接口的类
package io.mykit.lock.test.redis.single.service.impl;
import io.mykit.lock.test.redis.single.service.SeckillService;
import java.util.HashMap;
import java.util.Map;
/**
@author liuyazhuang
@version 1.0.0
@date 2018/9/7 23:38
@description 商品秒杀实现
*/
public class SeckillServiceImpl implements SeckillService {
public static Map<Long, Long> inventory ;
static{
inventory = new HashMap<>();
inventory.put(10000001L, 10000l);
inventory.put(10000002L, 10000l);
}
@Override
public void secKill(String arg1, Long arg2) {
reduceInventory(arg2);
}
//模拟秒杀操作,姑且认为一个秒杀就是将库存减一,实际情景要复杂的多
public Long reduceInventory(Long commodityId){
inventory.put(commodityId,inventory.get(commodityId) - 1);
return inventory.get(commodityId);
}
}
分布式锁概念补充
===========
业务场景
所谓秒杀,从业务角度看,是短时间内多个用户“争抢”资源,这里的资源在大部分秒杀场景里是商品;将业务抽象,技术角度看,秒杀就是多个线程对资源进行操作,所以实现秒杀,就必须控制线程对资源的争抢,既要保证高效并发,也要保证操作的正确。 一些可能的实现
刚才提到过,实现秒杀的关键点是控制线程对资源的争抢,根据基本的线程知识,可以不加思索的想到下面的一些方法:
1、秒杀在技术层面的抽象应该就是一个方法,在这个方法里可能的操作是将商品库存-1,将商品加入用户的购物车等等,在不考虑缓存的情况下应该是要操作数据库的。那么最简单直接的实现就是在这个方法上加上 synchronized 关键字,通俗的讲就是锁住整个方法;
2、锁住整个方法这个策略简单方便,但是似乎有点粗暴。可以稍微优化一下,只锁住秒杀的代码块,比如写数据库的部分;
3、既然有并发问题,那我就让他“不并发”,将所有的线程用一个队列管理起来,使之变成串行操作,自然不会有并发问题。
上面所述的方法都是有效的,但是都不好。为什么?第一和第二种方法本质上是“加锁”,但是锁粒度依然比较高。什么意思?试想一下,如果两个线程同时执行秒杀方法,这两个线程操作的是不同的商品,从业务上讲应该是可以同时进行的,但是如果采用第一二种方法,这两个线程也会去争抢同一个锁,这其实是不必要的。第三种方法也没有解决上面说的问题。 那么如何将锁控制在更细的粒度上呢?可以考虑为每个商品设置一个互斥锁,以和商品 ID 相关的字符串为唯一标识,这样就可以做到只有争抢同一件商品的线程互斥,不会导致所有的线程互斥。分布式锁恰好可以帮助我们解决这个问题。
何为分布式锁
分布式锁是控制分布式系统之间同步访问共享资源的一种方式。在分布式系统中,常常需要协调他们的动作。如果不同的系统或是同一个系统的不同主机之间共享了一个或一组资源,那么访问这些资源的时候,往往需要互斥来防止彼此干扰来保证一致性,在这种情况下,便需要使用到分布式锁。
评论