本文基于官方规范与企业实战整理,无冗余、无错误、结构清晰,覆盖 Redis 基础、命令、SpringBoot 整合、事务锁、秒杀、持久化、主从、哨兵、集群、高可用运维全流程。

目录

  1. Redis 与 NoSQL 概述
  2. Redis 安装与配置(Windows/Linux)
  3. Redis 常用 5 大数据结构与命令
  4. SpringBoot 整合 Redis(标准版配置)
  5. Redis 持久化:RDB + AOF
  6. Redis 事务与锁机制(核心)
  7. 高并发秒杀实战(解决超卖)
  8. 缓存三大问题:穿透/击穿/雪崩
  9. Redis 实现 SSO 单点登录
  10. 主从复制部署
  11. 哨兵模式(自动故障转移)
  12. Redis Cluster 集群部署
  13. 性能优化与运维规范

1. Redis 与 NoSQL 概述

1.1 什么是 NoSQL

NoSQL = Not Only SQL,泛指非关系型数据库,用于解决高并发、海量数据、高扩展场景。

  • 不遵循标准 SQL
  • 不支持严格 ACID
  • 性能远超关系型数据库

1.2 主流 NoSQL 对比

  • Memcache:纯内存、简单 KV、不支持持久化
  • Redis:内存为主、支持持久化、多数据结构、企业首选缓存
  • MongoDB:文档型、支持复杂查询、适合海量非结构化数据

1.3 Redis 是什么

Redis 是开源、高性能、基于内存的 Key-Value 数据库,支持:

  • 多数据结构
  • 持久化
  • 主从/哨兵/集群
  • 事务、Lua 脚本
  • 高并发读写(10W QPS+)

典型场景:缓存、秒杀、分布式锁、会话、消息队列、排行榜。

2. Redis 安装与配置

2.1 Linux 安装(标准步骤)

# 安装依赖
yum install -y gcc-c++
# 下载解压
cd /opt
wget https://download.redis.io/releases/redis-6.2.5.tar.gz
tar -zxvf redis-6.2.5.tar.gz
cd redis-6.2.5

# 编译安装
make
make install

2.2 后台运行配置

mkdir -p /usr/local/redis/config
cp /opt/redis-6.2.5/redis.conf /usr/local/redis/config/

# 修改配置
vim /usr/local/redis/config/redis.conf

核心配置:

daemonize yes       # 后台运行
bind 0.0.0.0        # 允许远程
protected-mode no   # 关闭保护模式
requirepass 123456  # 密码
port 6379

2.3 启动/关闭/连接

# 启动
redis-server /usr/local/redis/config/redis.conf

# 客户端连接
redis-cli -p 6379 -a 123456

# 关闭
redis-cli -a 123456 shutdown

2.4 远程访问配置

  • 注释 bind 127.0.0.1
  • protected-mode no
  • 防火墙开放 6379 端口
  • 设置密码 requirepass

3. Redis 5 大数据结构与常用命令

Redis 默认 16 个库,默认使用 db0。

select 0        # 切换库
dbsize          # 查看 key 数量
flushdb         # 清空当前库
flushall        # 清空所有库
exists key       # 是否存在
type key        # 查看类型
expire key 10    # 10秒过期
ttl key          # 查看剩余时间

3.1 String(字符串)

  • 二进制安全,最大 512MB
  • 适用:缓存、计数器、分布式锁
set k1 v1
get k1
incr k1       # 自增(计数器)
decr k1       # 自减
setnx k1 v1   # 不存在则设置(分布式锁)

3.2 List(列表)

  • 双向链表、有序、可重复
  • 适用:队列、栈、消息队列
lpush list a b c
rpush list d
lrange list 0 -1  # 查看全部
lpop list
rpop list

3.3 Set(集合)

  • 无序、唯一、自动去重
  • 适用:去重、交集/并集/差集、抽奖
sadd set a b c
smembers set    # 查看所有
sismember set a # 是否存在
sinter set1 set2 # 交集
spop set        # 随机弹出(抽奖)

3.4 Hash(哈希)

  • key-field-value,适合存对象
  • 适用:用户信息、商品信息
hset user name zhang age 20
hget user name
hgetall user
hkeys user
hvals user

3.5 ZSet(有序集合)

  • 按 score 排序、元素唯一
  • 适用:排行榜、热度排序
zadd top 100 java 200 mysql
zrange top 0 -1 withscores
zrevrange top 0 -1 withscores # 倒序
zrank top java # 排名

4. SpringBoot 整合 Redis(企业标准版)

4.1 依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-pool2</artifactId>
</dependency>

4.2 application.yml

spring:
  redis:
    host: 127.0.0.1
    port: 6379
    password: 123456
    database: 0
    lettuce:
      pool:
        max-active: 8
        max-idle: 8
        min-idle: 0
        max-wait: -1ms

4.3 RedisTemplate 配置(解决乱码)

@Configuration
public class RedisConfig {
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(factory);
        StringRedisSerializer stringSerializer = new StringRedisSerializer();
        Jackson2JsonRedisSerializer<Object> jacksonSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL);
        jacksonSerializer.setObjectMapper(om);
        template.setKeySerializer(stringSerializer);
        template.setValueSerializer(jacksonSerializer);
        template.setHashKeySerializer(stringSerializer);
        template.setHashValueSerializer(jacksonSerializer);
        template.afterPropertiesSet();
        return template;
    }
}

4.4 常用操作

// String
redisTemplate.opsForValue().set("name", "zhangsan");
// Hash
redisTemplate.opsForHash().put("user", "age", 20);
// List
redisTemplate.opsForList().leftPush("list", "a");
// Set
redisTemplate.opsForSet().add("set", "a");
// ZSet
redisTemplate.opsForZSet().add("zset", "java", 100);

5. Redis 持久化:RDB + AOF

Redis 基于内存,必须开启持久化防止重启丢数据

5.1 RDB(快照)

  • 定时把内存数据保存为 dump.rdb
  • 优点:恢复快、文件小
  • 缺点:可能丢最后一次快照数据

配置:

save 900 1
save 300 10
save 60 10000
dbfilename dump.rdb
dir ./

5.2 AOF(日志追加)

  • 记录每一条写命令
  • 优点:数据安全
  • 缺点:文件大、恢复慢

配置:

appendonly yes
appendfilename "appendonly.aof"
appendfsync everysec

5.3 企业最佳实践

  • 纯缓存:RDB
  • 交易/库存/登录:RDB + AOF 同时开启

6. Redis 事务与锁机制(核心)

6.1 Redis 事务特性

  • 批量命令入队、顺序执行
  • 执行中不被打断
  • 不支持回滚
  • 不保证严格原子性

6.2 事务命令

MULTI     # 开启事务
SET k1 v1
INCR k2
EXEC      # 执行
DISCARD   # 放弃

6.3 乐观锁 WATCH(高并发必备)

Redis 无悲观锁,只用乐观锁解决并发冲突。

  • WATCH key:监控 key,若被修改则事务中断
  • 秒杀、库存扣减必须使用
SET stock 10
WATCH stock
MULTI
DECR stock
EXEC

7. 高并发秒杀实战(解决超卖)

7.1 需求

  • 库存 10
  • 100 人并发抢购
  • 禁止超卖、禁止重复购买

7.2 核心方案

  • WATCH 监控库存
  • Redis 事务保证原子性
  • SessionCallback 批量执行

7.3 最终代码(无超卖)

@RestController
public class SecKillController {
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @PostMapping("/seckill")
    public Result secKill() {
        String userId = String.valueOf(new Random().nextInt(10000));

        SessionCallback callback = new SessionCallback() {
            @Override
            public Object execute(RedisOperations operations) {
                // 监控库存
                stringRedisTemplate.watch("stock");
                String stock = stringRedisTemplate.opsForValue().get("stock");

                if (stock == null || Integer.parseInt(stock) <= 0) {
                    return Result.fail("已售罄");
                }
                // 判断是否重复购买
                Boolean bought = stringRedisTemplate.opsForSet().isMember("buy_users", userId);
                if (Boolean.TRUE.equals(bought)) {
                    return Result.fail("已购买");
                }
                // 开启事务
                stringRedisTemplate.multi();
                stringRedisTemplate.opsForValue().decrement("stock");
                stringRedisTemplate.opsForSet().add("buy_users", userId);
                return stringRedisTemplate.exec();
            }
        };

        List result = (List) stringRedisTemplate.execute(callback);
        if (result == null || result.isEmpty()) {
            return Result.fail("抢购失败");
        }
        return Result.ok("抢购成功");
    }
}

8. 缓存三大问题:穿透/击穿/雪崩

8.1 缓存穿透

  • 现象:查不存在的数据,直接打库
  • 方案:
  1. 参数校验
  2. 缓存空值(短过期)
  3. 布隆过滤器

8.2 缓存击穿

  • 现象:热点 key 过期,大量请求打库
  • 方案:
  1. 热点 key 永不过期
  2. 分布式锁

8.3 缓存雪崩

  • 现象:大量 key 同时过期,数据库压垮
  • 方案:
  1. 过期时间加随机值
  2. 集群高可用
  3. 限流降级

9. Redis 实现 SSO 单点登录

9.1 流程

  1. 登录成功生成 Token
  2. Token 作为 key,用户信息存入 Redis
  3. 拦截器校验 Token
  4. 登出删除 Token

9.2 登录接口

@PostMapping("/login")
public String login(@RequestBody User user, HttpServletResponse response) {
    if ("admin".equals(user.getUsername()) && "123".equals(user.getPassword())) {
        String token = UUID.randomUUID().toString().replace("-", "");
        redisTemplate.opsForValue().set(token, user, 3600, TimeUnit.SECONDS);
        response.setHeader("Authorization", token);
        return token;
    }
    return "fail";
}

9.3 登录拦截器

@Component
public class LoginInterceptor implements HandlerInterceptor {
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        String token = request.getHeader("Authorization");
        if (token == null) return false;
        return redisTemplate.hasKey(token);
    }
}

10. 主从复制部署

10.1 作用

  • 读写分离
  • 数据备份
  • 读性能扩展

10.2 配置(一主两从)

  • 6379:主
  • 6380、6381:从

从库配置:

replicaof 127.0.0.1 6379
masterauth 123456

查看状态:

info replication

11. 哨兵模式(自动故障转移)

11.1 作用

  • 监控主节点
  • 自动选举新主
  • 故障通知

11.2 配置 sentinel.conf

sentinel monitor mymaster 127.0.0.1 6379 1
sentinel auth-pass mymaster 123456
daemonize yes

11.3 启动

redis-sentinel sentinel.conf

12. Redis Cluster 集群部署

12.1 特点

  • 无中心
  • 16384 个槽分片
  • 3主3从企业标准

12.2 集群创建

redis-cli --cluster create 192.168.1.100:7000 192.168.1.100:7001 192.168.1.100:7002 192.168.1.100:7003 192.168.1.100:7004 192.168.1.100:7005 --cluster-replicas 1

12.3 连接集群

redis-cli -c -p 7000

13. 性能优化与运维规范

13.1 禁止大 Key

  • String > 10KB
  • Hash/List/Set 元素过多

大 Key 导致:阻塞、迁移慢、内存碎片

13.2 内存优化

  • maxmemory 设置上限
  • 淘汰策略 allkeys-lru
  • 开启 activedefrag 内存整理

13.3 安全规范

  • 必须设置密码
  • 禁止外网暴露
  • 防火墙限制 IP
  • 不要使用默认端口

13.4 监控

  • 内存使用率
  • 命中率
  • 慢查询
  • 连接数
  • 主从同步状态

14. 总结

本文覆盖 Redis 从零到集群部署 全流程:

  • 基础命令 → 数据结构
  • SpringBoot 整合 → 序列化
  • 事务/锁 → 秒杀实战
  • 持久化 → 主从/哨兵/集群
  • 缓存问题 → 性能优化