mcpField
R
redis-redisson-patterns

redis-redisson-patterns

github.com/full-stack-skills開発795 回インストール4 週間前に更新
リポジトリ

redis-redisson-patterns について

redis-redisson-patternsは、JavaおよびSpring開発者向けのキャッシュと分散ロックの実践ガイドです。Redisの設定、キャッシュ障害の防止、シリアライズ方式、Redissonのロックパターンを扱います。

主な機能

  1. 01キャッシュキーの命名規則
  2. 02TTLとシリアライズ方式の選択
  3. 03Redisson分散ロックのパターン
  4. 04キャッシュ貫通・雪崩・集中失効への対策
  5. 05CaffeineとRedisの選択
  6. 06RedisTemplateのJSON設定

活用シーン

  1. 01Redisオブジェクトキャッシュの設定
  2. 02ホットデータ向けローカル・共有キャッシュの設計
  3. 03自動延長付き分散ロックの実装
  4. 04キャッシュの同時失効リスクの低減

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/full-stack-skills/java-skills --skill redis-redisson-patterns

インストール後、Claude Code で/redis-redisson-patternsを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

agents/
openai.yaml
examples/
redis-realworld.md
references/
redis-kafka-resources.md

詳細

Redis + Redisson キャッシュと分散ロック

出典:https://redisson.org/docs/
GitHub:https://github.com/redisson/redisson
Redis:https://redis.io/documentation

対応範囲

✅ 得意分野
  1. キャッシュKeyの規約 — 形式は {業務名}:{種類}:{ID}、プレフィックスを統一
  2. 有効期限の原則 — ホットデータは長いTTL、非ホットデータは短いTTL、-1は設定しない
  3. シリアライズ方式の選択 — JSON、JDK、Stringの3方式を比較し、設定
  4. Redisson分散ロック — tryLock/watchDog/leaseTime/再入可能/公平ロック/Redlock
  5. キャッシュの三大問題への対策 — キャッシュ貫通(ブルームフィルター/空値)/キャッシュスタンピード(相互排他ロック)/キャッシュ雪崩(ランダムTTL)
  6. CaffeineとRedisの使い分け — ローカルキャッシュとRedisを使う場面
  7. RedisTemplateの適切な設定 — Key/Valueのシリアライズを統一
❌ 対象外
  1. メッセージキュー/パブリッシュ・サブスクライブ → kafka / RabbitMQ
  2. Spring Sessionの共有 → spring-security
  3. Jedis/Lettuceクライアントの選択 → 本ドキュメントではLettuceを推奨(Spring Bootのデフォルト)

シリアライズ方式の選択

方式メリットデメリット適用シーン
StringRedisTemplateシンプルで読みやすいStringしか保存できず、オブジェクトは手動でシリアライズが必要文字列のみのキャッシュ
RedisTemplate + Jackson2JsonRedisSerializer読みやすく、言語をまたいで利用可能パフォーマンスがやや低い✅ 推奨(ほとんどのシーンに適しています)
RedisTemplate + JdkSerializationRedisSerializerデフォルト(型情報を含む)読み取れず、サイズが大きく、Java専用❌ 非推奨(デフォルトがこれです)
RedisTemplate + GenericJackson2JsonRedisSerializer@class型情報を含む冗長なフィールドが多い複雑なオブジェクトのキャッシュ

LLMがよく犯す間違い

#間違い正しい方法
1キャッシュに有効期限を設定しない(永久)メモリ不足を防ぐため、必ずTTLを設定する
2StringRedisTemplateとRedisTemplateを混在させるどちらかに統一し、RedisTemplate + JSONシリアライズを推奨
3キャッシュ貫通(存在しないデータの検索がそのままDBに到達)空値をキャッシュ(Boolean.FALSE、TTL 5分)するか、ブルームフィルターを使う
4Redisを高頻度のホットキャッシュに使う(毎秒1000qps以上)Caffeineのローカルキャッシュ層を追加する(L1ローカル + L2 Redis)
5lock.lock() をtry-finallyで囲まない必ず finally { lock.unlock() } にする
6キャッシュKeyに命名規約がない形式を統一する:saas:user:10001、saas:order:list
7RedissonでleaseTimeを指定しながら、Watchdogによる延長を期待するleaseTimeを指定するとWatchdogは機能しません!
8キャッシュ雪崩に対処しない(大量のKeyが同時に期限切れになる)TTLにランダム値(±30%)を加える
9ホットKeyのキャッシュスタンピード相互排他ロック、または有効期限を設けず非同期で更新する
10RedisTemplateのデフォルトであるJDKシリアライズを使うJSONシリアライズに変更する(読みやすく、言語をまたいで利用可能)

コアパターン

パターン 1: RedisTemplateの統一設定(JSONシリアライズ)
@Configuration
public class RedisConfig {
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(factory);

        // ✅ 推荐:Jackson2JsonRedisSerializer
        Jackson2JsonRedisSerializer<Object> serializer =
            new Jackson2JsonRedisSerializer<>(Object.class);
        ObjectMapper mapper = new ObjectMapper();
        mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        mapper.activateDefaultTyping(LazySerializationTypeValidator.getDefaultTyper(),
            ObjectMapper.DefaultTyping.NON_FINAL);
        serializer.setObjectMapper(mapper);

        template.setKeySerializer(new StringRedisSerializer());     // Key: String
        template.setValueSerializer(serializer);                    // Value: JSON
        template.setHashKeySerializer(new StringRedisSerializer());
        template.setHashValueSerializer(serializer);
        template.afterPropertiesSet();
        return template;
    }
}
パターン 2: キャッシュ貫通対策(空値キャッシュ)
public User getUser(Long id) {
    String key = String.format("saas:user:%s", id);
    User user = (User) redisTemplate.opsForValue().get(key);

    // 空值标记,直接返回
    if (user == NULL_PLACEHOLDER) return null;
    // 缓存命中
    if (user != null) return user;

    // 查询DB
    user = userMapper.selectById(id);
    if (user == null) {
        // ✅ 空值缓存(防穿透),TTL 5分钟
        redisTemplate.opsForValue().set(key, NULL_PLACEHOLDER, 5, TimeUnit.MINUTES);
        return null;
    }
    // ✅ 正常缓存,30分钟
    redisTemplate.opsForValue().set(key, user, 30, TimeUnit.MINUTES);
    return user;
}
パターン 3: Redisson分散ロックの3つのパターン

パターンA: tryLock + watchDog(推奨)— 待機時間あり + 自動延長

RLock lock = redissonClient.getLock("lock:order:" + orderId);
// ✅ 只指定 waitTime,不指定 leaseTime → watchDog 生效(默认30s续期)
if (lock.tryLock(10, TimeUnit.SECONDS)) {  // 等10秒获取锁
    try {
        // 业务处理(可能超过30秒,watchDog自动续期)
    } finally {
        if (lock.isHeldByCurrentThread()) {
            lock.unlock();
        }
    }
}

パターンB: tryLock + leaseTime — ハードタイムアウト(Watchdogは機能しません)

RLock lock = redissonClient.getLock("lock:order:" + orderId);
// ⚠️ 指定了 leaseTime → watchDog 不生效
if (lock.tryLock(10, 30, TimeUnit.SECONDS)) {
    try {
        // 必须在30秒内完成,否则锁自动释放
    } finally {
        if (lock.isHeldByCurrentThread()) {
            lock.unlock();
        }
    }
}

パターンC: lock() — ブロッキング待機 + watchDog

RLock lock = redissonClient.getLock("lock:order:" + orderId);
lock.lock();  // 阻塞直到获取锁,watchDog 生效
try {
    // 业务处理
} finally {
    if (lock.isHeldByCurrentThread()) {
        lock.unlock();
    }
}
パターン 4: キャッシュ雪崩対策(ランダムTTL)
// 相同业务场景的缓存 TTL 加随机值,避免同时过期
int baseTtl = 3600;  // 1小时
int randomTtl = baseTtl + new Random().nextInt(600);  // +0~10分钟随机
redisTemplate.opsForValue().set(key, value, randomTtl, TimeUnit.SECONDS);
パターン 5: キャッシュKeyの規約
// 命名格式: {业务}:{领域}:{实体}:{唯一标识}
private static final String USER_CACHE_KEY = "saas:user:detail:%s";
private static final String ORDER_LIST_KEY = "saas:order:list:%s:%d"; // userId + page
private static final String CONFIG_KEY = "saas:config:global";

String key = String.format(USER_CACHE_KEY, userId);

注意点

  1. キャッシュには必ず有効期限を設定する — TTLを設定しないとメモリリークが発生します
  2. Redissonのロックはtry-finallyでunlockする — そうしないとデッドロックが発生します
  3. watchDogによる自動延長 — leaseTimeを指定しない場合、デフォルトは30秒で、10秒ごとに延長されます
  4. leaseTimeを指定するとWatchdogは機能しない — 自動延長が必要ならleaseTimeを指定しないでください
  5. Redisクラスターでは一括mgetを使えない(Slotをまたぐ場合) — getをループするか、hash tagでSlotを固定してください
  6. キャッシュ雪崩:同時に大量のKeyが期限切れになる — TTLにランダム値(±30%)を加える
  7. キャッシュスタンピード:ホットKeyの期限切れ直後に大量のリクエストが貫通する — 相互排他ロック、または有効期限を設けず非同期で更新する
  8. Caffeineは単一サービスの高頻度キャッシュに適しています — Redisは分散共有に、Caffeineはローカルでの高速化に使います
  9. unlockの前にisHeldByCurrentThread()を確認する — IllegalMonitorStateExceptionを防ぎます
  10. RedisTemplateのデフォルトはJDKシリアライズ — JSONシリアライズに変更する(読みやすく、言語をまたいで利用可能)
  11. Lettuce(Spring Bootのデフォルト)はJedisより推奨 — 非同期、コネクションプール、活発なコミュニティ
  12. ブルームフィルター(RedissonBloomFilter)はキャッシュ貫通対策に使う — Key数が多く、100%の精度が求められない場合に適しています

データプライバシー

本スキルは、ユーザーデータを収集、保存、送信しません。

コメント