当前位置:首页 > 科技  > 软件

面试官必问的分布式锁面试题,你答得上来吗?

来源: 责编: 时间:2023-11-10 09:14:54 166观看
导读一、面试聊聊-分布式锁,如何回答?要分析分布式锁这个问题,我们根据黄金圈法则来分析。黄金圈法则是由美国营销顾问西蒙·斯涅克(Simon Sinek)提出的一种思维模型,用于帮助人们更好地理解和传达信息。黄金圈法则由三个圈组成

1wh28资讯网——每日最新资讯28at.com

一、面试聊聊-分布式锁,如何回答?

要分析分布式锁这个问题,我们根据黄金圈法则来分析。1wh28资讯网——每日最新资讯28at.com

1wh28资讯网——每日最新资讯28at.com

黄金圈法则是由美国营销顾问西蒙·斯涅克(Simon Sinek)提出的一种思维模型,用于帮助人们更好地理解和传达信息。黄金圈法则由三个圈组成,分别是:1wh28资讯网——每日最新资讯28at.com

  • 为什么(Why):为什么要做这件事?这是黄金圈的核心,是一切的起点。
  • 怎么做(How):怎么做这件事?这是黄金圈的中间部分,是实现目标的方法。
  • 做什么(What):做什么这件事?这是黄金圈的外围部分,是具体的行为。

使用3w分析问题思路来分析分布式锁,可以从以下几个方面进行分析:1wh28资讯网——每日最新资讯28at.com

What:分布式锁是什么?

分布式锁是控制分布式系统之间同步访问共享资源的机制。在分布式系统中,常常需要协调他们的动作。如果不同的系统或是同一个系统的不同主机之间共享了一个或一组资源,那么访问这些资源的时候,往往需要互斥来防止彼此干扰来保证一致性,在这种情况下,便需要使用到分布式锁。1wh28资讯网——每日最新资讯28at.com

回答时:先说一下概念。分布式锁是用于在分布式系统中控制对共享资源的访问,以避免数据竞争和并发问题。1wh28资讯网——每日最新资讯28at.com

How:如何实现分布式锁?

分布式锁的实现方法有很多,常见的有以下几种:1wh28资讯网——每日最新资讯28at.com

  • 数据库锁:使用数据库中的行锁或表锁来实现分布式锁。
  • 文件锁:使用文件来实现分布式锁。
  • Zookeeper锁:使用Zookeeper来实现分布式锁。
  • Redis锁:使用Redis来实现分布式锁。
  • 消息队列锁:使用消息队列来实现分布式锁。

回答时:说一下分布式锁以上的实现方式。1wh28资讯网——每日最新资讯28at.com

Why:为什么需要分布式锁?

一些需要分布式锁的场景:1wh28资讯网——每日最新资讯28at.com

  • 分布式数据库事务:在分布式系统中,通常需要使用分布式事务来保证数据的一致性。在分布式事务中,通常会使用分布式锁来保证事务的执行顺序。
  • 分布式资源分配:在分布式系统中,通常需要使用分布式锁来分配共享资源。例如,在抢购场景中,需要使用分布式锁来保证同一商品只能被一个用户购买。
  • 分布式数据同步:在分布式系统中,通常需要使用分布式锁来保证数据的同步。例如,在订单系统中,需要使用分布式锁来保证同一订单只能被一个系统修改。

回答时:说一下分布式锁的应用场景。1wh28资讯网——每日最新资讯28at.com

二、深入聊聊-分布式锁在项目中的应用

1、Redisson实现分布式锁

Redisson 是一个基于 Redis 的 Java 分布式框架。Redisson 提供了丰富的功能,包括分布式锁、分布式集合、分布式队列等。1wh28资讯网——每日最新资讯28at.com

以下是使用 Redisson 实现分布式锁的示例:1wh28资讯网——每日最新资讯28at.com

@Autowired    private RedissonClient redissonClient;    public String lock() {        // 获取锁        RLock lock = redissonClient.getLock("lock");        boolean acquired = lock.tryLock(10,-1,TimeUnit.SECONDS);        if (acquired) {            // 获取锁成功,执行业务逻辑            return "获取锁成功,执行业务逻辑...";        } else {            // 获取锁失败,重试            return "获取锁失败,重试...";        }    }    public String unlock() {        // 释放锁        RLock lock = redissonClient.getLock("lock");        lock.unlock();        return "释放锁成功...";    }

另外,redisson支持锁续期。即在锁键值过期后任务还没执行完成,此时需要把锁键值的时间自动延长。1wh28资讯网——每日最新资讯28at.com

Redisson提供了的续期机制,只要客户端加锁成功,就会启动一个Watch Dog。可以看到源代码的实现leaseTime不设置为-1时开启监听。如果任务没完成就调用scheduleExpirationRenewal续期方法。1wh28资讯网——每日最新资讯28at.com

1wh28资讯网——每日最新资讯28at.com

tryLock() 方法用于尝试获取分布式锁,该方法有三个参数:1wh28资讯网——每日最新资讯28at.com

  • key:锁的键值。
  • waitTime:等待获取锁的时间,单位为毫秒。
  • leaseTime:锁的过期时间,单位为毫秒。

waitTime 参数表示客户端最多等待多长时间来获取锁。如果在 waitTime 时间内没有获取到锁,则会返回 false。1wh28资讯网——每日最新资讯28at.com

leaseTime 参数表示锁的过期时间。如果锁在 leaseTime 时间内没有被释放,则会自动释放。如果 leaseTime 设置为 -1,则表示锁的过期时间由 renew() 方法来控制。这样,在业务逻辑执行过程中,可以定期调用 lock.renew() 方法来续期锁的过期时间。1wh28资讯网——每日最新资讯28at.com

tryLock() 方法的返回值是一个 Boolean 值,表示是否成功获取到锁。如果成功获取到锁,则返回 true。否则,返回 false。1wh28资讯网——每日最新资讯28at.com

2、Springboot+Lettuce

在 SpringBoot 2.7 中,可以通过spring-boot-starter-data-redis 默认依赖是Lettuce。那么Lettuce是如何实现分布式锁呢1wh28资讯网——每日最新资讯28at.com

  • 在 Spring Boot 项目中添加 spring-boot-starter-data-redis 依赖。
  • 定义一个 RedisLock 类来封装分布式锁的相关操作。
  • 在 ServiceImpl类中使用 RedisLock 类来获取和释放分布式锁。

以下是 SpringBoot+Lettuce 实现分布式锁的完整代码:1wh28资讯网——每日最新资讯28at.com

@Componentpublic class RedisLock {    private static final String LOCK_SCRIPT = "if redis.call('exists', KEYS[1]) == 0 then/n" +    "    redis.call('set', KEYS[1], ARGV[1], 'NX', 'PX', ARGV[2]);/n" +    "    return 1/n" +    "else/n" +    "    return 0/n" +    "end";    private final RedisTemplate<String, String> redisTemplate;    public RedisLock(RedisTemplate<String, String> redisTemplate) {        this.redisTemplate = redisTemplate;    }    //获得锁    public boolean acquireLock(String key, long timeout) {        String uuid = UUID.randomUUID().toString();        Object result = redisTemplate.execute(new DefaultRedisScript(LOCK_SCRIPT, Long.class), Arrays.asList(key), uuid, timeout);        return result != null && (long) result == 1;    }	//释放锁    public void releaseLock(String key, String uuid) {        redisTemplate.delete(key);    }}
@Servicepublic class TestServcieImpl implements TestServcie{  @Autowired    private StringRedisTemplate stringRedisTemplate;    // 加锁脚本    private static final String LOCK_SCRIPT = "if redis.call ('setnx', KEYS[1], ARGV[1]) == 1 then return redis.call ('expire', KEYS[1], ARGV[2]) else return 0 end";    // 解锁脚本    private static final String UNLOCK_SCRIPT = "if redis.call ('get', KEYS[1]) == ARGV[1] then return redis.call ('del', KEYS[1]) else return 0 end";    // 加锁方法    public boolean lock(String key, String value, Long expire) {        RedisScript<Long> redisScript = new DefaultRedisScript<>(LOCK_SCRIPT, Long.class);        Long result = stringRedisTemplate.execute(redisScript, Collections.singletonList(key), value, String.valueOf(expire));        return result.equals(Long.valueOf(1));    }    // 解锁方法    public boolean unlock(String key, String value) {        RedisScript<Long> redisScript = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);        Long result = stringRedisTemplate.execute(redisScript, Collections.singletonList(key), value);        return result.equals(Long.valueOf(1));    }}

在上述 demo 中,我们使用 RedisLock 类来封装分布式锁的相关操作。acquireLock() 方法用于获取分布式锁,releaseLock() 方法用于释放分布式锁。1wh28资讯网——每日最新资讯28at.com

在 ServcieImpl 类中,我们使用 RedisLock 类来获取和释放分布式锁。lock() 方法用于获取锁,unlock() 方法用于释放锁。不像Redisson封装好了相应的方法,Lettuuce如果要实现锁续期就需要自己写监听器及相应的lua脚本。1wh28资讯网——每日最新资讯28at.com

三、小结

1、什么是Lua?

可以看到不论是Redisson还是Lettuce实现分布式锁都使用的Lua脚本,那我们先来了解一下什么是Lua脚本语言。1wh28资讯网——每日最新资讯28at.com

Lua 是一个小巧的脚本语言,由巴西里约热内卢天主教大学(Pontifical Catholic University of Rio de Janeiro)里的一个研究小组于 1993 年开发的。Lua 使用标准 C 语言编写并以源代码形式开放,几乎在所有操作系统和平台上都能编译运行。Lua 脚本可以调用 C/C++ 的函数,也可以被 C/C++ 代码调用,所以 Lua 在应用程序中可以被广泛应用。1wh28资讯网——每日最新资讯28at.com

Lua 的特点如下:1wh28资讯网——每日最新资讯28at.com

  • 小巧灵活:Lua 的核心只有 200K,非常小巧,可以方便地嵌入到应用程序中。Lua 的语法也非常简单,易于学习和使用。
  • 可扩展性:Lua 可以调用 C/C++ 的函数,也可以被 C/C++ 代码调用,所以 Lua 可以很容易地扩展到应用程序的其他部分。
  • 高性能:Lua 的运行效率非常高,可以满足大多数应用程序的需求。

Lua 在游戏开发、Web 开发、嵌入式系统等领域都有广泛的应用。1wh28资讯网——每日最新资讯28at.com

以下是 Lua 的一些典型应用:1wh28资讯网——每日最新资讯28at.com

  • 游戏开发:Lua 常用于游戏中的脚本编写,用于实现游戏的逻辑和特效。
  • Web 开发:Lua 可以用于 Web 开发,用于实现动态页面和游戏。
  • 嵌入式系统:Lua 可以用于嵌入式系统的开发,用于实现控制逻辑和用户界面。

Lua 是一款非常实用的脚本语言,在众多领域都有广泛的应用。1wh28资讯网——每日最新资讯28at.com

2、为什么使用Lua?

1wh28资讯网——每日最新资讯28at.com

  • Redis 实现分布式锁中,获取锁、释放锁为什么要使用 Lua 脚本?
  • 使用 Lua 脚本的主要原因是为了保证操作的原子性,避免出现并发问题或误解锁的情况。
  • 使用 setnx 命令获取锁,然后使用 expire 命令设置过期时间,这两个命令之间可能会发生网络延迟或者其他异常,导致锁没有正确设置过期时间,从而造成死锁。
  • 使用 del 命令释放锁,需要先判断锁是否属于当前客户端,否则可能会误解其他客户端的锁。

使用 Lua 脚本可以将判断和删除锁的操作合并为一个原子操作,避免了这些问题。Lua 脚本在 Redis 服务器端执行,不会受到网络延迟或者客户端故障的影响,也不会被其他命令打断,因此可以保证操作的原子性。1wh28资讯网——每日最新资讯28at.com

  • 为什么说 Redis 命令没有原子性?
  • Redis 命令本身是单线程执行的,所以单个命令是具有原子性的。
  • 但是如果要实现分布式锁的功能,通常需要多个命令组合起来执行,例如 setnx + expire 或者 get + del。
  • 这些命令组合在执行过程中可能会被其他客户端发送的命令打断,导致数据不一致或者逻辑错误。

因此,Redis 命令没有原子性是指多个命令组合起来执行时没有原子性。1wh28资讯网——每日最新资讯28at.com

以下是使用 Lua 脚本实现分布式锁的示例:1wh28资讯网——每日最新资讯28at.com

-- 获取锁function acquire_lock(key, uuid, timeout)  local value = redis.call("GET", key)  if value == nil then    redis.call("SET", key, uuid, "NX", "PX", timeout)    return 1  else    return 0  endend-- 释放锁function release_lock(key, uuid)  redis.call("DEL", key)end

上述脚本实现了简单的 SETNX 和 DEL 操作,可以保证同一时刻只有一个客户端可以获取到锁。1wh28资讯网——每日最新资讯28at.com

在实际使用中,可以根据具体的业务场景来调整 Lua 脚本的实现。1wh28资讯网——每日最新资讯28at.com

本文链接:http://www.28at.com/showinfo-26-19895-0.html面试官必问的分布式锁面试题,你答得上来吗?

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com

上一篇: 给正在使用Lombok的朋友一些建议

下一篇: 你可能听说过雪花算法

标签:
  • 热门焦点
  • MIX Fold3包装盒泄露 新机本月登场

    MIX Fold3包装盒泄露 新机本月登场

    小米的全新折叠屏旗舰MIX Fold3将于本月发布,近日该机的真机包装盒在网上泄露。从图上来看,新的MIX Fold3包装盒在外观设计方面延续了之前的方案,变化不大,这也是目前小米旗舰
  • 石头自清洁扫拖机器人G10S评测:多年黑科技集大成之作 懒人终极福音

    石头自清洁扫拖机器人G10S评测:多年黑科技集大成之作 懒人终极福音

    科技圈经常能看到一个词叫“缝合怪”,用来形容那些把好多功能或者外观结合在一起的产品,通常这样的词是贬义词,但如果真的是产品缝合的好、缝合的实用的话,那它就成了中性词,今
  • 企业采用CRM系统的11个好处

    企业采用CRM系统的11个好处

    客户关系管理(CRM)软件可以为企业提供很多的好处,从客户保留到提高生产力。  CRM软件用于企业收集客户互动,以改善客户体验和满意度。  CRM软件市场规模如今超过580
  • 十个简单但很有用的Python装饰器

    十个简单但很有用的Python装饰器

    装饰器(Decorators)是Python中一种强大而灵活的功能,用于修改或增强函数或类的行为。装饰器本质上是一个函数,它接受另一个函数或类作为参数,并返回一个新的函数或类。它们通常用
  • 深度探索 Elasticsearch 8.X:function_score 参数解读与实战案例分析

    深度探索 Elasticsearch 8.X:function_score 参数解读与实战案例分析

    在 Elasticsearch 中,function_score 可以让我们在查询的同时对搜索结果进行自定义评分。function_score 提供了一系列的参数和函数让我们可以根据需求灵活地进行设置。近期
  • 10天营收超1亿美元,《星铁》比《原神》差在哪?

    10天营收超1亿美元,《星铁》比《原神》差在哪?

    来源:伯虎财经作者:陈平安即便你没玩过《原神》,你一定听说过的它的大名。恨它的人把《原神》开服那天称作是中国游戏史上最黑暗的一天,有粉丝因为索尼在PS平台上线《原神》,怒而
  • 2纳米决战2025

    2纳米决战2025

    集微网报道 从三强争霸到四雄逐鹿,2nm的厮杀声已然隐约传来。无论是老牌劲旅台积电、三星,还是誓言重回先进制程领先地位的英特尔,甚至初成立不久的新
  • 到手价3099元起!iQOO Neo8 Pro今日首销:安卓性能最强旗舰

    到手价3099元起!iQOO Neo8 Pro今日首销:安卓性能最强旗舰

    5月23日,iQOO如期举行了新品发布会,全新的iQOO Neo8系列也正式与大家见面,包含iQOO Neo8和iQOO Neo8 Pro两个版本,其中标准版搭载高通骁龙8+,而Pro版更
  • 最薄的14英寸游戏笔记本电脑  Alienware X14已可以购买

    最薄的14英寸游戏笔记本电脑 Alienware X14已可以购买

    2022年1月份在国际消费电子展(CES2022)上首次亮相的Alienware新品——Alienware X14现在已经可以购买了,这款笔记本电脑被誉为世界上最薄的 14 英寸游戏笔
Top