扫地阿姨看完都学会了!阿里再次定义互联网实战案例,真香

news/2024/7/6 5:27:52

前言

蓦然回首自己做开发已经十年了,这十年中我获得了很多,技术能力、培训、出国、大公司的经历,还有很多很好的朋友。但再仔细一想,这十年中我至少浪费了五年时间,这五年可以足够让自己成长为一个优秀的程序员,可惜我错过了,我用这五年时间和很多程序员一样在困惑和迷茫中找不到出路!

路其实一直都在那里,只是我们看不到而已!

以前我一直被公司和技术牵着走,并不是自己在选择技术,而是不自觉地被推到了这个位置上。想想有多少人对于自己将来要从事的职业和技术类型进行过深入思考和比较呢?当我跳出编码后,我开始思考和程序及程序员职业生涯相关的问题,最后发现,影响我们走入今天的困局的竟然是一些我们常常挂在嘴边的话。

分布式锁的坑

高并发场景下的问题

以下问题不是说在并发不高的场景下不容易出现,只是在高并发场景下出现的概率更高些而已。

性能问题来自于以下两方面:

**①获取锁的时间上。**如果 Redlock 运用在高并发的场景下,存在 N 个 Master 节点,一个一个去请求,耗时会比较长,从而影响性能。

这个好解决,通过上面描述不难发现,从多个节点获取锁的操作并不是一个同步操作,可以是异步操作,这样可以多个节点同时获取。

即使是并行处理的,还是得预估好获取锁的时间,保证锁的 TTL>获取锁的时间+任务处理时间。

**②被加锁的资源太大。**加锁的方案本身就是会为了正确性而牺牲并发的,牺牲和资源大小成正比,这个时候可以考虑对资源做拆分。

拆分的方式有如下两种:

**①从业务上将锁住的资源拆分成多段,每段分开加锁。**比如,我要对一个商户做若干个操作,操作前要锁住这个商户,这时我可以将若干个操作拆成多个独立的步骤分开加锁,提高并发。

**②用分桶的思想,将一个资源拆分成多个桶,一个加锁失败立即尝试下一个。**比如批量任务处理的场景,要处理 200w 个商户的任务,为了提高处理速度,用多个线程,每个线程取 100 个商户处理,就得给这 100 个商户加锁。

如果不加处理,很难保证同一时刻两个线程加锁的商户没有重叠,这时可以按一个维度。

比如某个标签,对商户进行分桶,然后一个任务处理一个分桶,处理完这个分桶再处理下一个分桶,减少竞争。

**重试的问题:**无论是简单实现还是 Redlock 实现,都会有重试的逻辑。

如果直接按上面的算法实现,是会存在多个 Client 几乎在同一时刻获取同一个锁,然后每个 Client 都锁住了部分节点,但是没有一个 Client 获取大多数节点的情况。

解决的方案也很常见,在重试的时候让多个节点错开,错开的方式就是在重试时间中加一个随机时间。这样并不能根治这个问题,但是可以有效缓解问题,亲试有效。

节点宕机

对于单 Master 节点且没有做持久化的场景,宕机就挂了,这个就必须在实现上支持重复操作,自己做好幂等。对于多 Master 的场景,比如 Redlock,我们来看这样一个场景:

  • 假设有 5 个 Redis 的节点:A、B、C、D、E,没有做持久化。

  • Client1 从 A、B、C 这3 个节点获取锁成功,那么 client1 获取锁成功。

  • 节点 C 挂了。

  • Client2 从 C、D、E 获取锁成功,client2 也获取锁成功,那么在同一时刻 Client1 和 Client2 同时获取锁,Redlock 被玩坏了。

怎么解决呢?最容易想到的方案是打开持久化。持久化可以做到持久化每一条 Redis 命令,但这对性能影响会很大,一般不会采用,如果不采用这种方式,在节点挂的时候肯定会损失小部分的数据,可能我们的锁就在其中。

另一个方案是延迟启动。就是一个节点挂了修复后,不立即加入,而是等待一段时间再加入,等待时间要大于宕机那一刻所有锁的最大 TTL。

但这个方案依然不能解决问题,如果在上述步骤 3 中 B 和 C 都挂了呢,那么只剩 A、D、E 三个节点,从 D 和 E 获取锁成功就可以了,还是会出问题。

那么只能增加 Master 节点的总量,缓解这个问题了。增加 Master 节点会提高稳定性,但是也增加了成本,需要在两者之间权衡。

任务执行时间超过锁的 TTL

之前产线上出现过因为网络延迟导致任务的执行时间远超预期,锁过期,被多个线程执行的情况。

这个问题是所有分布式锁都要面临的问题,包括基于 Zookeeper 和 DB 实现的分布式锁,这是锁过期了和 Client 不知道锁过期了之间的矛盾。

在加锁的时候,我们一般都会给一个锁的 TTL,这是为了防止加锁后 Client 宕机,锁无法被释放的问题。

但是所有这种姿势的用法都会面临同一个问题,就是没法保证 Client 的执行时间一定小于锁的 TTL。

虽然大多数程序员都会乐观的认为这种情况不可能发生,我也曾经这么认为,直到被现实一次又一次的打脸。

Martin Kleppmann 也质疑过这一点,这里直接用他的图:

  • Client1 获取到锁。

  • Client1 开始任务,然后发生了 STW 的 GC,时间超过了锁的过期时间。

  • Client2 获取到锁,开始了任务。

  • Client1 的 GC 结束,继续任务,这个时候 Client1 和 Client2 都认为自己获取了锁,都会处理任务,从而发生错误。

Martin Kleppmann 举的是 GC 的例子,我碰到的是网络延迟的情况。不管是哪种情况,不可否认的是这种情况无法避免,一旦出现很容易懵逼。

如何解决呢?一种解决方案是不设置 TTL,而是在获取锁成功后,给锁加一个 watchdog,watchdog 会起一个定时任务,在锁没有被释放且快要过期的时候会续期。

最后

面试题文档来啦,内容很多,485页!

由于笔记的内容太多,没办法全部展示出来,下面只截取部分内容展示。有想获取完整版笔记的朋友,点赞后点击这里免费领取哦

1111道Java工程师必问面试题

MyBatis 27题 + ZooKeeper 25题 + Dubbo 30题:

Elasticsearch 24 题 +Memcached + Redis 40题:

Spring 26 题+ 微服务 27题+ Linux 45题:

Java面试题合集:

543360992)]

Spring 26 题+ 微服务 27题+ Linux 45题:

[外链图片转存中…(img-IlYPfWit-1618543360994)]

Java面试题合集:


http://www.niftyadmin.cn/n/3647674.html

相关文章

程序员必知必会之maillist篇

程序员必知必会之maillist篇本文最初由恋花蝶发表于http://blog.csdn.net/lanphaday,可以随意转载,但未经同意不得增删修改,转载应保留本声明,否则追究责任。题注:因为我参与了若干个maillist,眼看一个一个…

挑战华为社招:不会真有人觉得mybatis很难学吧?经验分享

前言 今天来带大家研究一下Linux内存管理。对于精通 CURD 的业务同学,内存管理好像离我们很远,但这个知识点虽然冷门(估计很多人学完根本就没机会用上)但绝对是基础中的基础,这就像武侠中的内功修炼,学完之…

OpenMP与C++:事半功倍地获得多线程的好处(下)

声明:本文并未获得翻译授权,本人翻译这篇文章仅用于学习和研究之用,任何人不得在未经授权之前将原文和译文用以商业用途.因版权原因,暂不建议转载本文.本文发表于http://blog.csdn.net/lanphaday请保留本文完整本文发表于2005年第10期的,英文版本地址:http://msdn.microsoft.co…

[python]有限状态机(FSM)简单实现

本文发表于恋花蝶的博客http://blog.csdn.net/lanphaday,欢迎转载,但必须保留文章内容完整且包含本声明。违者必究。 [python]有限状态机(FSM)简单实现简述有限状态机(以下用FSM指代)是一种算法思想&#x…

掌握这6大技能体系:这次被它搞惨了!分享一点面试小经验

前言 提到插件,相信大家都知道,插件的存在主要是用来改变或者增强原有的功能,MyBatis中也一样。然而如果我们对MyBatis的工作原理不是很清楚的话,最好不要轻易使用插件,否则的话如果因为使用插件导致了底层工作逻辑被…

Python温故

Python温故上周五的时候,在公司做了一个关于python的交流会,我花了两天时间,写了48页ppt作为大纳。会后咨询参会的同事,都说效果不错,所以就大胆地把ppt放到blog上来了。这些ppt主要说的是python的基础知识&#xff0c…

推荐学习!Redis宕机数据丢失解决方案,赶紧收藏备战金三银四!

前言 这期我想写很久了,但是因为时间的原因一直拖到了现在,我以为一两天就写完了,结果从构思到整理资料,再到写出来用了差不多一周的时间吧。 你们也知道作者一直都是创作鬼才来的,所以我肯定不会一本正经的写&#…

[2007技术英雄会]行食人景情

[2007技术英雄会]行食人景情行4月5日。早晨。已经很久没有这么早起了,比平时整整早了一个小时。微雨的广州,春寒料峭。去到广运楼坐空港快线时,远远地看着一部车在雨中远去。只好坐下一班车,10点出发。多等了半个小时。到了机场&a…