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

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


http://www.kler.cn/a/600211.html

相关文章:

  • AI大模型全攻略:原理 · 部署 · Prompt · 场景应用
  • 大数据E10:基于Spark和Scala编程解决一些基本的数据处理和统计分析,去重、排序等
  • 【Vue3入门1】01-Vue3的基础 + ref reactive
  • Golang 老题,生产者和消费者模型,先后关闭通道的问题
  • STM32 ADC和DAC详解
  • [React 进阶系列] 组合组件 复合组件
  • 矩阵指数的定义和基本性质
  • [实操]Mysql8 InnoDB引擎主从配置三节点操作流程
  • LeetCode热题100_最长连续序列
  • 保姆级 STM32 HAL 库外部中断教学
  • 使用 Ansible 通过源码编译安装 Nginx 的完整步骤。
  • CSS网格布局Grid
  • C# WinForms 中的回调:从性能到技术层面的全面解析
  • Netty源码—3.Reactor线程模型四
  • 【Qt】QDialog对话框
  • SQL语句---DDL
  • 买卖股票的最佳时机 IV (leetcode 188)
  • 基于SpringBoot的汽车租赁系统
  • 消息队列ActiveMQ、RabbitMQ、RocketMQ、Kafka对比分析和选型
  • 第八:在Go语言项目中使用Zap日志库