粉丝46.8万获赞513.4万


今天面了个四年后端,我问他分布式锁怎么实现,他很自信,用 reddis 的 set next 加个过期时间,保证只有一个县城能拿到锁。我点点头,接着问了个经典场景,好,假设你们用这个方法做了一个用户余额扣减的分布式锁, 县城 a 拿到锁后,开始执行扣款逻辑。但就在此时, jvm 触发了负 gc, 停顿了十秒, 而 radis 里的锁因为过期时间到了,自动释放了。县城 b 看到锁没了,也拿到了锁,开始执行扣款。 然后县城 a 的 g、 c 结束,继续执行后面的代码。问题来了,这时候会发生什么?他愣了一下,这县城 a 不知道锁已经没了,他会继续执行扣款,导致重复扣款。我追问,对用户被扣了两次钱,你现在收到客诉,怎么跟财务解释?更致命的是,你怎么从根本上解决这种锁失效问题? 它开始吱吱呜呜,可以加大过期时间,或者用 red soon 面试直接结束了。 这正是分布式锁最经典的失效陷阱,纽塞奈克斯解决了护翅,却没解决持有锁的现成在锁过期后继续执行的问题。 如果你也对问题发出,我整理了让面试官沉默的大场必考题库,包含 jvm 夺命连环问 spring 灵魂八谷高并发必杀场景, radis 深度陷阱,点个赞,留个六六六,直接暴走 nice! 为什么这个问题能筛出高手?因为他考察的不是会不会用 set next, 而是有没有深入理解分布式所在真实生产环境下的所有失效模式。 一个能真正扛住生产压力的分布式锁方案,必须建立三层防御,第一层,原子性与过期时间。 set key value n x x seconds, 这是底线,千万不要用 set n x 加 expire 两步操作,那不是分布式锁,是给自己挖坑, 必须在一条命令里完成枷锁和设置过期时间。第二层,锁续期与守护现成 watchdog 自动续期,这是 redison 的 核心机制,拿到锁的同时,启动一个后台现成,每隔三分之一过期时间就检查一次, 如果现成还在执行,就自动延长锁的过期时间。这样即使业务执行时间超过预期,锁也不会提前释放。 合理设置过期时间,根据业务预估执行时间设置。但永远要假设业务可能被 g c 打断,续期机制必须存在。第三层,谁枷锁谁释放。唯一标识叫验 value, 不 能是简单的一,必须是局。唯一的标识 释放时先 get 判断是不是自己的锁,再用录艾脚本原子删除,防止误删。别人的锁可重入,支持同一个县城多次获取同一把锁,需要用计数器实现,可重入,否则自己把自己锁死。 所以这道题考的是什么?它考的是你有没有从会用命令升级为理解分布式系统持续的深度思维。普通开发觉得 set nex 就 能解决一切。而高级工程师知道,在不可预测的 g c 网络时钟面前,你的锁必须要有自我保护和自动续期的能力,否则一次 g c 就是 一次资金事故。你们线上有没有因为分布式锁出过事故?是锁过期了还是误伤了别人的锁?来聊聊。

有很多人都没搞懂这个虚幻武器要怎么玩,怎么触发,简单来说就是这个虚幻武器可以让你的技能附带一个零点伤害的普通攻击,而英雄联盟里面有一些技能还有一些装备特性,只能靠平 a 去触发。 如果你有了虚幻武器之后,就可以直接用技能触发了他,比如机器人的 e, 他 在强化下一次普攻,可以让对方把对方给击飞。 如果你有了循环武器的时候,你开 e 再开 q, 那 么 q 到对方就不是把对方给抓过来了,而是把对方给远程击飞一下。所以玩机器人的时候一定要记住,先 q 后 e, 不 然你拉不回来。还有一样的就是开完 e 之后,机器人大招如果大到了对方,也会把对方给击飞起来, 同样的狗头也是狗头,正常来说要把自己的 q 打到对方脸上,你要走到对方面前,这对于狗头玩家是非常的不友好。但如果你有了循环武器,那么你把 q 打开的时候,你只要把那个 e 能打到对方脸上,那么 e 直接的可以把你的 q 的 伤害同样打到对方脸上,不需要再走过去了,是不是很好用? 还有一些被动,还比如说维恩 w 的 被动,还有卡莎的被动,这打印记的对吧?比如说你要维恩打三环,你要 a 三下,或者是 a a e, 但如果你有了虚幻武器之后,你只需 a 瞬间放个 e, 那 个 e 能再触发一层,那个平 a, 立马三环啊,安全好用。

家人们谁懂啊,做后端的谁没经历过这种暴击?系统好好的跑着,突然卡死了好几秒,监控曲线直接断崖式的下跌,用户疯狂的去投诉炸屏,老板在群里疯狂的去艾特你不用猜,十有八九是负极 c 这个性能杀手出动了 很多的牛马兄弟,只知道内存满了就负极 c 这句话啊,太笼统了。今天呢,咱们就把 gvm 的 内部触发负极 c 的 四道警报拆给大家听,听懂了你就能提前的去进行设防,少背锅。先跟新手兄弟们说句大实话啊, 负极 c 就是 gvm 放出来的终极的清理大招,一旦放出来,整个应用基本上它就停摆了,所有的请求都得排队等待,卡死的几秒,它就是这么来的,知道吧,而它出动全靠这四道警报去拉响。 首先第一道警报最经典的也是最常见的,我们的老年代空间不足,这是负极 c 的 头号触发原因,年轻代的对象熬过了几次我们的 minor c, 也就是 young c 之后啊,然后呢,他就会去进行一个升级,到老年代 去进行一个养老,要是老年代呢,也被塞得满满当当。 g m 没辙了,只能拉响最高级别的警报,就是启动负极 c, 把整个堆,整个堆就相当于年轻代老年代原空间彻底的去清理一遍, 相当于仓库的主货区爆仓了,只能全员停工盘点,但是你以为只有老年怠慢了才会触发吗?太天真了。第二道警报其实就藏在原空间里面, 很多的公司升级到 g d k 八之后啊,用原空间替代了我们的永久代,而这玩意呢,默认是按需分配的,看似是无限用,可你如果要是在代码当中疯狂地、动态地去生成类, 比如说搞大量的反射啊,用 c g lab 去做代理啊,就很容易把原空间给撑爆了, 照样会触发我们的负 g c。 这就是很多系统升级之后莫名卡顿的根源,排查半天可能都找不到原因。 第三道警报,更隐蔽,更坑人啊,就是我们所谓的担保失败。每次 miner g c 之前呢, gvm 都会先查老年代的剩余空间 够不够,装下年轻代理所有的对象啊。当然,这是最悲观的情况,要是剩余空间空间不够就说明啊, 呃,比如说,就算 miner g c 丸,存活的对象也可能塞不进老年袋,这个时候 gvm 就 会直接摆烂 miner g c 直接不搞了,直接提前去拉起我们的副 g c, 相当于一一批我们所谓的新货要入库, 发现临时货区根本装不下最坏的情况,那我直接干脆停工大整顿啊。而第四道警报呢,纯纯就是我们人货啊,手工拉响的。 比如说,像有同学啊,有人在代码里面去瞎写什么 system 点 g c, 或者在 g m x 控制台用 j start 命令手动去进行触发,重点去提醒啊。这只是个建议啊,因为 gvm 它其实是不一定听的, 但是这个代码呢,他很多的时候会来帮倒忙,本来系统好好的,一手动触发直接卡死,就像老板 不管仓库忙不忙,突然冲进来喊,现在立刻站起来盘点,马上啊,给大家去打个通俗的比方啊, 如果把这四道警报想象成仓库管理系统啊,老年代满了,它其实就等于主仓库报仓,全员停工,彻底清点原空间。满了呢,就等于仓库的货物名册写满了, 不不换新的册子,新货根根本没办法登进入库。而担保失败呢,就相当于预估一批新货装不下临时的货区,干脆直接停工提前整顿。而手手动触发呢,相当于老板乱指挥,强行要求盘点,不管业务的死活。 所以啊,各位同学,你们看啊,负极 c 它的本质就是 gvm 在 内存管理搞不定,陷入全面危机的时候,被迫搞的,叫做大局止损的一个策略,代价就是整个应用停摆,用户体验直接崩溃。 你们公司的系统遇到过负极 c 频繁的这样的坑吗?是哪道警报触发的呢?评论区分享你排查的血泪史, 比如说调优过哪些参数?关注我,下期直接上干货,教你怎么去设置关键参数,把这四道警报的引线全部拆掉,跟负极 c 卡顿,彻底地说再见,说拜拜!好吧!

如果你的电脑突然黑屏了,只剩一个鼠标,千万不要重启电脑,这样你的数据都会丢失。我们只需要按住 ctrl shift 加微软件, 加这个 b, 这个是重置显卡驱动的快捷键,摁一下电脑会滴的响一声,我们再看一下电脑已经正常了。