基于 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/DAMENGusername: your_userpassword: your_passworddriver-class-name: dm.jdbc.driver.DmDrivermybatis:mapper-locations: classpath*:mapper/*.xmlconfiguration: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_lockSET 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
