基于数据库实现分布式锁
基于 Spring Boot + MyBatis + DM8 的分布式锁
project-root/
├── src/
│ └── main/
│ ├── java/com/example/demo/
│ │ ├── DemoApplication.java
│ │ ├── config/
│ │ │ └── MyBatisConfig.java
│ │ ├── entity/
│ │ │ └── ScheduledLock.java
│ │ ├── mapper/
│ │ │ └── ScheduledLockMapper.java
│ │ ├── service/
│ │ │ └── TaskLockService.java
│ │ └── task/
│ │ └── DemoScheduledTask.java
│ └── resources/
│ ├── application.yml
│ └── mapper/ScheduledLockMapper.xml
├── pom.xml
// pom.xml
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>dm8-task-lock-demo</artifactId>
<version>1.0.0</version>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.3.1</version>
</dependency>
<dependency>
<groupId>com.dameng</groupId>
<artifactId>DmJdbcDriver18</artifactId>
<version>8.1.2.49</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-scheduling</artifactId>
</dependency>
</dependencies>
</project>
// application.yml
spring:
datasource:
url: jdbc:dm://localhost:5236/DAMENG
username: your_user
password: your_password
driver-class-name: dm.jdbc.driver.DmDriver
mybatis:
mapper-locations: classpath*:mapper/*.xml
configuration:
map-underscore-to-camel-case: true
// entity/ScheduledLock.java
@Data
public class ScheduledLock {
private String lockName;
private LocalDateTime lockUntil;
private LocalDateTime lockedAt;
private String lockedBy;
}
// mapper/ScheduledLockMapper.java
@Mapper
public interface ScheduledLockMapper {
ScheduledLock selectLock(@Param("lockName") String lockName);
void insertLock(ScheduledLock lock);
int updateIfExpired(ScheduledLock lock);
}
// mapper/ScheduledLockMapper.xml
<mapper namespace="com.example.demo.mapper.ScheduledLockMapper">
<select id="selectLock" resultType="com.example.demo.entity.ScheduledLock">
SELECT * FROM scheduled_lock WHERE lock_name = #{lockName}
</select>
<insert id="insertLock">
INSERT INTO scheduled_lock (lock_name, lock_until, locked_at, locked_by)
VALUES (#{lockName}, #{lockUntil}, #{lockedAt}, #{lockedBy})
</insert>
<update id="updateIfExpired">
UPDATE scheduled_lock
SET lock_until = #{lockUntil},
locked_at = #{lockedAt},
locked_by = #{lockedBy}
WHERE lock_name = #{lockName} AND lock_until < SYSDATE
</update>
</mapper>
// service/TaskLockService.java
@Service
public class TaskLockService {
@Autowired ScheduledLockMapper mapper;
private final String instanceId = InetAddress.getLocalHost().getHostName();
public boolean tryLock(String lockName, Duration holdTime) {
LocalDateTime now = LocalDateTime.now();
LocalDateTime until = now.plus(holdTime);
ScheduledLock lock = new ScheduledLock();
lock.setLockName(lockName);
lock.setLockUntil(until);
lock.setLockedAt(now);
lock.setLockedBy(instanceId);
int updated = mapper.updateIfExpired(lock);
if (updated > 0) return true;
ScheduledLock existing = mapper.selectLock(lockName);
if (existing == null) {
mapper.insertLock(lock);
return true;
}
return instanceId.equals(existing.getLockedBy()) && existing.getLockUntil().isAfter(now);
}
}
// task/DemoScheduledTask.java
@Slf4j
@Component
public class DemoScheduledTask {
@Autowired TaskLockService lockService;
@Scheduled(cron = "0 */1 * * * ?")
public void runClusterSingletonTask() {
if (!lockService.tryLock("demo-task", Duration.ofMinutes(2))) {
log.info("跳过任务,本机未抢到锁");
return;
}
log.info("本机获得锁,执行定时任务");
// 执行任务逻辑
}
}
// SQL 建表
CREATE TABLE scheduled_lock (
lock_name VARCHAR(100) PRIMARY KEY,
lock_until TIMESTAMP,
locked_at TIMESTAMP,
locked_by VARCHAR(100)
);
特点:
-
支持多实例部署,只有一台机器能执行任务
-
使用达梦数据库做分布式锁,自动过期无需手动释放
-
基于 MyBatis,简单清晰,易于扩展
-
配置友好,完全可运行、可集成
包含模块:
-
scheduled_lock 建表 SQL
-
实体类 + Mapper + XML + Service
-
一个最小定时任务示例(每分钟执行一次)
-
YML 配置连接 DM8

浙公网安备 33010602011771号