はじめに
以前、Redis上でセマフォを実装する必要がありました。驚いたことに、私たちが使用しているJedisクライアントとLettuceクライアントの両方には、それに対する良い準備ができた解決策がないことがわかりました(Redissonにはそのようなものがあります)。
そのため、私はその隙間を埋め、JedisとLettuceの両方のRedisクライアント向けの解決策を提供することにしました。
セマフォが使用したい理由は何ですか?
リソースの相互利用を制限する必要がある状況を想像してみてください。たとえば、バックグラウンドタスクで実行されている重いSQLクエリが全体のサービスパフォーマンスに悪影響を及ぼす可能性がある場合、許可された回数よりも同時にそのクエリが発行されないようにする必要があります。
セマフォを使用することで、共通リソースのクロスプロセス競合状態を解決し、共通リソースへのアクセスを特定の量に制限することができます。
解決策はこちらです
RedPulsar が、セマフォを含む分散ロックを提供しています!
コード例1
dependencies {
...
implementation("com.himadieiev:redpulsar-jedis:1.2.0")
...
}
3つのリースとリトライ構成のセマフォを作成します:
var poolConfig = new GenericObjectPoolConfig<Connection>();
var client = new JedisPooled(poolConfig, "redis-host-name", 6379, 100);
var semaphore = LockFactory.createSemaphore(List.of(client), 3, Duration.ofMillis(50), 2);
var worker = Worker(semaphore, databaseService);
もしロックが取得できない場合は、初期ディレイを50ミリ秒として2回リトライします。
Worker
の中セマフォを利用します:
public void run() {
if (semaphore.lock("MyResource", Duration.ofMinutes(1))) {
var report = database.fetchAnalyticsReport();
...
}
}
このコード例は、RedPulsar をコードベースに組み込むのがどれほど簡単かを示しています。
しかし、ロックに高可用性を持たせたい場合はどうすればよいでしょうか?冗長性を追加する必要があります。RedPulsar がそれをどのように実現しているかを以下に示します。
コード例2
以下の例は、前のコード例と似ていますが、今回は3つのJedisクライアントのインスタンスを渡します:
var poolConfig = new GenericObjectPoolConfig<Connection>();
var client1 = new JedisPooled(poolConfig, "redis-host-name1", 6379, 100);
var client2 = new JedisPooled(poolConfig, "redis-host-name2", 6379, 100);
var client3 = new JedisPooled(poolConfig, "redis-host-name3", 6379, 100);
var semaphore = LockFactory.createSemaphore(List.of(client1, client2, client3), 3, Duration.ofMillis(50), 3);
var worker = Worker(semaphore, databaseService);
最後に
RedPulsar を使用したセマフォの実装は、システムの安定性と信頼性を高めるための有力な手段であり、Redisを使用した分散システムの開発において役立つでしょう。
🔗 GitHubリポジトリ: RedPulsar on GitHub