問題の説明: e コマース プラットフォームが新しい携帯電話を発売します。 1 人は 2 ユニットの購入に制限されており、同時実行は 10 W であることが予想されます。この場合、在庫が差し引かれると、売れすぎないことが保証されます。
#解決策 1
データベース ロック メカニズムを使用してロックを記録し、操作を行います
SELECT * from goods where ID =1 for update; UPDATE goods set stock = stock - 1;
排他的ロックを使用して並列操作を直列操作に変換しますが、このソリューションのパフォーマンスとユーザー エクスペリエンスは劣ります
解決策 2
redis を使用して分散ロックを実装します。
setnx コマンドを使用します (キーが存在しない場合は値を作成して設定し、1 を返します。キーが存在する場合は 0 を返します)ビジネス ロジックでは、このような計画を通じて操作できます
Jedis client = jedisPool.getResource(); while(client.setnx("lock",String.valueOf(System.currentTimeMillis())) == 0){ Thread.sleep(10000); } //coding here client.del("lock")
高度な計画 2
デッドロックの問題を考慮すると、つまり、既製の A がロックを取得した後、このコマンドはロックのタイムスタンプを取得し、それを使用してタイムアウトを決定し、ロックを解放します。
Long TIMEOUT_SECOUND = 120000L; Jedis client = jedisPool.getResource(); while(client.setnx("lock",String.valueOf(System.currentTimeMillis())) == 0){ Long lockTime = Long.valueOf(client.get("lock")); if (lockTime!=null && System.currentTimeMillis() > lockTime+TIMEOUT_SECOUND) { client.del("lock"); } Thread.sleep(10000); } ........................... ........................... client.del("lock")
オプション 2 の機能強化
オプション 2 のアルゴリズムでは、タイムアウト以外の状況でロックが可能なことを保証するために、ロックされたスレッドを解放するには、スレッド署名
Long TIMEOUT_SECOUND = 120000L; String featureCode = "machine01"; Jedis client = jedisPool.getResource(); while(client.setnx("lock",featureCode+":"+String.valueOf(System.currentTimeMillis())) == 0){ Long lockTime = Long.valueOf(client.get("lock").substring(9)); if (lockTime!=null && System.currentTimeMillis() > lockTime+TIMEOUT_SECOUND) { client.del("lock"); } Thread.sleep(10000); } ........................... ........................... if (featureCode.equals(client.get("lock").substring(0, 8))) { client.del("lock"); }
を入力できます。 Redis 関連の技術記事の詳細については、Redis チュートリアル 列にアクセスして学習してください。
以上がRedis が分散トランザクションを実装する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。