きり丸の技術日記

技術検証したり、資格等をここに残していきます。

SpringでRedisを使う(データベース、キャッシュとしての使い方)

本業はJavaのバックエンドエンジニアなのですが、Redisを使ったことがないので、素振りします。

今回の記事では、データベース、キャッシュとしての機能を検証することをゴールとします。メッセージブローカー、キューとしての挙動は記載いたしません。

環境

  • Java
    • 17
  • Redis
    • 7.0.5
  • org.springframework.boot
    • 2.6.4
  • org.testcontainers:junit-jupiter
    • 1.17.4
  • Gradle
  • Lombok
  • Docker

対応

Gradleを記載する

Redisを使えるように、依存関係に含めます。テストについても記載するのでTestContainersについても、依存関係に含めます。

implementation 'org.springframework.boot:spring-boot-starter-web:2.6.4'
implementation 'org.springframework.boot:spring-boot-starter-data-redis:2.6.4'

testImplementation 'org.springframework.boot:spring-boot-starter-test:2.6.4'
testImplementation 'org.testcontainers:junit-jupiter:1.17.4'

エンティティの用意

適当なエンティティを用意します。@RedisHash(テーブル名)をエンティティに付与すると、そのテーブル名でRedisへのアクセスを行ってくれます。

@RedisHash("user")
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class UserDto implements Serializable {
    private String id;
    private String name;
}

DAO(Mapper)の用意

org.springframework.data.repository.CrudRepositoryを継承し、<T, ID>を指定するだけで、データアクセスができます。

@Repository
public interface UserRedisMapper extends CrudRepository<UserDto, String> {
}

設定ファイルの用意

デフォルトの場合、特に指定しなくても接続できます。接続情報を指定してください。

spring.redis:
 database: 0
 host: localhost
 port: 6379 #6379がウェルノウンポート
 password: null
 timeout: 200

テストコードの準備

TestContainersを使用したいので、TestContainersRedisを準備します。また、Dockerを使用するので、Dockerを起動しておいてください。

@SpringBootApplication
@Testcontainers
public class RepositoryApplication {

  @Container
  private static final GenericContainer<?> redis;

  static {
    // Redisのバージョン指定
    redis = new GenericContainer<>(DockerImageName.parse("redis:latest"))
        .withExposedPorts(6379);
    
    redis.start();
  
    // 接続情報の書き換え
    System.setProperty("spring.redis.host", redis.getHost());
    System.setProperty("spring.redis.port", redis.getFirstMappedPort().toString());
  }
}

テストコード本体

基本的には、@DataRedisTestを付与するだけで、MyBatis等々と同じように記載できます。@SpringBootTestよりも多少は軽く起動できます。

@DataRedisTest
class UserRedisMapperTests {
  @Autowired
  UserRedisMapper mapper;

  @BeforeEach
  void setUp() {
    mapper.deleteAll();
  }

  @Test
  void test_01() {
    assertThat(mapper.findAll()).isEmpty();
  }

  @Test
  void test_02() {
    var USER1 = UserDto.builder().id("1").name("1").build();
    var USER2 = UserDto.builder().id("2").name("2").build();

    mapper.saveAll(List.of(USER1, USER2));

    assertThat(
        mapper.findAll()
    ).isEqualTo(List.of(USER1, USER2));
  }
}

懸念点

ローカルでは動作確認できたのですが、GitHub Actionsでは動きませんでした。

動かそうとすると、次のエラーが発生します。49154ポートなんてどこでも使用していないのですが…。

org.springframework.data.redis.RedisConnectionFailureException: Unable to connect to Redis; nested exception is io.lettuce.core.RedisConnectionException: Unable to connect to localhost/<unresolved>:49154

TestContainersGitHub Actionsで使用すると同じようになりそうですね。PostgreSQLも似た事象が発生しました。いろいろググっても、TestContainersのissueを見ても解決方法が分からなかったので、教えていただければ非常に喜びます。

ソースコード

Redisだけ別プロジェクトにしています。

終わりに

メッセージブローカー、キューとしての使い方は公式ドキュメントに載っていたので、そちらは一応素振りしてみたのですがイマイチよくわからず…。

正直、かなり浅い記事なのはわかっているのですが、とりあえず一応本業でRedisを採用するときになったら、すぐに使いこなせそうです。

参考情報