redisロックは分布式番号取りの構想を実現する
21786 ワード
最近分布式ロックというものを見て、他の大神の説に基づいて、いくつかの基本的な実現方法をまとめました.
1、データベース楽観ロック
2、redis錠
3、zookeeper
暇なときは、比較的簡単に実現できるredisロックを書きました.説明が苦手なので、直接コードを貼りましょう.
1、mavenは関連jarパッケージを持ち込む
2、ロックの取得とロックの解除に関するコード
3、簡単なデータ記録センターで、一括で順序番号を取得する方法を提供する
4、1つの補充流水番号と日付が完全な流水番号を生成する補助類
5、呼び出しクライアントを作成し、ここではスレッドで表す
6、Testクラスの作成
出力結果:
Thread-6スピンThread-2スピンThread-5スピンThread-0スピンThread-4スピンThread-8スピンThread-7スピンレリーズロック成功Thread-3配列番号DataRange{start=0,end=499}レリーズロック成功Thread-3配列番号DataRange{start=500,end=999}レリーズロック成功Thread-3配列番号DataRange{start=1000,end=1499}リリースロック成功Thread-3取得配列番号DataRange{start=1500,end=1999}リリースロック成功Thread-3取得配列番号DataRange{start=2000,end=2499}Thread-3スピンリリースロック成功Thread-1取得配列番号DataRange{start=2500,end=2999}リリースロック成功Thread-1取得配列番号DataRange{start=3000,end=3499}リリースロック成功Thread-1取得配列番号DataRange{start=3500,end=3999}Thread-1スピンレリーズロック成功Thread-9配列番号取得DataRange{start=4000,end=4499}レリーズロック成功Thread-9配列番号取得DataRange{start=4500,end=4999}レリーズロック成功Thread-9配列番号取得DataRange{start=5000,end=5499}レリーズロック成功Thread-9配列番号取得Datange{start=5500,end=5999}解放ロック成功Thread-9配列番号DataRange{start=6000,end=6499}解放ロック成功Thread-9配列番号DataRange{start=6500,end=6999}解放ロック成功Thread-9配列番号DataRange{start=7000,end=7499}解放ロック成功Thread-9配列番号DataRange{start=7500,end=7999}解放ロック成功Thread-9配列番号DataRange{start=8000,end=8499}リリースロック成功Thread-9取得配列番号DataRange{start=8500,end=8999}Thread-2スピン中Thread-5スピンリリースロック成功Thread-6取得配列番号DataRange{start=9000,end=9499}リリースロック成功Thread-6取得配列番号DataRange{start=9500,end=999}リリースロック成功Thread-6取得配列番号DataRange{start=10000,end=10499}解放ロック成功Thread-6配列番号DataRange{start=10500,end=10999}Thread-4正スピンThread-8正スピンThread-6正スピン解放ロック成功Thread-0配列番号DataRange{start=1000,end=1499}解放ロック成功Thread-0配列番号DataRange{start=1500,end=1999}Thread-0正スピン解放ロック成功Thread-7配列番号DataRange{start=12000,end=12499}リリースロック成功Thread-7取得配列番号DataRange{start=12500,end=12999}リリースロック成功Thread-7取得配列番号DataRange{start=13000,end=13499}リリースロック成功Thread-7取得配列番号DataRange{start=13500,end=13999}リリースロック成功Thread-7取得配列番号DataRange{start=1400,end=14499}Thread-7スピンリリースロック成功Thread-3取得配列番号DataRange{start=14500,end=14999}リリースロック成功Thread-3取得配列番号DataRange{start=15000,end=15499}リリースロック成功Thread-3取得配列番号DataRange{start=15500,end=15999}リリースロック成功Thread-3取得配列番号DataRange{start=16099}リリースロック成功Thread-3取得配列番号DataRange{start=16500,end=16999}リリースロック成功Thread-3取得配列番号DataRange{start=16500,end=16999}リリースロック成功Thread-1取得配列番号DataRange{start=1700,end=17499}レリーズロック成功Thread-1配列番号DataRange{start=17500,end=17999}レリーズロック成功Thread-1配列番号DataRange{start=18000,end=18499}レリーズロック成功Thread-1配列番号DataRange{start=18500,end=18999}レリーズロック成功Thread-1配列番号DataRange{start=1900,end=19499}レリーズロック成功Thread-1配列番号DataRange{start=19500,end=19999}リリースロック成功Thread-1取得配列番号DataRange{start=20000,end=20499}リリースロック成功Thread-2取得配列番号DataRange{start=20500,end=20999}Thread-2スピンリリースロック成功Thread-5取得配列番号DataRange{start=2100,end=21499}リリースロック成功Thread-5取得配列番号Datange{start=21500,end=21999}リリースロック成功Thread-5取得配列番号DataRange{start=2000,end=22499}リリースロック成功Thread-5取得配列番号DataRange{start=2500,end=22999}リリースロック成功Thread-5取得配列番号DataRange{start=23000,end=23499}リリースロック成功Thread-5取得配列番号DataRange{start=23500,end=23999}Thread-8スピンThread-4スピンレリーズロック成功Thread-6配列番号DataRange{start=24500,end=24999}レリーズロック成功Thread-5配列番号DataRange{start=24000,end=244999}Thread-5スピンレリーズロック成功Thread-6配列番号DataRange{start=25000,end=254999}レリーズロック成功Thread-6配列番号DataRange{start=25500,end=25999}リリースロック成功Thread-6取得配列番号DataRange{start=25600,end=26499}リリースロック成功Thread-6取得配列番号DataRange{start=26500,end=26999}リリースロック成功Thread-6取得配列番号DataRange{start=2700,end=27499}リリースロック成功Thread-0取得配列番号DataRange{start=2700,end=27999}リリースロック成功Thread-0取得配列番号DataRange{start=28000,end=28499}解放ロック成功Thread-0配列番号DataRange{start=28500,end=28999}解放ロック成功Thread-0配列番号DataRange{start=29000,end=29999}解放ロック成功Thread-0配列番号DataRange{start=29500,end=29999}解放ロック成功Thread-0配列番号DataRange{start=30000,end=30499}解放ロック成功Thread-0配列番号DataRange{start=30999}解放ロック成功Thread-0配列番号Datange{start=30500,end=30999}解放ロック成功Thread-0配列番号DataRange{start=31000,end=31499}解放ロック成功Thread-7配列番号DataRange{start=31500,end=31999}解放ロック成功Thread-7配列番号DataRange{start=32000,end=32499}解放ロック成功Thread-7配列番号DataRange{start=32500,end=32999}解放ロック成功Thread-7配列番号DataRange{start=33000,end=33499}解放ロック成功Thread-7配列番号DataRange{start=33500,end=33999}解放ロック成功Thread-2配列番号DataRange{start=34000,end=34499}解放ロック成功Thread-2配列番号DataRange{start=34500,end=34999}解放ロック成功Thread-2配列番号DataRange{start=35000,end=35499}解放ロック成功Thread-2配列番号DataRange{start=35500,end=35999}Thread-8スピンレリーズロック成功Thread-2配列番号DataRange{start=36000,end=36499}Thread-5スピンThread-2スピンレリーズロック成功Thread-4配列番号DataRange{start=36500,end=36999}レリーズロック成功Thread-4配列番号DataRange{start=37000,end=37499}レリーズロック成功Thread-4配列番号DataRange{start=37500,end=37999}解放ロック成功Thread-4配列番号DataRange{start=38000,end=38499}解放ロック成功Thread-4配列番号DataRange{start=38500,end=38999}解放ロック成功Thread-4配列番号DataRange{start=39000,end=39499}解放ロック成功Thread-4配列番号DataRange{start=39500,end=39999}解放ロック成功Thread-4配列番号DataRange{start=40000,end=40499}解放ロック成功Thread-4配列番号DataRange{start=40500,end=40999}解放ロック成功Thread-4配列番号DataRange{start=41000,end=41499}解放ロック成功Thread-8配列番号DataRange{start=41500,end=41999}解放ロック成功Thread-8配列番号DataRange{start=42000,end=42499}解放ロック成功Thread-8配列番号DataRange{start=42999}リリースロック成功Thread-8配列番号DataRange{start=43000,end=43499}Thread-8スピンリリースロック成功Thread-5配列番号DataRange{start=43500,end=43999}Thread-2スピンリリースロック成功Thread-5配列番号DataRange{start=44000,end=44499}リリースロック成功Thread-5配列番号DataRange{start=44500,end=44999}Thread-2スピンレリーズロック成功Thread-8配列番号DataRange{start=45000,end=45499}レリーズロック成功Thread-8配列番号DataRange{start=45500,end=45999}レリーズロック成功Thread-8配列番号DataRange{start=46000,end=46499}レリーズロック成功Thread-8配列番号DataRange{start=4600,end=46999}レリーズロック成功Thread-8配列番号DataRange{start=46500,end=46999}レリーズロック成功Thread-8配列番号DataRange{start=47000,end=47499}解放ロック成功Thread-8配列番号DataRange{start=47500,end=47999}解放ロック成功Thread-2配列番号DataRange{start=48000,end=48499}解放ロック成功Thread-2配列番号DataRange{start=48500,end=48999}解放ロック成功Thread-2配列番号DataRange{start=49000,end=499}解放ロック成功Thread-2配列番号DataRange{start=49500, end=49999}
まとめ:redisのsetnxを使用して、どのクライアントがロックを取得するかを制御します(現在、上記のロック取得方法では同期の問題があり、keyvalueの設定と期限切れの設定が同期しないと、場合によってはデッドロックになります).取得したフロー番号は、毎回複数取得され、一定期間使用できます.本機のテストのため、学習の参考に供するだけで、必要なのは自分でコードを修正して完備することができます.
ここでdatacenterは、データベースまたはredisキャッシュストレージに変更できます.
あるいは、データベース楽観ロックを直接使用して実装してもよい.
1、データベース楽観ロック
2、redis錠
3、zookeeper
暇なときは、比較的簡単に実現できるredisロックを書きました.説明が苦手なので、直接コードを貼りましょう.
1、mavenは関連jarパッケージを持ち込む
redis.clients
jedis
2.9.0
2、ロックの取得とロックの解除に関するコード
public class RedisLock {
private static JedisPool jedisPool;
static {
JedisPoolConfig config = new JedisPoolConfig();
config.setMaxTotal(100);
config.setMaxIdle(100);
config.setMaxWaitMillis(3000);
config.setTestOnBorrow(false);
config.setMinIdle(10);
jedisPool = new JedisPool(config, "127.0.0.1", 6379);
}
private static Jedis getClient() {
return jedisPool.getResource();
}
private static String key = "redis.lock";
private static String val = "true";
private static int expire = 60; //
//
public static boolean getLock() {
for (; ; ) {
Jedis jedis = null;
try {
jedis = getClient();
Long result = jedis.setnx(key, val);
if (result == 1) {
jedis.expire(key, expire);
return true;
}
System.out.println(Thread.currentThread().getName() + " ");
try {
TimeUnit.SECONDS.sleep(1);
} catch (Exception e) {
e.printStackTrace();
}
} finally {
jedisPool.returnResource(jedis);
}
}
}
//
public static void relaseLock() {
getClient().expire(key, -1);
System.out.println(" ");
}
}
3、簡単なデータ記録センターで、一括で順序番号を取得する方法を提供する
public class DataRange {
private Long start;
private Long end;
public Long getStart() {
return start;
}
public void setStart(Long start) {
this.start = start;
}
public void setEnd(Long end) {
this.end = end;
}
public Long getEnd() {
return end;
}
@Override
public String toString() {
return "DataRange{" +
"start=" + start +
", end=" + end +
'}';
}
}
public class DataCenter {
private static Long num = 0L;
private static Integer step = 500;
public static DataRange getRangeNos() throws Exception {
if (RedisLock.getLock()) {
DataRange range = new DataRange();
range.setStart(num);
num += step;
range.setEnd(num - 1);
// TimeUnit.SECONDS.sleep(10);
RedisLock.relaseLock();
return range;
}
throw new Exception(" ");
}
}
4、1つの補充流水番号と日付が完全な流水番号を生成する補助類
public class DataUtil {
private static final int length = 8;
private static final String addc = "0";
private static SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd");
public static String complete(Long l) throws Exception {
String dateStr = format.format(new Date());
String ls = l.toString();
int lsl = ls.length();
if (lsl < length) {
StringBuilder sb = new StringBuilder(dateStr);
for (int i = 0; i < length - lsl; i++) {
sb.append(addc);
}
return sb.append(ls).toString();
} else if (lsl == length) {
return dateStr + ls;
} else {
throw new Exception("out of range");
}
}
}
5、呼び出しクライアントを作成し、ここではスレッドで表す
public class MyThread extends Thread {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
try {
DataRange range = DataCenter.getRangeNos();
System.out.println(this.getName() + " " + range);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
6、Testクラスの作成
public class Test {
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
Thread thread = new MyThread();
thread.start();
}
}
}
出力結果:
Thread-6スピンThread-2スピンThread-5スピンThread-0スピンThread-4スピンThread-8スピンThread-7スピンレリーズロック成功Thread-3配列番号DataRange{start=0,end=499}レリーズロック成功Thread-3配列番号DataRange{start=500,end=999}レリーズロック成功Thread-3配列番号DataRange{start=1000,end=1499}リリースロック成功Thread-3取得配列番号DataRange{start=1500,end=1999}リリースロック成功Thread-3取得配列番号DataRange{start=2000,end=2499}Thread-3スピンリリースロック成功Thread-1取得配列番号DataRange{start=2500,end=2999}リリースロック成功Thread-1取得配列番号DataRange{start=3000,end=3499}リリースロック成功Thread-1取得配列番号DataRange{start=3500,end=3999}Thread-1スピンレリーズロック成功Thread-9配列番号取得DataRange{start=4000,end=4499}レリーズロック成功Thread-9配列番号取得DataRange{start=4500,end=4999}レリーズロック成功Thread-9配列番号取得DataRange{start=5000,end=5499}レリーズロック成功Thread-9配列番号取得Datange{start=5500,end=5999}解放ロック成功Thread-9配列番号DataRange{start=6000,end=6499}解放ロック成功Thread-9配列番号DataRange{start=6500,end=6999}解放ロック成功Thread-9配列番号DataRange{start=7000,end=7499}解放ロック成功Thread-9配列番号DataRange{start=7500,end=7999}解放ロック成功Thread-9配列番号DataRange{start=8000,end=8499}リリースロック成功Thread-9取得配列番号DataRange{start=8500,end=8999}Thread-2スピン中Thread-5スピンリリースロック成功Thread-6取得配列番号DataRange{start=9000,end=9499}リリースロック成功Thread-6取得配列番号DataRange{start=9500,end=999}リリースロック成功Thread-6取得配列番号DataRange{start=10000,end=10499}解放ロック成功Thread-6配列番号DataRange{start=10500,end=10999}Thread-4正スピンThread-8正スピンThread-6正スピン解放ロック成功Thread-0配列番号DataRange{start=1000,end=1499}解放ロック成功Thread-0配列番号DataRange{start=1500,end=1999}Thread-0正スピン解放ロック成功Thread-7配列番号DataRange{start=12000,end=12499}リリースロック成功Thread-7取得配列番号DataRange{start=12500,end=12999}リリースロック成功Thread-7取得配列番号DataRange{start=13000,end=13499}リリースロック成功Thread-7取得配列番号DataRange{start=13500,end=13999}リリースロック成功Thread-7取得配列番号DataRange{start=1400,end=14499}Thread-7スピンリリースロック成功Thread-3取得配列番号DataRange{start=14500,end=14999}リリースロック成功Thread-3取得配列番号DataRange{start=15000,end=15499}リリースロック成功Thread-3取得配列番号DataRange{start=15500,end=15999}リリースロック成功Thread-3取得配列番号DataRange{start=16099}リリースロック成功Thread-3取得配列番号DataRange{start=16500,end=16999}リリースロック成功Thread-3取得配列番号DataRange{start=16500,end=16999}リリースロック成功Thread-1取得配列番号DataRange{start=1700,end=17499}レリーズロック成功Thread-1配列番号DataRange{start=17500,end=17999}レリーズロック成功Thread-1配列番号DataRange{start=18000,end=18499}レリーズロック成功Thread-1配列番号DataRange{start=18500,end=18999}レリーズロック成功Thread-1配列番号DataRange{start=1900,end=19499}レリーズロック成功Thread-1配列番号DataRange{start=19500,end=19999}リリースロック成功Thread-1取得配列番号DataRange{start=20000,end=20499}リリースロック成功Thread-2取得配列番号DataRange{start=20500,end=20999}Thread-2スピンリリースロック成功Thread-5取得配列番号DataRange{start=2100,end=21499}リリースロック成功Thread-5取得配列番号Datange{start=21500,end=21999}リリースロック成功Thread-5取得配列番号DataRange{start=2000,end=22499}リリースロック成功Thread-5取得配列番号DataRange{start=2500,end=22999}リリースロック成功Thread-5取得配列番号DataRange{start=23000,end=23499}リリースロック成功Thread-5取得配列番号DataRange{start=23500,end=23999}Thread-8スピンThread-4スピンレリーズロック成功Thread-6配列番号DataRange{start=24500,end=24999}レリーズロック成功Thread-5配列番号DataRange{start=24000,end=244999}Thread-5スピンレリーズロック成功Thread-6配列番号DataRange{start=25000,end=254999}レリーズロック成功Thread-6配列番号DataRange{start=25500,end=25999}リリースロック成功Thread-6取得配列番号DataRange{start=25600,end=26499}リリースロック成功Thread-6取得配列番号DataRange{start=26500,end=26999}リリースロック成功Thread-6取得配列番号DataRange{start=2700,end=27499}リリースロック成功Thread-0取得配列番号DataRange{start=2700,end=27999}リリースロック成功Thread-0取得配列番号DataRange{start=28000,end=28499}解放ロック成功Thread-0配列番号DataRange{start=28500,end=28999}解放ロック成功Thread-0配列番号DataRange{start=29000,end=29999}解放ロック成功Thread-0配列番号DataRange{start=29500,end=29999}解放ロック成功Thread-0配列番号DataRange{start=30000,end=30499}解放ロック成功Thread-0配列番号DataRange{start=30999}解放ロック成功Thread-0配列番号Datange{start=30500,end=30999}解放ロック成功Thread-0配列番号DataRange{start=31000,end=31499}解放ロック成功Thread-7配列番号DataRange{start=31500,end=31999}解放ロック成功Thread-7配列番号DataRange{start=32000,end=32499}解放ロック成功Thread-7配列番号DataRange{start=32500,end=32999}解放ロック成功Thread-7配列番号DataRange{start=33000,end=33499}解放ロック成功Thread-7配列番号DataRange{start=33500,end=33999}解放ロック成功Thread-2配列番号DataRange{start=34000,end=34499}解放ロック成功Thread-2配列番号DataRange{start=34500,end=34999}解放ロック成功Thread-2配列番号DataRange{start=35000,end=35499}解放ロック成功Thread-2配列番号DataRange{start=35500,end=35999}Thread-8スピンレリーズロック成功Thread-2配列番号DataRange{start=36000,end=36499}Thread-5スピンThread-2スピンレリーズロック成功Thread-4配列番号DataRange{start=36500,end=36999}レリーズロック成功Thread-4配列番号DataRange{start=37000,end=37499}レリーズロック成功Thread-4配列番号DataRange{start=37500,end=37999}解放ロック成功Thread-4配列番号DataRange{start=38000,end=38499}解放ロック成功Thread-4配列番号DataRange{start=38500,end=38999}解放ロック成功Thread-4配列番号DataRange{start=39000,end=39499}解放ロック成功Thread-4配列番号DataRange{start=39500,end=39999}解放ロック成功Thread-4配列番号DataRange{start=40000,end=40499}解放ロック成功Thread-4配列番号DataRange{start=40500,end=40999}解放ロック成功Thread-4配列番号DataRange{start=41000,end=41499}解放ロック成功Thread-8配列番号DataRange{start=41500,end=41999}解放ロック成功Thread-8配列番号DataRange{start=42000,end=42499}解放ロック成功Thread-8配列番号DataRange{start=42999}リリースロック成功Thread-8配列番号DataRange{start=43000,end=43499}Thread-8スピンリリースロック成功Thread-5配列番号DataRange{start=43500,end=43999}Thread-2スピンリリースロック成功Thread-5配列番号DataRange{start=44000,end=44499}リリースロック成功Thread-5配列番号DataRange{start=44500,end=44999}Thread-2スピンレリーズロック成功Thread-8配列番号DataRange{start=45000,end=45499}レリーズロック成功Thread-8配列番号DataRange{start=45500,end=45999}レリーズロック成功Thread-8配列番号DataRange{start=46000,end=46499}レリーズロック成功Thread-8配列番号DataRange{start=4600,end=46999}レリーズロック成功Thread-8配列番号DataRange{start=46500,end=46999}レリーズロック成功Thread-8配列番号DataRange{start=47000,end=47499}解放ロック成功Thread-8配列番号DataRange{start=47500,end=47999}解放ロック成功Thread-2配列番号DataRange{start=48000,end=48499}解放ロック成功Thread-2配列番号DataRange{start=48500,end=48999}解放ロック成功Thread-2配列番号DataRange{start=49000,end=499}解放ロック成功Thread-2配列番号DataRange{start=49500, end=49999}
まとめ:redisのsetnxを使用して、どのクライアントがロックを取得するかを制御します(現在、上記のロック取得方法では同期の問題があり、keyvalueの設定と期限切れの設定が同期しないと、場合によってはデッドロックになります).取得したフロー番号は、毎回複数取得され、一定期間使用できます.本機のテストのため、学習の参考に供するだけで、必要なのは自分でコードを修正して完備することができます.
ここでdatacenterは、データベースまたはredisキャッシュストレージに変更できます.
あるいは、データベース楽観ロックを直接使用して実装してもよい.