Redisの総務
Redisのトランザクションは、別のステップでコマンドを実行できます(他のコマンドに挿入することができない、許容ストッパーを順次実行直列化)複数のコマンドを実行し、次の2つの重要な保証を持つことができ:
1、Redisのは、すべてのトランザクションのシリアル化を指令し、次に順序で実行されます。
2及び他のコマンドの実行中に挿入されません、ガッサー挙動を表示させません
これは、EXECコマンドバッファキューを送信する前にバッチ操作に置かれています。
トランザクションの実行を入力するにはEXECコマンドを受信した後、トランザクション任意のコマンドの実行が失敗し、コマンドの残りの部分はまだ実行されています。
トランザクションの実行中に、クライアントから提出された他のコマンド要求は、トランザクションの実行コマンド・シーケンスに挿入されることはありません。
トランザクションを実行するために最初から三つの段階を通過します
(1)开始事务
(2)命令入队
(3)执行事务
Redisのトランザクションは、5つのコマンドを関与しました:
- マルチ:トランザクションを開始のRedisは、ネストされたトランザクションをサポートしていないネストされたMULTIは、コマンドを実行すると、トランザクションの開始コマンドが、コマンドが戻るとOKメッセージ、MULTIはMULTI複数のコマンドを実行し、同じ効果を実行され、Redisのは、単にエラーを返します。メッセージ。
- EXEC:トランザクションを行う、EXECコマンドトランザクション、コマンドシーケンストランザクションコマンドは、応答配列、トランザクションの実行結果に対応するコマンドの内容を返し行う(または楽観的ロックの失敗、等のように、行われていない)されることを提出しました。
- ウォッチ:WATCH楽観的ロックが開始されたコマンド、コマンドキーパラメータ(複数持つことができる)である他のクライアントがこれらのキーを変更する場合は、Redisのは、コマンドWATCHを実行し、クライアントオブジェクトWATCHコマンドとキー仲間を実行しますフラグ楽観的ロックの失敗を設定します。コマンドクライアントは、コマンドを実行する前に、実装MULTI WATCHコマンドことを、トランザクションの開始前に、そうでない場合は、無効な実行、およびエラーメッセージを返しますする必要があります。
- unwatch:現在の楽観的ロックキークライアントオブジェクトをキャンセルするunwatchコマンド、トランザクションのクライアントオブジェクトは、無条件の実装になって提出されます。
- 廃棄:DISCARDコマンドは、トランザクションを終了し、コマンド・シーケンスのすべてを破棄します。
機能的なデザインスパイク
それでは、どのようRedisのスパイク機能との取引を実現するには?答えは、時計を使用して、特定のキーの変更を監視するために見ることで、トランザクションが実行されたときに、他のクライアントが対応し、この値を変更することができれば、楽観的ロック機構に似て実行されていない現在のクライアントのトランザクションにつながります。
:次のようにサンプルコードは
まず、コードを見ていない:
例は10枚のクーポンを持っているために、スパイクの機能を提供するために、より多く奪う超える必要があります。
:まず、キーが0のRedisのNUM値内で提供される
コマンド:SET numの0
MyThreadカテゴリ:
import com.itheima.RedisPoolUtil;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.Transaction;
import java.util.List;
import java.util.UUID;
public class MyThread extends Thread{
@Override
public void run() {
for (int i = 0; i < 10; i++){
Jedis jedis = RedisPoolUtil.getJedis();
String num = jedis.get("num");
int n = Integer.parseInt(num);
if (n < 10){
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
jedis.incr("num");
String name = UUID.randomUUID().toString().replaceAll("-", "");
System.out.println(name + "抢到一张优惠券");
}
}
}
}
主な機能:
public class TestMain {
public static void main(String[] args) {
for (int i = 0; i < 5; i++){
MyThread thread = new MyThread();
thread.start();
}
}
}
RedisPoolUtilカテゴリ:
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
public class RedisPoolUtil {
private static JedisPool pool;
static {
//1、连接池redis pool 基本配置信息
JedisPoolConfig poolConfig=new JedisPoolConfig();
poolConfig.setMaxTotal(5);
poolConfig.setMaxIdle(1);
//其他配置
//2、连接池
String host="192.168.18.132";
int port=6379;
pool=new JedisPool(poolConfig,host,port);
}
public static Jedis getJedis(){
Jedis jedis=pool.getResource();
jedis.auth("root");
return jedis;
}
//关闭连接
public static void close(Jedis jedis){
jedis.close();
}
}
コードが実行されると、それは10枚の以上の個々のグラブクーポンに見出されます。
コードの最適化は、トランザクションを使用して:
さらにウォッチ、次のコードを、Mythredカテゴリを変更しました:
import com.itheima.RedisPoolUtil;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.Transaction;
import java.util.List;
import java.util.UUID;
public class MyThread extends Thread{
@Override
public void run() {
for (int i = 0; i < 10; i++){
// Jedis jedis = RedisConnection.getJedis();
Jedis jedis = RedisPoolUtil.getJedis();
String watch = jedis.watch("num");
String num = jedis.get("num");
int n = Integer.parseInt(num);
if (n < 10){
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
Transaction transaction = jedis.multi();
transaction.incr("num");
List<Object> list = transaction.exec();
String name = UUID.randomUUID().toString().replaceAll("-", "");
if (list == null || list.size() == 0){
System.out.println(watch + "==="+list+"----" + name + "手慢了,抢票失败");
}else {
System.out.println(watch + "==="+list+"----" + name + "抢到一张优惠券");
}
}
}
}
}
テスト結果は、あなたは多くの人々が盗もうとして存在しますが、ことがわかりますが、それでも唯一の10人がつかむことができます。