こんにちは。アスクルの加藤です。 私が所属するチームで開発しているシステムで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からの乗り換えも比較的楽に行えそうでした。 以上、ここまで読んでいただきありがとうございました!