当前位置: 首页 > news >正文

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. 配置注意事项

  1. 序列化兼容性
    RedisTemplate 使用 JSON 序列化,确保数据类有无参构造或 @JvmOverloads 注解。
    • Redisson 默认使用 org.redisson.codec.JsonJacksonCodec,需与 RedisTemplate 的序列化方式一致。

  2. 连接池配置
    redisson.yaml 中优化连接池(示例):

    singleServerConfig:
      connectionPoolSize: 64      # 最大连接数
      idleConnectionTimeout: 10000 # 空闲连接超时(毫秒)
      connectTimeout: 1000        # 连接超时
    

7. 核心区别

特性RedisTemplateRedissonClient
定位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 的 数据存储、缓存、队列、分布式协调 等核心场景。

相关文章:

  • Python:互斥锁,线程同步及总结
  • 脑启发式AI Agent:解锁人类大脑奥秘,迈向真正的通用人工智能(AGI)
  • Dify - 架构、部署、扩展与二次开发指南
  • 大模型概述
  • spring-security原理与应用系列:总体流程
  • Web Workers 教程
  • 前端知识点---innerHTML和innerText
  • Turtle基本操作(前进、后退、旋转)
  • QT零基础学习之路(十)--QDialog对话框的使用及信息传递
  • el-tree树多选,将选中的树对象中某个字段值改为true,并过滤出所有为true的对象,组成新的数组
  • 开源图生视频模型技术全景解析
  • QT学习笔记(对话框)
  • Next.Js 权限绕过漏洞复现(附脚本)(CVE-2025-29927)
  • Vue打包后如何在本地进行测试(附解决浏览器刷新无法访问的问题)
  • 【数据库-复试】sql语句综合练习
  • Mysql--日志(错误日志、二进制日志、查询日志、慢查询日志)
  • 使用 fn_dblog手动恢复误操作的 update(单列数值型数据恢复)
  • 用卡片笔记要改变写作习惯
  • (并查集 省份数量)leetcode 547
  • Sqladmin - FastAPI框架下一键生成管理后台
  • 中国田径巡回赛西安站完赛:男子跳远石雨豪夺冠
  • 多图|多款先进预警机亮相雷达展,专家:中国预警机已达世界先进水平
  • 河南一女子被医院强制带走治疗,官方通报:当值医生停职
  • 试点首发进口消费品检验便利化措施,上海海关与上海商务委发文
  • 刘小涛任江苏省委副书记
  • 俄乌官员即将在土耳其会谈,外交部:支持俄乌开启直接对话