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(可读)
相关推荐
海兰32 分钟前
【高速缓存】RedisVL 高级查询(全文搜索、混合搜索和 多向量搜索)
数据库·人工智能·redis·缓存
记录者t3 小时前
redis常见问题:大key
数据库·redis
青石路3 小时前
如果写Redis序列化与读Redis序列化不一致,你觉得会发生什么
java·redis
難釋懷4 小时前
Nginx代理https请求
redis·nginx·https
流星白龙13 小时前
【Redis】2.Redis重大版本
数据库·redis·junit
流星白龙13 小时前
【Redis】7.Hash表
数据库·redis·哈希算法
流星白龙14 小时前
【Redis】4.基本全局命令
数据库·redis·缓存
流星白龙17 小时前
【Redis】3.Redis安装与命令行客户端
数据库·redis·缓存
Season45021 小时前
Redis命令 (generic即通用命令)
数据库·redis·bootstrap