この記事では主にRedisにおける分散ロックの実装とコード解析について紹介しますので、お役に立てれば幸いです。
Redis 分散ロック
分散ロック ハンドルはすべてのプロジェクトで使用され、通常はデータの順序付けに使用されます。注文の返金として (複数回返金できる場合)。あるいは、ユーザーは複数の端末から注文を行います。 [関連する推奨事項: Redis ビデオ チュートリアル ]
Maven の依存関係
私は主に Spring に基づいています。ブート 2.1.2
Jedis
実装
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.2.RELEASE</version> </parent> <groupId>cn.edu.cqvie</groupId> <artifactId>redis-lock</artifactId> <version>1.0-SNAPSHOT</version> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <java.version>1.8</java.version> <redis.version>2.9.0</redis.version> <spring-test.version>5.0.7</spring-test.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-autoconfigure</artifactId> </dependency> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-redis</artifactId> </dependency> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>${redis.version}</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-logging</artifactId> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>log4j-over-slf4j</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
構成ファイル
application.properties
設定ファイルの内容は次のとおりです:
spring.redis.host=127.0.0.1 spring.redis.port=6379 spring.redis.password= spring.redis.timeout=30000 spring.redis.jedis.pool.max-active=8 spring.redis.jedis.pool.min-idle=2 spring.redis.jedis.pool.max-idle=4 logging.level.root=INFO
インターフェース定義
コアをロックするためのインターフェース定義は、実際には次のとおりです。 1 つのメソッドlock
と unlock
.
public interface RedisLock { long TIMEOUT_MILLIS = 30000; int RETRY_MILLIS = 30000; long SLEEP_MILLIS = 10; boolean tryLock(String key); boolean lock(String key); boolean lock(String key, long expire); boolean lock(String key, long expire, long retryTimes); boolean unlock(String key); }
分散ロックの実装
私の実装は完了しましたsetnx. 、 tryLock
ロジックが存在する場合、 spin
// AbstractRedisLock.java 抽象类 public abstract class AbstractRedisLock implements RedisLock { @Override public boolean lock(String key) { return lock(key, TIMEOUT_MILLIS); } @Override public boolean lock(String key, long expire) { return lock(key, TIMEOUT_MILLIS, RETRY_MILLIS); } } // 具体实现 @Component public class RedisLockImpl extends AbstractRedisLock { private Logger logger = LoggerFactory.getLogger(getClass()); @Autowired private RedisTemplate<String, String> redisTemplate; private ThreadLocal<String> threadLocal = new ThreadLocal<String>(); private static final String UNLOCK_LUA; static { StringBuilder sb = new StringBuilder(); sb.append("if redis.call(\"get\",KEYS[1]) == ARGV[1] "); sb.append("then "); sb.append(" return redis.call(\"del\",KEYS[1]) "); sb.append("else "); sb.append(" return 0 "); sb.append("end "); UNLOCK_LUA = sb.toString(); } @Override public boolean tryLock(String key) { return tryLock(key, TIMEOUT_MILLIS); } public boolean tryLock(String key, long expire) { try { return !StringUtils.isEmpty(redisTemplate.execute((RedisCallback<String>) connection -> { JedisCommands commands = (JedisCommands) connection.getNativeConnection(); String uuid = UUID.randomUUID().toString(); threadLocal.set(uuid); return commands.set(key, uuid, "NX", "PX", expire); })); } catch (Throwable e) { logger.error("set redis occurred an exception", e); } return false; } @Override public boolean lock(String key, long expire, long retryTimes) { boolean result = tryLock(key, expire); while (!result && retryTimes-- > 0) { try { logger.debug("lock failed, retrying...{}", retryTimes); Thread.sleep(SLEEP_MILLIS); } catch (InterruptedException e) { return false; } result = tryLock(key, expire); } return result; } @Override public boolean unlock(String key) { try { List<String> keys = Collections.singletonList(key); List<String> args = Collections.singletonList(threadLocal.get()); Long result = redisTemplate.execute((RedisCallback<Long>) connection -> { Object nativeConnection = connection.getNativeConnection(); if (nativeConnection instanceof JedisCluster) { return (Long) ((JedisCluster) nativeConnection).eval(UNLOCK_LUA, keys, args); } if (nativeConnection instanceof Jedis) { return (Long) ((Jedis) nativeConnection).eval(UNLOCK_LUA, keys, args); } return 0L; }); return result != null && result > 0; } catch (Throwable e) { logger.error("unlock occurred an exception", e); } return false; } }
テスト コード ## によって再試行されます。 ##最後に使い方を見てみましょう (以下はフラッシュセールのシミュレーションです)
@RunWith(SpringRunner.class) @SpringBootTest public class RedisLockImplTest { private Logger logger = LoggerFactory.getLogger(getClass()); @Autowired private RedisLock redisLock; @Autowired private StringRedisTemplate redisTemplate; private ExecutorService executors = Executors.newScheduledThreadPool(8); @Test public void lock() { // 初始化库存 redisTemplate.opsForValue().set("goods-seckill", "10"); List<Future> futureList = new ArrayList<>(); for (int i = 0; i < 100; i++) { futureList.add(executors.submit(this::seckill)); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } // 等待结果,防止主线程退出 futureList.forEach(action -> { try { action.get(); } catch (InterruptedException | ExecutionException e) { e.printStackTrace(); } }); } public int seckill() { String key = "goods"; try { redisLock.lock(key); int num = Integer.valueOf(Objects.requireNonNull(redisTemplate.opsForValue().get("goods-seckill"))); if (num > 0) { redisTemplate.opsForValue().set("goods-seckill", String.valueOf(--num)); logger.info("秒杀成功,剩余库存:{}", num); } else { logger.error("秒杀失败,剩余库存:{}", num); } return num; } catch (Throwable e) { logger.error("seckill exception", e); } finally { redisLock.unlock(key); } return 0; } }概要
この記事は簡単な方法です。 Redis ロック 実装メソッドは、
jedis に基づいてロックのリトライ操作を実装します。
ただし、ロックの自動更新、ロックの再入性、公平性(現在は不当な方法に相当するスピンによって実装されています)をサポートしていないという欠点もあります。 プログラミング関連の知識について詳しくは、
以上がRedis の分散ロックの詳細な分析の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

Redisは、データベース、キャッシュ、メッセージブローカーとして使用されるオープンソースメモリデータ構造ストレージであり、高速応答と高い並行性が必要なシナリオに適しています。 1.Redisはメモリを使用してデータを保存し、マイクロ秒の読み取り速度と書き込み速度を提供します。 2.文字列、リスト、コレクションなどのさまざまなデータ構造をサポートします。3。Redisは、RDBおよびAOFメカニズムを介してデータの持続性を実現します。 4.シングルスレッドモデルと多重化テクノロジーを使用して、リクエストを効率的に処理します。 5.パフォーマンス最適化戦略には、LRUアルゴリズムとクラスターモードが含まれます。

Redisの関数には、主にキャッシュ、セッション管理、その他の機能が含まれます。1)キャッシュ関数はメモリを介してデータを保存して読み取り速度を向上させ、eコマースWebサイトなどの高周波アクセスシナリオに適しています。 2)セッション管理関数は、分散システムでセッションデータを共有し、有効期限のあるメカニズムを通じて自動的にクレンジングします。 3)リアルタイムメッセージプッシュおよびマルチスレッドシステムおよびその他のシナリオに適した、パブリッシュサブスクライブモード、分散ロック、カウンターなどのその他の機能。

Redisのコア関数には、メモリストレージと持続性メカニズムが含まれます。 1)メモリストレージは、高性能アプリケーションに適した非常に高速な読み取り速度と書き込み速度を提供します。 2)永続性は、RDBとAOFによってデータが失われないことを保証し、選択はアプリケーションのニーズに基づいています。

redis'sserver-sideoperations offferidions and forexuctingcomplexoperationsontheserver.1)機能を調整することで、javascript、orredis'sscriptinglanguage、infulancingscalabilityandmantenmention

redisisbothadatabaseandaserver.1)asadatabase、itusesin memorystorage forfastaccess、理想的なforreal-timeapplicationsandcaching.2)asaserver、itupportspub/submessagingandaging andluascriptingforreal-communicationandserver-sideoperation。

Redisは、高性能と柔軟性を提供するNOSQLデータベースです。 1)大規模データと高い並行性の処理に適したキー価値ペアを介してデータを保存します。 2)メモリストレージとシングルスレッドモデルは、速い読み取りと書き込みと原子性を確保します。 3)RDBおよびAOFメカニズムを使用してデータを持続し、高可用性とスケールアウトをサポートします。

Redisは、主にデータベース、キャッシュ、メッセージブローカーとして使用されるメモリデータ構造ストレージシステムです。そのコア機能には、シングルスレッドモデル、I/O多重化、持続メカニズム、複製、クラスタリング機能が含まれます。 Redisは、キャッシュ、セッションストレージ、メッセージキューのための実際のアプリケーションで一般的に使用されます。適切なデータ構造を選択し、パイプラインとトランザクションを使用し、監視とチューニングを使用することにより、パフォーマンスを大幅に改善できます。

RedisデータベースとSQLデータベースの主な違いは、Redisが高性能および柔軟性要件に適したインメモリデータベースであることです。 SQLデータベースは、複雑なクエリとデータの一貫性要件に適したリレーショナルデータベースです。具体的には、1)Redisは高速データアクセスとキャッシュサービスを提供し、キャッシュおよびリアルタイムのデータ処理に適した複数のデータ型をサポートします。 2)SQLデータベースは、テーブル構造を介してデータを管理し、複雑なクエリとトランザクション処理をサポートし、データの一貫性を必要とするeコマースや金融システムなどのシナリオに適しています。


ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

Video Face Swap
完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

人気の記事

ホットツール

WebStorm Mac版
便利なJavaScript開発ツール

SublimeText3 英語版
推奨: Win バージョン、コードプロンプトをサポート!

EditPlus 中国語クラック版
サイズが小さく、構文の強調表示、コード プロンプト機能はサポートされていません

ZendStudio 13.5.1 Mac
強力な PHP 統合開発環境

AtomエディタMac版ダウンロード
最も人気のあるオープンソースエディター

ホットトピック









