1、最近再学分布式锁,把自己所学的一点心得分享给大家
2、首先介绍我的spring boot项目结构
数据库表的结构很简单,t_lock表就一个主键字段id
3、实现锁的代码
这里运用了模板设计模式
锁接口:
public interface TestLock {
/**
* 加锁
*/
public void getLock();
/**
* 解锁
*/
public void unLock();
}
锁的抽象实现类:
public abstract class AbstractTestLock implements TestLock{
@Override
public void getLock() {
/**
* 1、竞争锁
* 2、占有锁
* 3、任务阻塞
* 4、释放锁
*/
if(tryLock()) {
System.out.println("========获取锁的资源===========");
}else {
//等待
waitLock();
//重新获取资源
getLock();
}
}
public abstract void waitLock();
public abstract boolean tryLock();
}
锁的实现:
@Service
public class MySqlLock extends AbstractTestLock{
@Resource
private LockMapper lockMapper;
private static final Integer ID = 1;
@Override
public boolean tryLock() {
try {
Lock lock = new Lock();
lock.setId(ID);
lockMapper.save(lock);
}catch (Exception e) {
return false;
}
return true;
}
@Override
public void unLock() {
lockMapper.delete(ID);
}
@Override
public void waitLock() {
try {
Thread.currentThread().sleep(10);
}catch (Exception e) {
e.printStackTrace();
}
}
}
仿照订单生成:
public class OrderGenerator {
// 全局订单号
public static int num = 0;
public String getNumber() {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
return sdf.format(new Date())+"-"+ ++num;
}
}
4、测试
public class MysqlLockTest extends LockApplicationTests{
public OrderGenerator generator = new OrderGenerator();
@Resource
private TestLock lock;
@Test
public void testGetOrderNum() throws InterruptedException {
System.out.println("=======生成唯一订单号==========");
for(int i=0; i< 50 ; i++) {
new Thread(
(Runnable) () -> { getNumber(); }
).start();
}
Thread.currentThread().join();
}
private void getNumber() {
try {
lock.getLock();
String number = generator.getNumber();
System.out.println(Thread.currentThread().getName() + ",生成订单ID:"+ number);
}catch (Exception e) {
e.printStackTrace();
}finally {
lock.unLock();
}
}
}
测试结果:
可以看见总共生成了50个订单号,没有重复出现同样的订单号,这样子就实现了用mysql实现分布式锁。
5、使用mysql实现分布式锁的弊端:
a、性能差,无法适应高并发场景,众所周知,mysql的并发瓶颈在300-700之间,当然也有可能达不到,所以一旦并发超过700的话,那么mysql就没法应用于此场景;
b、容易死锁,一旦数据库中数据一开始有数据,那么就会一直处于死锁状态,或者删除数据失败,那么也会一直处于死锁;
c、无法优雅的实现阻塞式锁。
相关推荐
**基于MySQL实现分布式锁** MySQL的InnoDB存储引擎支持行级锁定,我们可以利用这一特性实现分布式锁。有两种方式:悲观锁(`SELECT ... FOR UPDATE`)和乐观锁。悲观锁在事务开始时立即锁定资源,直到事务结束才释放...
总之,MySQL实现分布式锁提供了一种简单而实用的方法,但实际应用中还需要结合业务需求和系统特性进行优化和调整,以保证系统的稳定性和性能。通过深入理解数据库事务和索引机制,可以设计出更加高效和可靠的分布式...
计算机技术、IT咨询、人工智能AI理论介绍,学习参考资料 计算机技术、IT咨询、人工智能AI理论介绍,学习参考资料 计算机技术、IT咨询、人工智能AI理论介绍,学习参考资料 计算机技术、IT咨询、人工智能AI理论介绍,...
MySQL借助DB实现分布式锁是一种在分布式环境中协调多个节点访问共享资源的方法。分布式锁的主要目标是保证数据的一致性和避免并发冲突。在没有第三方组件如Redis或Zookeeper的情况下,使用MySQL数据库来实现分布式锁...
### 数据库实现分布式锁 在分布式系统中,为了确保数据的一致性和事务的原子性,分布式锁成为一种常用的解决方案。本文将围绕如何使用数据库来实现一个简单的分布式锁机制展开讨论,涉及尝试获取锁、等待锁以及释放...
其中,临时节点和ephemeral节点可以被用来实现分布式锁。 临时节点实现分布式锁 临时节点是一种特殊的节点,它可以被用来实现分布式锁。当一个客户端创建一个临时节点时,如果该节点已经存在,则客户端可以等待该...
1. 基于数据库的分布式锁:利用数据库的事务和行级锁机制,例如MySQL的SELECT FOR UPDATE语句。这种方式简单易懂,但可能面临数据库性能瓶颈。 2. 基于缓存的分布式锁:使用Redis等内存数据库,通过SETNX命令实现...
- **利用MySQL唯一索引特性**:通过在表中创建唯一索引来实现分布式锁,但这种方式在高并发场景下性能较差,且实现较为复杂,因此较少在生产环境中使用。 ##### 2. 基于Redis实现分布式锁 - **Redis为单进程单线程...
演示了mysql和redis+Lua、redisson实现分布式锁的具体过程
Zookeeper作为一个分布式应用程序协调服务,提供了对分布式锁、配置管理、命名服务和同步服务的支持。 为了实现DDBS的高效运行,集群软件应满足特定的技术要求。Linux操作系统6.2及以上版本、Zookeeper 3.4.5及以上...
1. 基于数据库实现:例如MySQL,通过行级锁或者表级锁,利用数据库的事务特性来实现分布式锁。但是这种方式存在性能瓶颈,不适用于高并发场景。 2. 基于Redis实现:Redis提供了丰富的数据结构和操作命令,如`SETNX`...
常见的分布式锁实现有Zookeeper、Redis的setnx命令、RedLock算法等。 4. **可重入锁**:可重入锁允许一个线程获取同一资源的多次锁定,如Java的`synchronized`和`ReentrantLock`。这样可以避免死锁,当一个线程已经...
1. **基于MySQL实现**:利用数据库的事务特性,如悲观锁或乐观锁,来实现分布式锁。例如,可以使用`SELECT ... FOR UPDATE`语句在读取数据时锁定行,防止其他事务修改。然而,这种方式可能会引入额外的数据库负载,...
百度可能会采用诸如Raft或Zookeeper这样的协调服务来管理分布式锁,确保在节点故障时仍能保持数据一致性。同时,通过冗余备份和故障检测机制,确保系统的高可用性。 5. 混合云存储:在某些情况下,百度可能将本地...
数据库作为传统意义上的数据存储介质,在实现分布式锁方面也有其独特的优势和局限性。常见的数据库锁分为悲观锁和乐观锁两种类型。 ##### 1. 悲观锁 悲观锁通常采用`SELECT ... WHERE ... FOR UPDATE`的方式来实现...
分布式锁实现的方案有很多,比如基于ZooKeeper实现、或者基于Mysql实现等等,我们来一起看看如何基于Redis实现分布式锁服务。 分布式锁要点 对于分布式锁的目标,我们必须首先明确三点: 1、任何一个时间点...
1. **基于数据库的分布式锁**:利用数据库的事务和行级锁来实现,例如在MySQL中使用`SELECT ... FOR UPDATE`语句。 2. **基于缓存的分布式锁**:如Redis或Memcached,利用它们的原子操作(如SETNX或CAS命令)来设置...