1.使用场景
当需要做类似于商品秒杀这种功能时,使用分布式锁控制资质的放行。
2.分布式锁实现
(1)基于数据库实现分布式锁;
(2)基于缓存(Redis等)实现分布式锁;
(3)基于Zookeeper实现分布式锁;
3.具体实现
(1)首先我们下载一个apache ab来模拟高并发,下载地址http://httpd.apache.org/download.cgi,具体用法可自行百度
(2)使用网上现成的demo可做测试(个人懒惰的原因,哈哈),demo地址: https://github.com/mzd123/mywy
(3)这个哥们写的还不错,我转发一下他的帖子https://blog.youkuaiyun.com/tuesdayma/article/details/82751790
/** * 加锁 */ public boolean lock3(String key, String value) { //setIfAbsent相当于jedis中的setnx,如果能赋值就返回true,如果已经有值了,就返回false //即:在判断这个key是不是第一次进入这个方法 if (redisTemplate.opsForValue().setIfAbsent(key, value)) { //第一次,即:这个key还没有被赋值的时候 return true; } String current_value = redisTemplate.opsForValue().get(key); if (!MyStringUtils.Object2String(current_value).equals("") //超时了 && Long.parseLong(current_value) < System.currentTimeMillis()) {//① String old_value = redisTemplate.opsForValue().getAndSet(key, value);//② if (!MyStringUtils.Object2String(old_value).equals("") //如果两个线程同时调用这个方法,当同时走到①的时候, // 无论怎么样都有一个线程会先执行②这一行, //假设线程1先执行②这行代码,那redis中key对应的value就变成了value //然后线程2再执行②这行代码的时候,获取到的old_value就是value, //那么value显然和他上面获取的current_value是不一样的,则线程2是没法获取锁的 && old_value.equals(current_value)) { return true; } } return false; }
public void unlock(String key, String value) { try { if (MyStringUtils.Object2String(redisTemplate.opsForValue().get(key)).equals(value)) { redisTemplate.opsForValue().getOperations().delete(key); } } catch (Exception e) { e.printStackTrace(); } }