温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

mysql如何实现分布式锁

发布时间:2021-07-07 16:56:22 来源:亿速云 阅读:410 作者:chen 栏目:编程语言

本篇内容主要讲解“mysql如何实现分布式锁”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“mysql如何实现分布式锁”吧!

一、具体实现

1、共享资源类TicketResource

package com.lau.mysql.resource;

import org.springframework.stereotype.Component;

/** 
* @ClassName: TicketResource 
* @Description: TODO
* @author Liu 
* @date 2021年4月18日 下午3:57:38 
*/
@Component
public class TicketResource {
	private Integer ticket = 20;
	
	public String use(){
		String res = null;
				
		if(this.ticket > 0) {
			res = "分布式锁-线程:" + Thread.currentThread().getName() + "卖了1张票,火车票还剩:" + (--ticket) + "张";
		}
		else {
			res = "火车票售罄!";
		}
		
		System.out.println(res);
		
		return res;
	}
}

2、表对象实体LockPo

package com.lau.mysql.entity;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class LockPo implements Serializable {
  private Long id;
}

3、dao

package com.lau.mysql.dao;


import org.apache.ibatis.annotations.Mapper;

import com.lau.mysql.entity.LockPo;

@Mapper
public interface LockDao {
    public int create(Long id); //写
    
    public int del(Long id); //写
}

4、controller

package com.lau.mysql.controller;

import javax.annotation.Resource;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import com.lau.mysql.lock.Lock;
import com.lau.mysql.resource.TicketResource;

@RestController
public class LockController {

  @Resource
  private Lock lock;
  
  @Resource
  private TicketResource ticketResource;

  @GetMapping(value = "/mysql/distributed/lock")
  public String purchaseTicket(){
	try {
		lock.getLock();
		
		return ticketResource.use();
	} finally {
		lock.unLock();
	}
  }
}

5、application.yml

server:
  port: 8001


spring:
  application:
    name: cloud-payment-service
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: org.gjt.mm.mysql.Driver
    url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8&useSSL=false
    username: root
    password: ******
    druid:
      validationQuery: SELECT 1

mybatis:
  mapperLocations: classpath:mapper/*.xml
  type-aliases-package: com.lau.mysql.entity

6、LockMapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.lau.mysql.dao.LockDao">

    <resultMap id="BaseResultMap" type="com.lau.mysql.entity.LockPo">
        <id column="id" property="id" jdbcType="BIGINT"/>
    </resultMap>

    <insert id="create" parameterType="java.lang.Long">
        insert into t_lock(id) values(#{id});
    </insert>

    <insert id="del" parameterType="java.lang.Long">
        delete from t_lock where id = #{id};
    </insert>

</mapper>

7、sql

CREATE TABLE `t_lock` (
   `id` BIGINT(11) COMMENT 'ID',
   PRIMARY KEY (`id`)
 ) ENGINE=INNODB DEFAULT CHARSET=utf8

8、数据表记录

mysql如何实现分布式锁

9、锁相关类

package com.lau.mysql.lock;

/** 
* @ClassName: Lock 
* @Description: TODO
* @author Liu 
* @date 2021年4月18日 下午3:32:23 
*/
public interface Lock {
	void getLock();
	
	void unLock();
}
package com.lau.mysql.lock;

/** 
* @ClassName: LockManager 
* @Description: 本类采用了模板方法模式
* @author Liu 
* @date 2021年4月18日 下午3:30:21 
*/
public abstract class AbstractLock implements Lock{

	@Override
	public void getLock() {
		if(this.tryLock()) {
			
		}
		else {
			this.waitLock();
			
			this.getLock();
		}
	}
	
	public abstract Boolean tryLock();
	
	public abstract void waitLock();
}
package com.lau.mysql.lock.impl;

import java.util.concurrent.TimeUnit;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.lau.mysql.dao.LockDao;
import com.lau.mysql.lock.AbstractLock;

/** 
* @ClassName: LockImpl 
* @Description: TODO
* @author Liu 
* @date 2021年4月18日 下午3:46:34 
*/
@Component
public class LockImpl extends AbstractLock{
	@Autowired
    private LockDao lockDao;

	@Override
	public void unLock() {
		lockDao.del(1L);
	}

	/**
	 * 注意如果已存在主键id 1,再次调用此方法会抛出异常,返回false(锁互斥)
	 */
	@Override
	public Boolean tryLock() {
		try {
			int create = lockDao.create(1L);
			return create > 0;
		}
		catch (Exception e) {
			return false;
		}
	}

	@Override
	public void waitLock() {
		try {
			TimeUnit.SECONDS.sleep(1);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

}

10、输出

分布式锁-线程:qtp879353005-178卖了1张票,火车票还剩:19张
分布式锁-线程:qtp879353005-175卖了1张票,火车票还剩:18张
分布式锁-线程:qtp879353005-177卖了1张票,火车票还剩:17张
分布式锁-线程:qtp879353005-180卖了1张票,火车票还剩:16张
分布式锁-线程:qtp879353005-179卖了1张票,火车票还剩:15张
分布式锁-线程:qtp879353005-177卖了1张票,火车票还剩:14张
分布式锁-线程:qtp879353005-180卖了1张票,火车票还剩:13张
分布式锁-线程:qtp879353005-179卖了1张票,火车票还剩:12张
分布式锁-线程:qtp879353005-177卖了1张票,火车票还剩:11张
分布式锁-线程:qtp879353005-180卖了1张票,火车票还剩:10张
分布式锁-线程:qtp879353005-177卖了1张票,火车票还剩:9张
分布式锁-线程:qtp879353005-180卖了1张票,火车票还剩:8张
分布式锁-线程:qtp879353005-179卖了1张票,火车票还剩:7张
分布式锁-线程:qtp879353005-177卖了1张票,火车票还剩:6张
分布式锁-线程:qtp879353005-179卖了1张票,火车票还剩:5张
分布式锁-线程:qtp879353005-177卖了1张票,火车票还剩:4张
分布式锁-线程:qtp879353005-180卖了1张票,火车票还剩:3张
分布式锁-线程:qtp879353005-179卖了1张票,火车票还剩:2张
分布式锁-线程:qtp879353005-177卖了1张票,火车票还剩:1张
分布式锁-线程:qtp879353005-180卖了1张票,火车票还剩:0张

二、mysql实现分布式锁的优缺点

缺点:

① 性能低下(频繁磁盘io)

② 产生死锁概率高

③ 不太适合太高并发场景

④ waitLock()方法频繁地轮询不优雅

到此,相信大家对“mysql如何实现分布式锁”有了更深的了解,不妨来实际操作一番吧!这里是亿速云网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI