【分布式基础】分布式锁

分布式锁

为什么需要分布式锁

当我们遇到同一方法在同一时间只能让一个线程来执行,那么在单机环境下,我们不需要考虑分布式锁,只需要使用 Java 相应的 API 即可。但是当我们的系统是分布式部署的时候,就不能仅在线程方面考虑锁的问题了,分布式环境下与单机环境最大的不同不是多线程而是多进程

多线程由于可以共享堆内存,因此可以简单的采取内存作为标记存储位置,而进程之间可能彼此都不在一个物理机上,因此需要将标记存储在一个所有进程都能看得到的地方。

基于数据库的分布式锁

基于数据库表

要使用数据库实现分布式锁,最简单的就是创建一个锁表,然后通过该表中的数据实现获取和释放锁的操作。

当我们要锁住某个方法或者某个资源的时候,我们就在该表中加入一条记录,想要释放的时候就删除这条记录。

可以创建一张表:

CREATE TABLE `resource_lock` (
  `key_resource` varchar(45) COLLATE utf8_bin NOT NULL DEFAULT '资源主键',
  `status` char(1) COLLATE utf8_bin NOT NULL DEFAULT '' COMMENT 'S,F,P',
  `lock_flag` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '1是已经锁 0是未锁',
  `begin_time` datetime DEFAULT NULL COMMENT '开始时间',
  `end_time` datetime DEFAULT NULL COMMENT '结束时间',
  `client_ip` varchar(45) COLLATE utf8_bin NOT NULL DEFAULT '抢到锁的IP',
  `time` int(10) unsigned NOT NULL DEFAULT '60' COMMENT '方法生命周期内只允许一个结点获取一次锁,单位:分钟',
  PRIMARY KEY (`key_resource`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin

当我们想要加锁就执行相应的 insert 语句,解锁就执行相应的 delete 语句

这张表之所以可以用来当做分布式锁,主要使用的是 主键的唯一性,如果有针对同一资源的加锁请求同时提交到数据库的话,数据库会保证只有一个操作可以执行成功。

存在的问题

  1. 锁强依赖数据库的可用性,若数据库是一个单点,数据库挂掉,整个系统就不能用了
  2. 锁没有失效时间,一旦解锁失败,记录会一直在数据库中,其他线程无法获得到锁
  3. 锁是非阻塞的,数据库 insert 失败只会直接报错,没有获得锁的线程不会进入队列排队等待
  4. 锁是非重入的

基于 Redis 实现分布式锁

利用 Setnx + expire命令(错误做法)

Redis 的 Setnx key value 命令可以用来当 key 不存在时才能成功添加新值,若 key 存在就什么也不做,考虑超时机制,所以我们利用 expire 命令来设置超时时间

public boolean lock(String key,String value,int timeout) {
    Long result = jedis.setnx(key, value);
    if (result == 1) {
        return jedis.expire(key, timeout) == 1;
    } else {
        return false;
    }
}

但是因为 setnx 和 expire 是分开操作的,并不是原子操作,如果 setnx 指令做完了就宕机了,那么这个锁就不会过期了

利用 Lua 脚本

针对上面的问题,我们可以使用 Lua 脚本解决,将 sentnx 和 expire 操作写进一个 Lua 脚本中,即可实现原子操作。

使用 set key value [EX sencond] [PX millisecond] [NX|XX]命令

这个命令是一个原子操作

public boolean tryLock_with_set(String key, String UniqueId, int seconds) {
    return "OK".equals(jedis.set(key, UniqueId, "NX", "EX", seconds));
}

value 需要具备唯一性,这样可以防止其他线程将自己的锁删除掉

  • 7
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
信息数据从传统到当代,是一直在变革当中,突如其来的互联网让传统的信息管理看到了革命性的曙光,因为传统信息管理从时效性,还是安全性,还是可操作性等各个方面来讲,遇到了互联网时代才发现能补上自古以来的短板,有效的提升管理的效率和业务水平。传统的管理模式,时间越久管理的内容越多,也需要更多的人来对数据进行整理,并且数据的汇总查询方面效率也是极其的低下,并且数据安全方面永远不会保证安全性能。结合数据内容管理的种种缺点,在互联网时代都可以得到有效的补充。结合先进的互联网技术,开发符合需求的软件,让数据内容管理不管是从录入的及时性,查看的及时性还是汇总分析的及时性,都能让正确率达到最高,管理更加的科学和便捷。本次开发的医院后台管理系统实现了病房管理、病例管理、处方管理、字典管理、公告信息管理、患者管理、药品管理、医生管理、预约医生管理、住院管理、管理员管理等功能。系统用到了关系型数据库中王者MySql作为系统的数据库,有效的对数据进行安全的存储,有效的备份,对数据可靠性方面得到了保证。并且程序也具备程序需求的所有功能,使得操作性还是安全性都大大提高,让医院后台管理系统更能从理念走到现实,确确实实的让人们提升信息处理效率。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值