注目のキャッシュサービスのValkeyをSpring Boot(Kotlin)で使ってみた

こんにちは。アスクルの加藤です。 私が所属するチームで開発しているシステムでAmazon RDSを使用しており、そこにキャッシュを導入することになりました。 ちょうどその頃Valkeyが話題になっており、検討の結果Amazon ElastiCacheでValkeyを使用することになりました。 今回はSpring Boot(Kotlin)でAmazon ElastiCacheのValkeyを使ってみたので、その手順や設定を紹介します。

Valkeyとは

Redisのライセンス変更を受けてRedisをフォークして作られた、オープンソースのキャッシュサービスがValkeyです。 2024年1月現在で8.0.1がリリースされており、現在はRedisと大きな差はありませんが、 今後のバージョンでRedisとの相違点が増えていくとValkeyのメンテナからコメントされています。 (https://redis.io/blog/what-is-valkey/)

またAWS、Google Cloud、Oracleなど複数企業がValkeyをサポートしています。 AWSではAmazon ElastiCacheとAmazon MemoryDBでValkeyを使用でき、Redisより低価格で提供されています。

SpringBootでのValkey利用

接続設定

Redisと同じくLettuceConnectionFactoryなどを使用して設定できます。 以下がValkey接続設定です。masterとreplicaのホスト情報と、タイムアウトなどの諸々を設定します。

@Configuration
class ElastiCacheConfig() {
    @Bean
    fun redisConnectionFactory(): LettuceConnectionFactory {
        val clientConfig = LettucePoolingClientConfiguration.builder()
            .commandTimeout(Duration.ofMillis(1000))
            .shutdownTimeout(Duration.ofMillis(1000))
            .readFrom(REPLICA_PREFERRED)
            .build()

        val serverConfig = RedisStaticMasterReplicaConfiguration(
            "masterHost",
            6379,
        ).apply {
            username = "userName"
            setPassword("password")
            addNode(
                "replicaHost",
                6379,
            )
        }

        return LettuceConnectionFactory(
            serverConfig,
            clientConfig,
        )
    }
}

操作処理

アプリからValkeyへの接続はRedisTemplateを使用して行えます。 (https://spring.pleiades.io/spring-data/redis/reference/redis/template.html)

取得はmultiGet等で行えます。

@Autowired
val stringRedisTemplate = StringRedisTemplate()

fun  get(
    keys: List<String>,
): List<String> = try {
    stringRedisTemplate.opsForValue().multiGet(keys)?.filterNotNull() ?: emptyList()
} catch (e: Exception) {
    throw e
}

登録更新も同様にmultiSet等で行えます。 multiSetでは同一キーがすでに登録されている場合は上書きされます。

fun set(
    keyValueMaps: Map<String, String>,
) {
    try {
        stringRedisTemplate.opsForValue().multiSet(keyValueMaps)
    } catch (e: Exception) {
        throw e
    }
}

stringRedisTemplate.executePipelinedを使用するとコマンドを非同期で同時に実行できるためパフォーマンス改善を見込めます。 (https://docs.spring.io/spring-data/redis/reference/redis/pipelining.html)

fun pipelinedSet(
    keyValueMaps: Map<String, String>,
) {
    try {
        stringRedisTemplate.executePipelined {
            val connection = it as StringRedisConnection
            connection.mSetString(keyValueMaps)
            keyValueMaps.keys.forEach { key ->
                connection.expire(key, TTL)
            }
            null
        }
    } catch (e: Exception) {
        throw e
    }
}

削除はdeleteで行え、削除成功件数が返されます。

fun delete(
    keys: List<String>,
) = try {
    stringRedisTemplate.delete(
        keys
    ).toInt()
} catch (e: Exception) {
    throw e
}

Valkeyユーザ権限設定

上記の取得、登録更新、削除する上で必要になるValkeyの権限は大まかに次になります。

get,
mget,
set,
mset,
del

masterとreplicaで利用する場合はrole権限も必要になります。

終わりに

Redis用に用意されたライブラリをそのまま使用できるため、比較的容易に導入できました。 今回は新規でキャッシュを導入しましたが、Redisからの乗り換えも比較的楽に行えそうでした。 以上、ここまで読んでいただきありがとうございました!

ASKUL Engineering BLOG

2021 © ASKUL Corporation. All rights reserved.