ホームページ  >  記事  >  データベース  >  Redis のフラッシュセールシナリオにおけるタイムアウトと売られすぎの問題を解決する方法

Redis のフラッシュセールシナリオにおけるタイムアウトと売られすぎの問題を解決する方法

WBOY
WBOY転載
2023-05-29 09:31:321447ブラウズ

タイムアウト

1. Redis 接続がタイムアウトになる理由

(1) 仮想マシンの構成の問題

リモート接続をテストして Redis 接続が確立されているかどうかを確認するとき成功すると、コンソールに次のエラーが報告される場合があります。
以下に示すように:

Redis のフラッシュセールシナリオにおけるタイムアウトと売られすぎの問題を解決する方法

#コンソールに赤いテキストが表示されるたびに頭が痛くなります。 。 。

コンソールの表示は、接続タイムアウトが失敗の原因であることを意味していると考えられます。
接続失敗の理由は次の 3 つです。

  • Linux のファイアウォールが閉じられていないため、失敗が発生します。

  • redis を開く必要があります。

  • redis.conf のbind 127.0.01 をコメントアウトしてから、保護モードを変更する必要があります。

今後上記の問題が発生した場合は、ご自身で調べてください。

(2) Redis 接続成功時の高同時実行時のタイムアウトをシミュレートします

図に示すように:

Redis のフラッシュセールシナリオにおけるタイムアウトと売られすぎの問題を解決する方法

2. 解決策

MySQL で jdbc を使用すると接続タイムアウトの問題が発生する場合があるため、druid、c3p0 などのデータベース接続プールを使用して問題を解決します。同様に、redis でデータベース接続プールを使用することもできます。
redis サービスへの各接続によって発生する消費量を保存し、接続されたインスタンスを再利用します。

パラメータを使用して接続動作を管理する

メモ帳のコードに直接移動します。

Redis のフラッシュセールシナリオにおけるタイムアウトと売られすぎの問題を解決する方法

リンク プール パラメーター:

  • MaxTotal: pool.getResource() を通じてプールに割り当てることができる jedis インスタンスの数を制御します。 ; 値が -1 の場合、制限がないことを意味します。プールに MaxTotal jedis インスタンスが割り当てられている場合、この時点でのプールのステータスは枯渇しています。

  • maxIdle: プール内のアイドル状態の jedis インスタンスの最大数を制御します;

  • MaxWaitMillis: jedis インスタンスを借用するとき、待機する最大ミリ秒数。待機時間を超過すると、JedisConnectionException が直接スローされます。

  • testOnBorrow: jedis インスタンスを取得するときに接続の可用性を確認する (ping()) かどうか。 if true の場合、取得された jedis インスタンスはすべて利用可能です;

OverSold

1. Flash Kill の過剰販売現象

高同時実行シナリオでは、複数のスレッドが発生します。在庫を同時に更新すると、マイナスの在庫状況が発生します。

写真を見て想像してください:

Redis のフラッシュセールシナリオにおけるタイムアウトと売られすぎの問題を解決する方法

2. 解決策

(1) 楽観的ロックを使用してユーザーを排除し、過剰販売の問題を解決します。

上の図:

Redis のフラッシュセールシナリオにおけるタイムアウトと売られすぎの問題を解決する方法

//增加乐观锁
jedis.watch(qtkey);
 
//3.判断库存
String qtkeystr = jedis.get(qtkey);
if(qtkeystr==null || "".equals(qtkeystr.trim())) {
	System.out.println("未初始化库存");
	jedis.close();
	return false ;
}
 
int qt = Integer.parseInt(qtkeystr);
if(qt<=0) {
	System.err.println("已经秒光");
	jedis.close();
	return false;
}
 
//增加事务
Transaction multi = jedis.multi();
 
//4.减少库存
//jedis.decr(qtkey);
multi.decr(qtkey);
 
//5.加人
//jedis.sadd(usrkey, uid);
multi.sadd(usrkey, uid);
 
//执行事务
List<Object> list = multi.exec();
 
//判断事务提交是否失败
if(list==null || list.size()==0) {
	System.out.println("秒杀失败");
	jedis.close();
	return false;
}
System.err.println("秒杀成功");
jedis.close();	

Redis のフラッシュセールシナリオにおけるタイムアウトと売られすぎの問題を解決する方法

Redis のフラッシュセールシナリオにおけるタイムアウトと売られすぎの問題を解決する方法

##スキームの原理:

(1) ユーザーが購入する際には、監視を通じて在庫を監視しますが、監視後に在庫が変化した場合、例外がキャッチされ、在庫を 1 つ減らす操作は諦められます。

(2) 在庫に変化が監視されておらず、数量が 1 より大きい場合、在庫は 1 つ減らされ、タスクが実行されます。
欠点

Redisがトランザクションを完了しようとすると、トランザクションの失敗により繰り返し再実行が試行される可能性があります

商品の在庫が正しいことを確認することが非常に重要です, しかし、単に WATCH のようなメカニズムを使用するとサーバーに過度の負荷がかかります

(2) reids の watch multi setnx コマンドを使用して実装する
なぜ自分でロックを構築する必要があるのですか?

Redis にロック機能を実装できる同様の SETNX コマンドがありますが、他のロックによって提供されるメカニズムは完全ではありません。

また、setnx には分散ロックの高度な機能がいくつかないため、依然として手動でビルドに渡します。

(1) Redis ロックの作成

Redis では、SETNX コマンドを使用してロックを構築できます: rs.setnx(lock_name, uuid value)

ロックの機能これは、ランダムに生成された 128 ビット UUID をビット キーの値に設定して、他のプロセスによってロックが取得されるのを防ぐことです。

(2) ロックの解除

ロックの削除操作は非常に簡単で、対応するロックのキー値から得られるuuid結果を判断し検証するだけです。

条件を満たしている(uuid値を判断する) delete, rs.delete(lockname)でredis内で削除するだけです
また、他のユーザーが同じロックを保持している場合、uuidが異なるため、他の人のロックは解除されません

(3) ロックが解除できない問題を解決

従来のロックでは、ロックを保持した後にプロセスが突然クラッシュしてロックが解除できなくなり、他のプロセスがロックを保持できなくなり、ロックが解除されなくなるなどの問題もありました。この問題を解決するには、ロックを取得するときにロック タイムアウト機能を追加できます。

以上がRedis のフラッシュセールシナリオにおけるタイムアウトと売られすぎの問題を解決する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はyisu.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。