分布式锁
1、什么是分布式锁:
分布式锁,即分布式系统中的锁。在单体应用中我们通过锁解决的是控制共享资源访问的问题,而分布式锁,就是解决了分布式系统中控制共享资源访问的问题。与单体应用不同的是,分布式系统中竞争共享资源的最小粒度从线程升级成了进程。
2、分布式锁应该具备哪些条件:
在分布式系统环境下,一个方法在同一时间只能被一个机器的一个线程执行
高可用的获取锁与释放锁
高性能的获取锁与释放锁
具备可重入特性(可理解为重新进入,由多于一个任务并发使用,而不必担心数据错误)
具备锁失效机制,即自动解锁,防止死锁
具备非阻塞锁特性,即没有获取到锁将直接返回获取锁失败
基于数据库的分布式锁
核心代码
@Slf4j
@Component
public class ScheduleJob
{
private String key = "job001";
@Autowired
JdbcTemplate jdbcTemplate;
String ip;
/**
* 初始化
*/
@PostConstruct
public void init()
{
long count = jdbcTemplate.queryForObject("SELECT count(*) FROM t_schedule_lock WHERE key_name=?", Long.class, key);
if (count == 0)
{
jdbcTemplate.update("INSERT INTO t_schedule_lock(key_name, time) VALUES(?, now())", key);
}
try
{
ip = InetAddress.getLocalHost().getHostAddress();
}
catch (UnknownHostException e)
{
}
}
@Scheduled(cron = "0/10 * * * * ?")
public void run()
{
try
{
if (getLock(9L))
{
log.info("[{}] #### hello world ***********", ip);
}
else
{
log.info("[{}] 没抢到,骂骂咧咧的走了......", ip);
}
}
catch (Exception e)
{
log.error(e.getMessage(), e);
}
}
/**
* 获取lock,并更新time为下次执行时间 now()+ seconds<BR>
*
* 注意: 为了保证jdbcTemplate.update执行成功,一般设置seconds稍小于@Scheduled设置的运行间隔秒数
*
* @return
*/
private boolean getLock(long seconds)
{
return jdbcTemplate.update("UPDATE t_schedule_lock SET time = adddate(now(), INTERVAL ? SECOND) WHERE key_name = ? AND now() > time", seconds, key) > 0;
}
}
代码传送
https://gitee.com/00fly/effict-side/tree/master/springboot-locks
项目已经实现了maven插件打包镜像,上传阿里云镜像仓库。
代码运行
下载docker文件下的这2个文件,上传至带有docker-compose以及docker环境的服务器
运行命令
sh scale.sh
docker ps
docker logs -f <containerId>
运行效果图:
有任何问题和建议,都可以向我提问讨论,大家一起进步,谢谢!
-over-