分散ロック・プログラム・セグメントは、あなたが何を知っていますかロックされましたか?

背景紹介

まず、この質問の背景を見てみましょうか?

私にはいくつかのインタビューのうち友人前の時間、その後、話に一日が言う:良い、国内の電力供給会社があり、インタビュアーは論外彼にシーンを与えます:

もしオーダー時に、売られ過ぎ銘柄を防ぐために、分散ロックと、それは、このシナリオに対処するための分散ロックの高い同時実行を最適化する方法を、第二の高同時実行シナリオごとの受注数千のでしょうか?

彼はアイデアが何もしないしなかったので、彼は、それに答えていないと述べました。実際に、私はインタビューの質問を聞いていたし、私は候補者にインタビューした場合、それはより大きな範囲を与える必要がありますので、私の心は、ビット平均を感じます。

例えば、並行性の高いシナリオは売られ過ぎのソリューション、利点、および様々なプログラムと実務慣行の欠点をスパイクの下で学生がチャットの電力会社の在庫をインタビューさせ、その後、分散ロックこのトピックに話します。

在庫が問題に売られているので、このような悲観的ロック、分散ロック、オプティミスティックロック、直列化キューなど、多くの技術的な解決策がある、アトミック操作をRedisの、そしてそれに。

:それは兄弟在庫が売られ過ぎ解決するために、分散ロックで死亡したインタビュアーを定義するので、しかし、私はそれが尋ねるべき点だと思い並行性の高いシナリオでの分散並行処理ロックのパフォーマンスを最適化する方法。

私は、生産の実際の到着時刻ので、インタビュアーの質問の角度が許容されると考え、分散ロックデータの正確性を確保するために、この事は、彼は少し弱い自然な同時能力でした。

他のプロジェクトでは、確かに高い同時実行のシナリオの下でロックの最適化を配布しなかった私はちょうど自分のシーンの前なので、この友人が顔の質問に、来て高い同時実行性の最適化、分散ロックのみんなのアイデアであることを起こる取りますチャット。

ストック売られ過ぎ、それをどうやっているのですか?

あなたは何を意味するかのように見てみましょうが、ロックを配布されていない株式は、いわゆる電気の供給を売られ過ぎ?我々は、次のチャートを見て:
IMG
この図は、注文システムへの要求をした、それぞれ、異なるユーザはまた、iphoneの10セットを購入する必要があり、順序は両方のマシンでシステムを展開すると仮定して、実際には非常に明確です。

次にチェックデータベースに各注文システムインスタンスは、現在のiPhoneの在庫が12個の単位です。

二人の兄弟と偉大な外観、音楽、在庫の12セットがああを購入する10の数よりも大きいです!

これにより、システムの各インスタンスは、10を控除し、SQLデータベースの注文、在庫との順序を送信する、請求局2へストック12から控除、在庫から差し引かさらに2 -8台湾。

今以上、マイナス在庫がありました!涙がああ、ああ何20 iphoneセンド二人のユーザーを走っていません!これが行うことができます。

株式売られ過ぎの問題を解決する方法とロックを分散?

**私たちは、売られ過ぎ銘柄が行う問題を解決するためにどのようにロックを分散しましたか?**実際には非常に単純な、我々は分散ロックの原則の実現を言った最後の時間を思い出します。

唯一のクライアントには、次のビジネスロジックを実行するために取得するには、ロックを獲得するためにロックを試みる無限に待機中のロックを取得するためのキー、同時に1つのクライアントだけ、他のクライアント行くとロック。
IMG
コードは、おそらくそのように上回っている、そして今、私たちは、分析しなければならない理由を避け株式は売られ過ぎていますか?
IMG
我々はすぐにクリアし、数字を読んでするには、上記の手順に従うことができます。

あなたは成功し、1つだけのインスタンス、彼は在庫を確認することができ、分散ロックを追加し、在庫の妥当性を判断する、注文を在庫控除し、ロックを解除することができ、注文システムのインスタンスが1つしかない、チャートから見ることができます。

ロック、ロックするためにシステムの他の例を解放した後、その後、在庫、在庫を確認し、彼らが購入することができない在庫の不足の2つだけ、次の単一故障を発見しました。在庫は-8として控除されることはありません。

問題売られ過ぎ銘柄を解決することができ、他の解決策はありませんか?

もちろんああがあります!たとえば、について悲観的ロック、分散ロック、オプティミスティックロック、直列化キュー、キュー非同期分散し、Redisのアトミック操作など、プログラムの多くは、我々は売られ過ぎている株式は、最適化メカニズムの独自のセットを持っています。

私が前に言ったようしかし、この記事では、株式チャットソリューションは売られ過ぎ、分散ロックの同時最適化をしませお話しますので、株価はようやくビジネスシナリオを売られ過ぎ

私は、物品、電気の供給業者の株式売られ過ぎの問題の解決策についての話を書く機会を持つことになり、この記事では、分散ロックの同時実行性の最適化に焦点を当てることで、私は見ていなかったいくつかの兄弟を避けるために、あなたはこの意図や背景を理解してほしいですはっきりとTucao。

パブリック数背景ゲストブックは私と一緒にそれを議論し、あなたが記事の内容に異議を持っていることを示唆している場合でも、技術はより多くの交流、オープンなアイデア、衝突の考え方にあります。

高並行性のシナリオの下で分散ロック・プログラム

好,现在我们来看看,分布式锁的方案在高并发场景下有什么问题?

问题很大啊!兄弟,不知道你看出来了没有。分布式锁一旦加了之后,对同一个商品的下单请求,会导致所有客户端都必须对同一个商品的库存锁key进行加锁。

比如,对iphone这个商品的下单,都必对“iphone_stock”这个锁key来加锁。这样会导致对同一个商品的下单请求,就必须串行化,一个接一个的处理。

大家再回去对照上面的图反复看一下,应该能想明白这个问题。

假设加锁之后,释放锁之前,查库存 -> 创建订单 -> 扣减库存,这个过程性能很高吧,算他全过程20毫秒,这应该不错了。

那么1秒是1000毫秒,只能容纳50个对这个商品的请求依次串行完成处理。

比如一秒钟来50个请求,都是对iphone下单的,那么每个请求处理20毫秒,一个一个来,最后1000毫秒正好处理完50个请求。

大家看一眼下面的图,加深一下感觉。
IMG
所以看到这里,大家起码也明白了,简单的使用分布式锁来处理库存超卖问题,存在什么缺陷。

缺陷就是同一个商品多用户同时下单的时候,会基于分布式锁串行化处理,导致没法同时处理同一个商品的大量下单的请求。

这种方案,要是应对那种低并发、无秒杀场景的普通小电商系统,可能还可以接受。

因为如果并发量很低,每秒就不到10个请求,没有瞬时高并发秒杀单个商品的场景的话,其实也很少会对同一个商品在一秒内瞬间下1000个订单,因为小电商系统没那场景。

如何对分布式锁进行高并发优化?

好了,终于引入正题了,那么现在怎么办呢?

面试官说,我现在就卡死,库存超卖就是用分布式锁来解决,而且一秒对一个iphone下上千订单,怎么优化?

现在按照刚才的计算,你一秒钟只能处理针对iphone的50个订单。

其实说出来也很简单,相信很多人看过java里的ConcurrentHashMap的源码和底层原理,应该知道里面的核心思路,就是分段加锁

把数据分成很多个段,每个段是一个单独的锁,所以多个线程过来并发修改数据的时候,可以并发的修改不同段的数据。不至于说,同一时间只能有一个线程独占修改ConcurrentHashMap中的数据。

另外,Java 8中新增了一个LongAdder类,也是针对Java 7以前的AtomicLong进行的优化,解决的是CAS类操作在高并发场景下,使用乐观锁思路,会导致大量线程长时间重复循环。

LongAdder中也是采用了类似的分段CAS操作,失败则自动迁移到下一个分段进行CAS的思路。

其实分布式锁的优化思路也是类似的,之前我们是在另外一个业务场景下落地了这个方案到生产中,不是在库存超卖问题里用的。

但是库存超卖这个业务场景不错,很容易理解,所以我们就用这个场景来说一下。大家看看下面的图:
IMG
其实这就是分段加锁。你想,假如你现在iphone有1000个库存,那么你完全可以给拆成20个库存段,要是你愿意,可以在数据库的表里建20个库存字段,比如stock_01,stock_02,类似这样的,也可以在redis之类的地方放20个库存key。

总之,就是把你的1000件库存给他拆开,每个库存段是50件库存,比如stock_01对应50件库存,stock_02对应50件库存。

接着,每秒1000个请求过来了,好!此时其实可以是自己写一个简单的随机算法,每个请求都是随机在20个分段库存里,选择一个进行加锁。

bingo!这样就好了,同时可以有最多20个下单请求一起执行,每个下单请求锁了一个库存分段,然后在业务逻辑里面,就对数据库或者是Redis中的那个分段库存进行操作即可,包括查库存 -> 判断库存是否充足 -> 扣减库存。

这相当于什么呢?相当于一个20毫秒,可以并发处理掉20个下单请求,那么1秒,也就可以依次处理掉20 * 50 = 1000个对iphone的下单请求了。

一旦对某个数据做了分段处理之后,有一个坑大家一定要注意:就是如果某个下单请求,咔嚓加锁,然后发现这个分段库存里的库存不足了,此时咋办?

这时你得自动释放锁,然后立马换下一个分段库存,再次尝试加锁后尝试处理。这个过程一定要实现。

分布式锁并发优化方案有没有什么不足?

不足肯定是有的,最大的不足,大家发现没有,很不方便啊!实现太复杂了。

  • 首先,你得对一个数据分段存储,一个库存字段本来好好的,现在要分为20个分段库存字段;
  • 其次,你在每次处理库存的时候,还得自己写随机算法,随机挑选一个分段来处理;
  • 最后,如果某个分段中的数据不足了,你还得自动切换到下一个分段数据去处理。

这个过程都是要手动写代码实现的,还是有点工作量,挺麻烦的。

不过我们确实在一些业务场景里,因为用到了分布式锁,然后又必须要进行锁并发的优化,又进一步用到了分段加锁的技术方案,效果当然是很好的了,一下子并发性能可以增长几十倍。

该优化方案的后续改进

以我们本文所说的库存超卖场景为例,你要是这么玩,会把自己搞的很痛苦!

再次强调,我们这里的库存超卖场景,仅仅只是作为演示场景而已,以后有机会,再单独聊聊高并发秒杀系统架构下的库存超卖的其他解决方案。

上篇文章的补充说明

本文最后做个说明,笔者收到一些朋友留言,说有朋友在技术群里看到上篇文章之后,吐槽了一通上一篇文章(《拜托,面试请不要再问我Redis分布式锁的实现原理》),说是那个Redis分布式锁的实现原理把人给带歪了。

在这儿得郑重说明一下,上篇文章,明确说明了是Redisson那个开源框架对Redis锁的实现原理,并不是我个人YY出来的那一套原理。

実際Redissonに優れたオープンソースのフレームワークとして、私はいくつかの欠点があるが、彼は、OKである全体的なロックの達成に配布さだと思いますが、本番環境で使用可能です。

また、いくつかの兄弟は、著者のRedisの公式ウェブサイトで分散ロックを達成するためにさまざまなアイデアを与えることを感じることがあり、Tucaoので、作者の公式ウェブサイトを追跡するのRedisは、アイデアの実現にロックを配布しました。

実際に、私は、Redisの公式ウェブサイト与えられただけでRedisのは、それをロックし、分散思考達成するために、ということを指摘しなければならない心に留めておく、という考えだということ!技術的なプログラム床本番環境でのアイデアの間のギャップです。

例えば、分散ロックRedisの公式ウェブサイトは、アイデアの実現を与え、自動更新、分散ロック機構に与えられていない、相互排他のロック機構を待ってから、再入可能ロックのロック機構をロックを解除します。しかし、分散ロックを実装するためのRedissonフレームワークは、メカニズムのセットを達成することです。

繰り返しだから、それはあなたが望むなら、あなたはアイデア分散ロック・アウトの生産レベルを達成するために、独自の公式ウェブサイトをのRedisに基づくことができ、ちょうど思考です。

アルゴリズムRedisの公式サイト与えられた加算RedLock、私が個人的に生産に使用していない尊敬されています。

問題のいくつかの論理アルゴリズムのセットがあるかもしれないので、外国で論争を巻き起こしている彼のRedLockアルゴリズムは公式サイトで論争を引き起こしたので、でもRedisの作者自身が記事を与え、もちろん、彼は同意することはほとんどありません。

しかし、この事、あなたの混乱行く国民は、合理的な女性と彼女は言いました。詳細については、オリジナルに参加する公式サイトを参照してください。

マーティンKleppmannはここRedlockを分析しました。私は分析に反対し、ここで彼の分析に私の返事を掲載しました。

公開された107元の記事 ウォン称賛14 ビュー40000 +

おすすめ

転載: blog.csdn.net/belongtocode/article/details/103395802