redis总结

一、Redis 命令基础

Redis 是键值(Key-Value)型内存数据库,命令具有以下特点:

  • 命令不区分大小写(如 GET/get 都生效),但Key/Value 区分大小写
  • 命令参数用空格分隔,部分命令支持可选参数(如过期时间);
  • 所有命令都围绕 "操作 Key 或 Key 对应的 Value" 展开。

二、核心命令分类讲解

1. 通用命令(所有数据类型通用)

这类命令用于管理 Key 本身,与 Value 类型无关,是最基础的操作。

命令 作用 示例(结合设备状态场景)
KEYS pattern 按通配符匹配查询所有 Key(生产环境慎用,会阻塞 Redis) KEYS device:status:GW001:* → 查 GW001 设备所有从机状态 Key
EXISTS key 判断 Key 是否存在(返回 1 = 存在,0 = 不存在) EXISTS device:status:GW001:03 → 检查 03 从机状态是否缓存
DEL key [key...] 删除指定 Key(返回删除成功的数量) DEL device:status:GW001:03 → 删除 03 从机状态缓存
EXPIRE key sec 为 Key 设置过期时间(单位:秒,返回 1 = 成功,0=Key 不存在) EXPIRE device:status:GW001:03 3600 → 1 小时过期
TTL key 查询 Key 的剩余过期时间(返回秒数;-1 = 永不过期;-2=Key 不存在) TTL device:status:GW001:03 → 查看剩余过期时间
PERSIST key 移除 Key 的过期时间(设为永不过期) PERSIST device:status:GW001:03 → 取消过期
RENAME old new 重命名 Key(若 new 已存在则覆盖) RENAME device:status:GW001:03 device:status:GW001:04
2. 字符串(String)命令

String 是 Redis 最基础的 Value 类型,可存储字符串、数字、序列化对象(如我代码中的 DeviceStatusCacheDTO),即之前 saveDeviceStatus 中使用的类型。

命令 作用 示例(设备状态场景)
SET key value [EX sec] 设置 Key-Value,可选 EX 指定过期时间(秒) SET device:status:GW001:03 "online" EX 3600
SETNX key value 仅当 Key 不存在时设置(避免覆盖,返回 1 = 成功,0 = 失败) SETNX device:status:GW001:03 "online"
GET key 获取 Key 对应的 Value(返回 null 表示 Key 不存在) GET device:status:GW001:03 → 获取 03 从机状态
MSET key1 v1 key2 v2... 批量设置多个 Key-Value(效率高于多次 SET) MSET a 1 b 2 c 3
MGET key1 key2... 批量获取多个 Key 的 Value(返回值数组) MGET a b c → ["1","2","3"]
INCR key 将 Key 的数值 Value 自增 1(非数字则报错) INCR alarm:count:GW001 → 统计 GW001 告警次数
INCRBY key num 数值 Value 自增指定数(如 INCRBY key 5) INCRBY alarm:count:GW001 2 → 告警次数 + 2
DECR key/DECRBY key num 数值 Value 自减 1 / 指定数(与 INCR 对应) DECR alarm:count:GW001

我的代码关联redisTemplate.opsForValue().set(key, status, expire, unit) 底层就是调用 SET key value EX 过期秒数 命令。

3. 哈希(Hash)命令

Hash 用于存储 "Key - 字段 - 值" 的二维结构,适合存储单个对象的多个属性(如设备状态的多个字段),比 String 存储序列化对象更灵活(可单独修改某个字段)。

命令 作用 示例(设备状态场景)
HSET key field value 给 Hash Key 设置指定字段的值(字段不存在则新增,存在则覆盖) HSET device:status:GW001:03 online_status 1
HGET key field 获取 Hash Key 中指定字段的值 HGET device:status:GW001:03 online_status → 1
HMSET key f1 v1 f2 v2... 批量设置 Hash Key 的多个字段值 HMSET device:status:GW001:03 power 0 battery 0
HMGET key f1 f2... 批量获取 Hash Key 的多个字段值 HMGET device:status:GW001:03 power battery → ["0","0"]
HGETALL key 获取 Hash Key 的所有字段和值(返回 [f1,v1,f2,v2...] 数组) HGETALL device:status:GW001:03 → 所有状态字段
HDEL key field [field...] 删除 Hash Key 的指定字段 HDEL device:status:GW001:03 rssi
HEXISTS key field 判断 Hash Key 中指定字段是否存在 HEXISTS device:status:GW001:03 online_status → 1
4. 列表(List)命令

List 是双向链表结构,适合存储有序的一组数据(如设备告警日志、消息队列)。

命令 作用 示例
LPUSH key value... 从列表左侧(头部)添加元素(返回列表长度) LPUSH alarm:log:GW001 "2025-11-11 14:35 离线"
RPUSH key value... 从列表右侧(尾部)添加元素 RPUSH alarm:log:GW001 "2025-11-11 14:40 恢复"
LPOP key 从列表左侧弹出并返回元素(列表空则返回 null) LPOP alarm:log:GW001 → 获取最新告警日志
RPOP key 从列表右侧弹出并返回元素 RPOP alarm:log:GW001 → 获取最早告警日志
LRANGE key start end 获取列表指定范围元素(0 = 第一个,-1 = 最后一个) LRANGE alarm:log:GW001 0 -1 → 所有告警日志
LLEN key 获取列表长度 LLEN alarm:log:GW001 → 告警日志条数
5. 集合(Set)命令

Set 用于存储不重复的元素,支持交集、并集、差集等集合运算(如存储设备关联的用户 ID、设备标签)。

命令 作用 示例
SADD key member... 向集合添加元素(返回新增元素数量,重复元素会忽略) SADD device:tag:GW001 "温湿度" "养殖舍"
SMEMBERS key 获取集合所有元素 SMEMBERS device:tag:GW001 → ["温湿度","养殖舍"]
SISMEMBER key member 判断元素是否在集合中(1 = 是,0 = 否) SISMEMBER device:tag:GW001 "温湿度" → 1
SREM key member... 从集合删除指定元素 SREM device:tag:GW001 "养殖舍"
SINTER key1 key2 获取多个集合的交集(共同元素) SINTER device:tag:GW001 device:tag:GW002
SUNION key1 key2 获取多个集合的并集(所有元素) SUNION device:tag:GW001 device:tag:GW002
6. 有序集合(ZSet)命令

ZSet 是 Set 的升级版,每个元素关联一个分数(score),按分数排序(如设备告警优先级、排行榜)。

命令 作用 示例
ZADD key score member... 向有序集合添加元素(分数为数字,重复元素会更新分数) ZADD alarm:priority 10 "GW001:03 离线" 5 "GW001:03 低电"
ZRANGE key start end [WITHSCORES] 按分数升序获取指定范围元素(加 WITHSCORES 显示分数) ZRANGE alarm:priority 0 -1 WITHSCORES → 按优先级升序
ZREVRANGE key start end [WITHSCORES] 按分数降序获取指定范围元素 ZREVRANGE alarm:priority 0 -1 → 高优先级在前
ZSCORE key member 获取元素的分数 ZSCORE alarm:priority "GW001:03 离线" → 10
ZREM key member... 删除有序集合中的元素 ZREM alarm:priority "GW001:03 离线"

三、生产环境注意事项

  1. 避免使用 KEYS *KEYS 命令会遍历所有 Key,Redis 是单线程,会阻塞其他操作,生产环境可用 SCAN 命令(分批遍历)替代;
  2. 设置过期时间 :所有缓存 Key 建议设置过期时间(如你代码中的 DEVICE_STATUS_EXPIRE_HOURS),避免 Redis 内存溢出;
  3. 批量操作优先 :用 MSET/HMSET 等批量命令替代多次单条命令,减少网络交互开销;
  4. 命令原子性:Redis 单条命令是原子性的(执行过程不会被打断),适合做分布式锁、计数器等场景。

java中使用redis

1、引入依赖

bash 复制代码
<!-- Spring Boot Redis 起步依赖,自动整合 RedisTemplate -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

核心作用:自动引入 Redis 客户端(Lettuce 作为默认客户端)、Spring 封装的 RedisTemplate/StringRedisTemplate,无需手动管理依赖版本。

2、配置 Redis 连接(application.yml)

java 复制代码
spring:
  data:
    redis:
      host: localhost
      port: 6379
      database: 0
      password: 1234

3、配置序列化器(可选但强烈推荐)

Spring Boot 自带的 RedisTemplate 默认使用 JDK 序列化,会导致 Redis 中存储的 Key/Value 乱码(如出现 \xAC\xED\x00\x05t\x00\x0Edevice:status:GW001:03),因此需要自定义序列化配置:

java 复制代码
/**
 * Redis 序列化配置类
 * 
 * 【类核心信息】
 * 1. 作用:自定义 RedisTemplate 的序列化规则,替换默认 JDK 序列化,使用 JSON 序列化保证数据可读性和对象兼容性
 * 2. 依赖:Spring Data Redis 核心组件(RedisConnectionFactory)、Jackson 序列化组件
 * 3. 核心产出:配置好序列化规则的 RedisTemplate<String, Object> Bean,供业务层自动注入使用
 * 4. 适用场景:存储自定义 Java 对象(如 DeviceStatusCacheDTO、List<AlarmRecordVO>)到 Redis,避免序列化乱码/失败
 */
@Configuration
public class RedisConfig {
    // 核心 Bean 配置方法(见下文拆解)
}

redisTemplate 方法 :

设计目标:构建支持 JSON 序列化的 RedisTemplate,适配自定义 Java 对象的存储/读取,解决默认序列化乱码问题。

1、参数:RedisConnectionFactory connectionFactory ( 必传)

Redis 连接工厂(Spring 自动注入,封装 Redis 连接信息)

2、返回值:

RedisTemplate<String, Object> 配置完成的 Redis 操作模板,可直接注入到 Service 层使用

java 复制代码
1、初始化 RedisTemplate 并绑定连接工厂(保证模板能连接到 Redis 服务器)
2、配置 Jackson 的 ObjectMapper
3、创建序列化器并绑定到 ObjectMapper
4、为 RedisTemplate 设置序列化规则
5、初始化模板并返回
​
​
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
    // 原函数逻辑(省略)
}

4、注入并使用 RedisTemplate

java 复制代码
@Service
public class RedisService {
    // 通用对象模板(支持存储自定义对象,如 DeviceStatusCacheDTO)
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    
    // 字符串专用模板(仅存储 String 类型,无需序列化)
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
}

Spring Boot 中 Redis 核心 API 详解

方法 对应 Redis 数据类型 核心作用
opsForValue() String(字符串) 操作单个 Key-Value,支持过期时间
opsForHash() Hash(哈希) 操作 Hash 类型的 Key - 字段 - 值
opsForList() List(列表) 操作有序列表(LPUSH/RPUSH/LPOP 等)
opsForSet() Set(集合) 操作无序不重复集合
opsForZSet() ZSet(有序集合) 操作带分数的有序集合
keys(pattern) 通用命令 按通配符匹配 Key
delete(key) 通用命令 删除指定 Key

opsForValue() 是你代码中使用最多的 API,对应 Redis 的 SET/GET/EXPIRE 等命令:

序列化器介绍

一、什么是序列化器?

1、序列化器(Serializer)是将 "内存中的 Java 对象" 和 "字节流 / 字符串" 相互转换的工具: 序列化:把内存中的 Java 对象(如 DeviceStatusCacheDTO)转换成可存储(Redis / 文件)、可传输(网络)的字节流 / 字符串; 反序列化:把存储 / 传输的字节流 / 字符串还原为内存中的 Java 对象。

2、为什么 Redis 需要序列化器? Redis 是键值数据库,只能存储字节序列(二进制数据),无法直接存储 Java 对象。因此 RedisTemplate 操作 Redis 时,必须通过序列化器: 存储对象:Java 对象 → 序列化器 → 字节流 → 存入 Redis; 获取对象:Redis 字节流 → 序列化器 → Java 对象 → 返回给业务代码。

二、JDK 序列化器 vs Jackson JSON 序列化器

对于jdk序列化起的乱码原因:

1、 Key 乱码的原因

JDK 序列化器对 Key(String 类型)的序列化逻辑: 1)先将 String 作为一个 Java 对象序列化,会在字节 流开头添加 序列化魔数(\xAC\xED)、版本号(00\x05)、类型标识(t 表示字符串)等额外二进制数据; 2)最终 Redis 中看到的 Key 是 "二进制前缀 + 实际字符串字节",用 Redis 客户端查看时,二进制前缀会显示为乱码(如 ��tdevice:GW001:03)。

2、 Value 乱码的原因

  • JDK 序列化 Value 时,会把整个 Java 对象(包括类的全限定名、字段类型、访问修饰符、序列化版本号等元数据)转换成二进制字节流;

  • 这些二进制字节流在 Redis 客户端中会被解析为乱码字符(如 �sr�com.xxx.DeviceStatusCacheDTO����),人类无法识别,也无法手动排查问题。

举个实际例子 存储 DeviceStatusCacheDTO(deviceAddr=GW001,onlineStatus=0): 1)JDK 序列化后 Redis 中的 Value:\xAC\xED\x00\x05sr\x00&com.xxx.DeviceStatusCacheDTO\x00\x00\x00\x00\x00\x00\x00\x01\x02\x00\x02L\x00\ndeviceAddrt\x00\x12Ljava/lang/String;L\x00\nonlineStatusI\x00\x00\x00\x00xp\x00\x00\x00\x00t\x00\x04GW001(完全不可读); 2)Jackson 序列化后 Redis 中的 Value:{"@class":"com.xxx.DeviceStatusCacheDTO","deviceAddr":"GW001","onlineStatus":0}(明文可直接看懂)。 】

三、总结:

1、Redis 存储的所有数据最终都是二进制字节流(包括字符串、数字),这是 Redis 的底层存储特性;

2、Redis 本身确实只存储二进制字节流,但 "乱码" 的核心不是 "二进制本身",而是 JDK 序列化的二进制包含大量 "Java 专属的元数据",这些元数据对 Redis 客户端(按 "通用字符串" 解析)来说是无意义的二进制垃圾,所以显示为乱码。

JDK 序列化的二进制 = Java 类元数据(魔数、版本号、类名、字段类型) + 实际数据字节 3、

bash 复制代码
Jackson 序列化 → 把 Java 对象转成 JSON 字符串(表现层,人类可读)
↓
String 转二进制 → JSON 字符串按 UTF-8 编码转成二进制字节流(存储层,Redis 能存)
↓
Redis 存储 → 仅存储这个"纯数据的二进制字节流"
↓
反序列化 → 从 Redis 读取二进制字节流 → 按 UTF-8 转成 JSON 字符串 → Jackson 转成 Java 对象
序列化方式 业务层看到的形态 底层存储的形态 Redis 客户端解析结果
JDK 序列化器 Java 对象 带 Java 元数据的二进制字节流 乱码(无法识别元数据二进制)
Jackson + String JSON 字符串 纯 JSON 字符串的 UTF-8 二进制 明文 JSON(可读)
相关推荐
少许极端3 小时前
Redis入门指南(六):从零到分布式缓存-数据持久化与事务
redis·分布式·缓存·事务·持久化
Charlie_lll3 小时前
RAG+ReAct 智能体深度重构|从「固定三步执行」到「动态思考-行动循环」
人工智能·spring boot·redis·后端·ai·重构
Leon-zy4 小时前
Redis7.4.5集群部署3主3从
redis·分布式·缓存·云原生
alonewolf_995 小时前
深入理解Redis线程模型:单线程神话与原子性实战
数据库·redis·缓存·分布式架构
小北方城市网5 小时前
SpringBoot 集成 Redis 实战(缓存优化与分布式锁):打造高可用缓存体系与并发控制
java·spring boot·redis·python·缓存·rabbitmq·java-rabbitmq
万象.5 小时前
redis数据结构hash的基本指令
数据结构·redis·哈希算法
小北方城市网5 小时前
SpringBoot 集成 Elasticsearch 实战(全文检索与聚合分析):打造高效海量数据检索系统
java·redis·分布式·python·缓存
alonewolf_995 小时前
Redis Stack全面解析:从JSON存储到布隆过滤器,打造高性能Redis扩展生态
数据库·redis·json
衫水13 小时前
ubuntu系统如何检查和安装以及运行redis
redis·ubuntu·bootstrap