spring +kotlin 配置redis 和redis的常用方法
在 Spring Boot + Kotlin 项目中,可以同时使用 RedissonClient
(提供分布式对象和高级功能)和 RedisTemplate
(Spring Data Redis 的标准操作)。以下是 完整配置和用法示例:
1. 添加依赖
在 build.gradle.kts
中引入依赖:
dependencies {
// Spring Data Redis
implementation("org.springframework.boot:spring-boot-starter-data-redis")
// Redisson
implementation("org.redisson:redisson-spring-boot-starter:3.23.6")
// Kotlin 序列化支持
implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
}
2. 配置 RedissonClient 和 RedisTemplate
配置 Redisson(通过 application.yml
)
spring:
redis:
host: localhost
port: 6379
password: your-password # 如有密码
redisson:
config: classpath:redisson.yaml # Redisson 配置文件路径
创建 redisson.yaml
配置文件(在 src/main/resources
目录下):
singleServerConfig:
address: "redis://${spring.redis.host}:${spring.redis.port}"
password: ${spring.redis.password}
database: 0
配置 RedisTemplate(支持 Kotlin 序列化)
@Configuration
class RedisConfig {
@Bean
fun redisTemplate(redisConnectionFactory: RedisConnectionFactory): RedisTemplate<String, Any> {
val template = RedisTemplate<String, Any>()
template.connectionFactory = redisConnectionFactory
template.keySerializer = StringRedisSerializer()
template.valueSerializer = GenericJackson2JsonRedisSerializer(
ObjectMapper().registerModule(KotlinModule.Builder().build())
)
return template
}
// 自动注入 RedissonClient(通过 redisson-spring-boot-starter)
@Bean
fun redissonClient(): RedissonClient = Redisson.create()
}
3. 使用 RedisTemplate 示例
@Service
class RedisTemplateService(
private val redisTemplate: RedisTemplate<String, Any>
) {
fun saveUser(key: String, user: User) {
redisTemplate.opsForValue().set(key, user)
redisTemplate.expire(key, 1, TimeUnit.HOURS) // 设置过期时间
}
fun getUser(key: String): User? {
return redisTemplate.opsForValue().get(key) as? User
}
}
// 数据类需支持序列化
data class User(val id: String, val name: String)
4. 使用 RedissonClient 示例
Redisson 提供分布式对象和服务(如锁、集合、原子变量等):
@Service
class RedissonService(
private val redissonClient: RedissonClient
) {
// 使用分布式锁
fun performTaskWithLock(taskId: String) {
val lock = redissonClient.getLock("lock:$taskId")
try {
if (lock.tryLock(10, 60, TimeUnit.SECONDS)) {
// 执行需要加锁的任务
println("Lock acquired for task $taskId")
Thread.sleep(5000)
}
} finally {
lock.unlock()
println("Lock released for task $taskId")
}
}
// 操作分布式原子长整型
fun getNextId(): Long {
val atomicLong = redissonClient.getAtomicLong("user:id:counter")
return atomicLong.incrementAndGet()
}
}
5. 结合使用场景
场景 1:缓存用户 + 分布式 ID 生成
@Service
class UserService(
private val redisTemplateService: RedisTemplateService,
private val redissonService: RedissonService
) {
fun createUser(name: String): User {
val id = redissonService.getNextId().toString()
val user = User(id, name)
redisTemplateService.saveUser("user:$id", user)
return user
}
fun getUser(id: String): User? {
return redisTemplateService.getUser("user:$id")
}
}
场景 2:高并发下安全操作
@Service
class InventoryService(
private val redissonClient: RedissonClient
) {
fun decreaseStock(productId: String, quantity: Int) {
val lock = redissonClient.getLock("inventory:lock:$productId")
try {
if (lock.tryLock(3, 10, TimeUnit.SECONDS)) {
val stock = redissonClient.getAtomicLong("inventory:stock:$productId")
if (stock.get() >= quantity) {
stock.addAndGet(-quantity.toLong())
} else {
throw RuntimeException("库存不足")
}
}
} finally {
lock.unlock()
}
}
}
6. 配置注意事项
-
序列化兼容性:
•RedisTemplate
使用 JSON 序列化,确保数据类有无参构造或@JvmOverloads
注解。
• Redisson 默认使用org.redisson.codec.JsonJacksonCodec
,需与RedisTemplate
的序列化方式一致。 -
连接池配置:
在redisson.yaml
中优化连接池(示例):singleServerConfig: connectionPoolSize: 64 # 最大连接数 idleConnectionTimeout: 10000 # 空闲连接超时(毫秒) connectTimeout: 1000 # 连接超时
7. 核心区别
特性 | RedisTemplate | RedissonClient |
---|---|---|
定位 | Spring 标准操作(CRUD) | 分布式对象和服务(锁、集合等) |
序列化 | 需手动配置 JSON/Kryo | 内置多种编解码器(JSON、Avro) |
分布式锁 | 需自行实现 | 原生支持(RLock ) |
数据结构 | 基础操作(String/List/Set 等) | 分布式集合(RList /RMap 等) |
性能 | 较高(直接操作 Redis 命令) | 略低(封装了分布式逻辑) |
通过这种方式,可以灵活选择工具:
• 简单数据操作 → RedisTemplate
• 分布式场景(锁、限流、分布式集合) → RedissonClient
在 Spring Boot + Kotlin 中,RedisClient
通常指代不同 Redis 客户端的核心操作对象(如 Lettuce 的 RedisClient
、Redisson 的 RedissonClient
或 Spring Data Redis 的 RedisTemplate
)。以下是 常用方法分类整理,涵盖不同场景下的高频操作:
一、基础数据操作(以 RedisTemplate
为例)
1. Key 操作
// 检查 Key 是否存在
redisTemplate.hasKey("key")
// 设置过期时间
redisTemplate.expire("key", 60, TimeUnit.SECONDS)
// 删除 Key
redisTemplate.delete("key")
// 查询匹配的 Key(通配符 *)
val keys = redisTemplate.keys("user:*")
2. String 类型
// 设置值(支持任意对象)
redisTemplate.opsForValue().set("key", value)
// 获取值
val value = redisTemplate.opsForValue().get("key")
// 自增/自减(AtomicLong)
val counter = redisTemplate.opsForValue().increment("counter", 1)
3. Hash 类型
// 设置 Hash 字段
redisTemplate.opsForHash().put("user:1001", "name", "Alice")
// 获取 Hash 所有字段
val entries = redisTemplate.opsForHash().entries("user:1001")
// 删除 Hash 字段
redisTemplate.opsForHash().delete("user:1001", "age")
4. List 类型
// 左端插入元素
redisTemplate.opsForList().leftPush("task_queue", "task1")
// 右端弹出元素
val task = redisTemplate.opsForList().rightPop("task_queue")
// 获取列表范围
val tasks = redisTemplate.opsForList().range("task_queue", 0, 10)
5. Set 类型
// 添加元素
redisTemplate.opsForSet().add("user_tags:1001", "vip", "active")
// 查询交集
val commonTags = redisTemplate.opsForSet().intersect("user_tags:1001", "user_tags:1002")
// 判断元素是否存在
val isVip = redisTemplate.opsForSet().isMember("user_tags:1001", "vip")
二、高级功能(以 RedissonClient
为例)
1. 分布式锁
val lock = redissonClient.getLock("order:lock:1001")
try {
if (lock.tryLock(10, 60, TimeUnit.SECONDS)) {
// 执行业务逻辑
}
} finally {
lock.unlock()
}
2. 原子变量
// 原子自增
val atomicLong = redissonClient.getAtomicLong("global:counter")
val newValue = atomicLong.incrementAndGet()
// 原子 Double
val atomicDouble = redissonClient.getAtomicDouble("temperature")
atomicDouble.set(36.5)
3. 分布式集合
// 分布式 Map
val map: RMap<String, User> = redissonClient.getMap("users")
map.put("1001", User("Alice"))
// 分布式队列
val queue: RQueue<String> = redissonClient.getQueue("message_queue")
queue.offer("Hello")
val message = queue.poll()
4. 发布订阅
// 订阅频道
val topic = redissonClient.getTopic("news")
topic.addListener(String::class.java) { channel, msg ->
println("收到消息: $msg")
}
// 发布消息
topic.publish("Breaking News!")
三、实用工具方法
1. 批量操作
redisTemplate.executePipelined { connection ->
(1..100).forEach {
connection.stringCommands().set("key$it".toByteArray(), "value$it".toByteArray())
}
null
}
2. 事务支持
redisTemplate.execute { session ->
session.multi() // 开启事务
session.opsForValue().set("key1", "A")
session.opsForValue().increment("counter", 1)
session.exec() // 提交事务
null
}
3. Lua 脚本
val script = """
local current = redis.call('GET', KEYS[1])
if current == ARGV[1] then
return redis.call('SET', KEYS[1], ARGV[2])
end
return nil
"""
val result = redisTemplate.execute(
RedisScript.of(script, String::class.java),
listOf("key"), "oldValue", "newValue"
)
四、最佳实践
1. 序列化配置
确保数据类可序列化:
// Kotlin 数据类 + 无参构造(通过默认值)
data class User(
val id: String = "",
val name: String = ""
)
2. 连接池优化
在 application.yml
中配置 Lettuce 连接池:
spring:
redis:
lettuce:
pool:
max-active: 16 # 最大连接数
max-idle: 8 # 最大空闲连接
min-idle: 2 # 最小空闲连接
3. 选择客户端优先级
• 简单操作 → RedisTemplate
(Spring 原生支持)
• 分布式场景 → RedissonClient
(锁、原子操作、集合)
• 极致性能 → 直接使用 Lettuce 的 RedisClient
通过合理使用这些方法,可以覆盖 Redis 的 数据存储、缓存、队列、分布式协调 等核心场景。