Redis 除了数据类型外的核心功能 的详细说明,包含事务、流水线、发布/订阅、Lua 脚本的完整代码示例和表格总结

以下是 Redis 除了数据类型外的核心功能 的详细说明,包含事务、流水线、发布/订阅、Lua 脚本的完整代码示例和表格总结:


1. Redis 事务(Transactions)

功能描述

事务通过 MULTIEXEC 命令将一组命令打包执行,保证命令的原子性(非严格原子性)。事务中的命令会被顺序执行,但中间可能被其他客户端命令插入。

代码示例
java 复制代码
@Service
public class RedisTransactionService {
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    // 使用事务操作
    public void transactionExample() {
        redisTemplate.multi(); // 开启事务
        try {
            // 添加多个命令到事务队列
            redisTemplate.opsForValue().set("key1", "value1");
            redisTemplate.opsForValue().increment("counter", 1);
            
            // 提交事务
            List<Object> results = redisTemplate.exec();
            System.out.println("事务执行结果:" + results);
        } catch (Exception e) {
            redisTemplate.discard(); // 回滚事务
            throw e;
        }
    }
}
注意事项
  • 事务中的命令若失败,后续命令仍会执行。
  • 使用 exec() 提交后,返回所有命令的执行结果列表。

2. Redis 流水线(Pipeline)

功能描述

流水线将多个命令批量发送到 Redis 服务器,减少网络往返延迟,提升性能。适用于批量操作(如批量读写)。

代码示例
java 复制代码
@Service
public class RedisPipelineService {
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    // 使用流水线批量操作
    public void pipelineExample() {
        redisTemplate.executePipelined((RedisConnection connection) -> {
            connection.set("key1".getBytes(), "value1".getBytes());
            connection.set("key2".getBytes(), "value2".getBytes());
            connection.set("key3".getBytes(), "value3".getBytes());
            return null;
        });
    }
}
注意事项
  • 流水线通过 executePipelined 方法实现,需操作底层 RedisConnection
  • 批量操作需自行处理字节序列化。

3. Redis 发布/订阅(Pub/Sub)

功能描述

用于实时消息通信:

  • 发布者:向频道(channel)发送消息。
  • 订阅者:监听指定频道的消息。
代码示例
3.1 发布者
java 复制代码
@Service
public class RedisPublisherService {
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    // 发布消息到频道
    public void publishMessage(String channel, String message) {
        redisTemplate.convertAndSend(channel, message);
    }
}
3.2 订阅者
java 复制代码
@Configuration
public class RedisSubscriberConfig {
    @Bean
    public RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory) {
        RedisMessageListenerContainer container = new RedisMessageListenerContainer();
        container.setConnectionFactory(connectionFactory);
        container.addMessageListener(new MessageListener() {
            @Override
            public void onMessage(Message message, byte[] pattern) {
                String channel = new String(message.getChannel());
                String payload = new String(message.getBody());
                System.out.println("收到消息:频道[" + channel + "],内容[" + payload + "]");
            }
        }, new PatternTopic("channel:*")); // 订阅所有以 "channel:" 开头的频道
        return container;
    }
}
注意事项
  • 需配置 RedisMessageListenerContainer 监听消息。
  • 消息不会持久化,客户端断开后未接收的消息会丢失。

4. Redis Lua 脚本(Lua Scripting)

功能描述

通过 Lua 脚本实现 原子性操作,适用于需要严格一致性的场景(如分布式锁、库存扣减)。Lua 脚本在 Redis 服务端单线程执行,确保原子性。

代码示例
4.1 示例脚本:库存扣减
lua 复制代码
-- Lua 脚本:扣减库存,仅当库存大于0时扣减
local stock = tonumber(redis.call("GET", KEYS[1]))
if stock and stock > 0 then
    redis.call("DECR", KEYS[1])
    return stock - 1
else
    return -1 -- 库存不足
end
4.2 Spring Boot 调用 Lua 脚本
java 复制代码
@Service
public class RedisLuaService {
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    // 执行 Lua 脚本(库存扣减)
    public Long deductStock(String stockKey) {
        DefaultRedisScript<Long> script = new DefaultRedisScript<>();
        script.setScriptText(loadLuaScript("deduct_stock.lua")); // 加载脚本内容
        script.setResultType(Long.class);
        
        return redisTemplate.execute(
            script, 
            Collections.singletonList(stockKey), 
            new Object[]{});
    }

    // 加载 Lua 脚本内容(示例)
    private String loadLuaScript(String scriptName) {
        // 实际开发中可从文件或资源加载
        return "local stock = tonumber(redis.call('GET', KEYS[1])) ..."; // 省略脚本内容
    }
}
注意事项
  • 脚本在 Redis 服务端执行,需确保脚本逻辑正确。
  • 可通过 SHA1 哈希缓存脚本,减少传输开销。

5. 总结表格

功能 描述 代码方法 适用场景
事务 将一组命令打包执行,保证顺序性,但非严格原子性。 redisTemplate.multi()redisTemplate.exec() 需要命令顺序执行但允许部分失败的场景。
流水线 批量发送命令,减少网络延迟。 redisTemplate.executePipelined() 大批量读写操作(如批量插入、查询)。
发布/订阅 实时消息通信,支持频道或模式订阅。 redisTemplate.convertAndSend()RedisMessageListenerContainer 实时通知(如订单状态更新、聊天消息)。
Lua 脚本 在 Redis 服务端原子性执行复杂逻辑,确保数据一致性。 redisTemplate.execute(script, keys, args) 需要严格原子性的操作(如分布式锁、扣减库存)。

6. 关键点总结

  1. 事务 vs Lua 脚本

    • 事务提供顺序执行,但非原子性(中间可能被其他命令中断)。
    • Lua 脚本确保原子性,适合需要严格一致性的场景。
  2. 流水线优化

    • 批量操作时,流水线可显著提升性能(减少网络 RTT)。
  3. 发布/订阅

    • 适用于实时消息通信,但需注意消息丢失风险(客户端断开时未接收的消息会丢失)。
  4. Lua 脚本注意事项

    • 脚本在服务端执行,需谨慎设计逻辑(避免死循环或高耗时操作)。
    • 可通过 EVALSHA 命令缓存脚本,减少传输开销。

通过合理使用这些功能,可以解决高并发场景下的性能、一致性和实时性挑战。

相关推荐
启明真纳5 分钟前
PostgreSQL 单库备份
数据库·postgresql
Amd79418 分钟前
PostgreSQL备份不是复制文件?物理vs逻辑咋选?误删还能精准恢复到1分钟前?
数据库·postgresql
wzg201624 分钟前
pyqt5 简易入门教程
开发语言·数据库·qt
你是狒狒吗3 小时前
为什么mysql要有主从复制,主库,从库这种东西
数据库·mysql
倔强的石头1066 小时前
【金仓数据库】ksql 指南(一) 连接本地 KingbaseES 数据库与基础交互
数据库·oracle·kingbasees·金仓数据库·ksql
卷Java11 小时前
违规通知功能修改说明
java·数据库·微信小程序·uni-app
养生技术人11 小时前
Oracle OCP认证考试题目详解082系列第54题
数据库·sql·oracle·运维开发·database·开闭原则·ocp
数据知道12 小时前
Go基础:用Go语言操作MongoDB详解
服务器·开发语言·数据库·后端·mongodb·golang·go语言
爱喝白开水a12 小时前
2025时序数据库选型,从架构基因到AI赋能来解析
开发语言·数据库·人工智能·架构·langchain·transformer·时序数据库