JDWA 技术文档
首页
  • 数据库
  • 前端开发
  • 后端开发
  • 开发工具
  • 虚拟化技术
  • KVM显卡直通
  • FPGA仿真固件
  • 项目实战
  • 踩坑记录
  • 开发心得
  • 软件工具
  • 学习资料
  • 开发环境
更新日志
关于我
Gitee
GitHub
首页
  • 数据库
  • 前端开发
  • 后端开发
  • 开发工具
  • 虚拟化技术
  • KVM显卡直通
  • FPGA仿真固件
  • 项目实战
  • 踩坑记录
  • 开发心得
  • 软件工具
  • 学习资料
  • 开发环境
更新日志
关于我
Gitee
GitHub
  • 数据库

    • 数据库教程
    • MySQL免安装版使用指南
    • MySQL性能优化实践
    • Redis入门与实践
    • MinIO快速部署指南
    • MinIO基础使用教程
  • 前端开发

    • 前端开发教程
    • Vue.js开发最佳实践
    • CSS常用技巧与解决方案
    • JavaScript实用技巧与编程模式
    • CSS Grid布局教程
  • 后端开发

    • 后端开发教程
    • Spring Boot实战指南
    • Node.js Express 框架开发实战指南
    • Python Flask 框架开发指南
  • 开发工具

    • 开发工具教程
    • Git 基础教程
    • Git工作流实践指南
    • VS Code 全面使用指南
    • VS Code必装插件推荐
    • Docker基础入门
    • IntelliJ IDEA 使用技巧
    • Eclipse配置与优化
    • Sublime Text 高级技巧
    • Vim 从入门到精通
    • Maven 详解
    • Gradle 入门与进阶
    • Webpack 配置指南
    • npm 与 yarn 使用技巧
    • Makefile 编写指南
    • Navicat 使用指南
    • MCP本地部署教程
  • 虚拟化技术

    • JDWA虚拟化技术专题
    • KVM虚拟机去虚拟化技术详解
  • KVM显卡直通

    • KVM显卡GPU直通教程
  • FPGA仿真固件

    • FPGA仿真固件开发指南
    • 基础-完整设备仿真定制固件开发指南
    • 中级-完整设备仿真定制固件开发指南
    • 高级-完整设备仿真定制固件开发指南

Redis入门与实践

资源下载: Redis学习资源包 密码: jdwa

Tips

本教程基于Redis 6.0及以上版本,同时兼顾Windows和Linux/macOS环境,适合Redis初学者及有一定使用经验的开发者。

1. Redis简介

Redis(Remote Dictionary Server)是一个开源的、基于内存的键值数据库,以其超高性能、灵活性和丰富的数据结构支持而闻名。

1.1 Redis的主要特点

  • 高性能:基于内存操作,读写性能极高(10万/秒级别)
  • 丰富的数据类型:支持String、List、Hash、Set、Sorted Set等多种数据类型
  • 原子性操作:单个操作是原子性的,也支持批量操作
  • 持久化机制:支持RDB和AOF两种持久化方式
  • 主从复制:支持主从复制和读写分离
  • 高可用:通过Redis Sentinel和Redis Cluster提供高可用解决方案
  • 事务支持:支持事务操作,但不支持回滚
  • Lua脚本:支持Lua脚本执行复杂操作

1.2 Redis的应用场景

  • 缓存系统:存储热点数据,减轻数据库压力
  • 计数器:如网站访问量计数、用户点赞数
  • 消息队列:简单的发布订阅(pub/sub)或消息队列场景
  • 排行榜:利用Sorted Set实现如游戏排行榜
  • 会话存储:Web应用Session共享
  • 分布式锁:利用SETNX命令实现简单的分布式锁
  • 社交网络:如粉丝列表、关注列表等
  • 地理位置应用:使用GEO命令实现附近的人、商店等功能

2. Redis安装与配置

2.1 Windows环境安装

虽然Redis官方不提供Windows版本,但可以使用Microsoft开源的Windows版Redis:

  1. 下载地址:https://github.com/microsoftarchive/redis/releases

  2. 下载zip文件并解压到指定目录,如 C:\Redis

  3. 运行Redis服务器:

    C:\Redis\redis-server.exe
    
  4. 运行Redis客户端:

    C:\Redis\redis-cli.exe
    
  5. 安装为Windows服务(可选):

    C:\Redis\redis-server.exe --service-install redis.windows.conf
    

2.2 Linux环境安装

Ubuntu/Debian系统:

sudo apt update
sudo apt install redis-server

启动Redis服务:

sudo systemctl start redis-server

CentOS/RHEL系统:

sudo yum install epel-release
sudo yum install redis
sudo systemctl start redis

2.3 源码编译安装

最新版本的Redis需要通过源码编译安装:

wget https://download.redis.io/releases/redis-6.2.6.tar.gz
tar xzf redis-6.2.6.tar.gz
cd redis-6.2.6
make
sudo make install

2.4 基本配置

Redis的配置文件(redis.conf)中有许多重要参数,以下是几个关键配置:

  • 端口:默认是6379

    port 6379
    
  • 绑定IP:默认仅本地访问,生产环境应限制IP访问

    bind 127.0.0.1
    
  • 密码保护:设置AUTH密码

    requirepass yourpassword
    
  • 内存限制:设置最大内存使用量

    maxmemory 1gb
    
  • 内存策略:当达到内存限制时的淘汰策略

    maxmemory-policy allkeys-lru
    
  • 持久化配置:RDB持久化

    save 900 1      # 900秒内有1个更改
    save 300 10     # 300秒内有10个更改
    save 60 10000   # 60秒内有10000个更改
    
  • AOF持久化:

    appendonly yes
    appendfsync everysec
    

3. Redis数据类型与命令

Redis提供了丰富的数据类型,以下介绍各种数据类型的基本用法和常用命令。

3.1 String(字符串)

最基本的数据类型,可以存储字符串、整数或浮点数。

基本命令:

# 设置键值
SET key value
# 设置带过期时间的键值(10秒)
SET key value EX 10
# 获取值
GET key
# 递增
INCR key
# 递增指定量
INCRBY key increment
# 删除
DEL key
# 检查存在
EXISTS key
# 设置过期时间(秒)
EXPIRE key seconds

使用场景:

  • 存储用户信息、配置信息
  • 计数器(如页面访问量)
  • 缓存对象(JSON字符串)
  • 实现分布式锁(SETNX)

3.2 List(列表)

有序的字符串列表,基于双向链表实现,支持两端操作。

基本命令:

# 左侧添加
LPUSH key value1 [value2]
# 右侧添加
RPUSH key value1 [value2]
# 左侧弹出
LPOP key
# 右侧弹出
RPOP key
# 获取列表元素
LRANGE key start stop
# 获取列表长度
LLEN key
# 根据索引获取元素
LINDEX key index
# 裁剪列表
LTRIM key start stop

使用场景:

  • 消息队列(生产者-消费者模式)
  • 最近更新的列表(如朋友圈最新状态)
  • 实现栈或队列

3.3 Hash(哈希)

存储字段和值的映射表,适合存储对象。

基本命令:

# 设置单个字段
HSET key field value
# 设置多个字段
HMSET key field1 value1 field2 value2
# 获取单个字段
HGET key field
# 获取多个字段
HMGET key field1 field2
# 获取所有字段和值
HGETALL key
# 删除字段
HDEL key field1 [field2]
# 增加数字
HINCRBY key field increment
# 检查字段是否存在
HEXISTS key field
# 获取所有字段名
HKEYS key
# 获取所有值
HVALS key
# 获取字段数量
HLEN key

使用场景:

  • 存储用户信息、商品信息等对象数据
  • 购物车(用户ID为key,商品ID为field,数量为value)
  • 计数器(多个相关计数一起存储)

3.4 Set(集合)

无序的字符串集合,不允许重复元素。

基本命令:

# 添加元素
SADD key member1 [member2]
# 删除元素
SREM key member1 [member2]
# 获取所有元素
SMEMBERS key
# 判断元素是否在集合中
SISMEMBER key member
# 获取集合元素数量
SCARD key
# 随机获取元素
SRANDMEMBER key [count]
# 弹出随机元素
SPOP key [count]
# 交集
SINTER key1 key2
# 并集
SUNION key1 key2
# 差集
SDIFF key1 key2

使用场景:

  • 标签系统
  • 用户关注/粉丝列表
  • 黑名单/白名单
  • 抽奖系统

3.5 Sorted Set(有序集合)

有序的字符串集合,每个元素关联一个分数用于排序。

基本命令:

# 添加元素
ZADD key score1 member1 [score2 member2]
# 获取元素排名(从小到大)
ZRANK key member
# 获取元素排名(从大到小)
ZREVRANK key member
# 获取元素分数
ZSCORE key member
# 获取指定排名范围的元素
ZRANGE key start stop [WITHSCORES]
# 按分数获取元素
ZRANGEBYSCORE key min max [WITHSCORES]
# 增加元素分数
ZINCRBY key increment member
# 删除元素
ZREM key member1 [member2]
# 获取集合元素数量
ZCARD key
# 获取指定分数范围内的元素数量
ZCOUNT key min max

使用场景:

  • 排行榜系统
  • 带权重的队列
  • 延迟队列(以时间戳为分数)
  • 评分系统

3.6 其他数据类型

Bitmap:位图,可以对位进行操作

# 设置位图中某位的值
SETBIT key offset value
# 获取位图中某位的值
GETBIT key offset
# 统计位图中值为1的位的数量
BITCOUNT key [start end]

HyperLogLog:用于基数统计的概率性数据结构

# 添加元素
PFADD key element1 [element2]
# 获取基数估计值
PFCOUNT key [key2]

Geospatial:地理位置索引

# 添加地理位置
GEOADD key longitude latitude member
# 计算两个位置间的距离
GEODIST key member1 member2 [unit]
# 获取指定范围内的位置
GEORADIUS key longitude latitude radius unit

4. Redis高级特性

4.1 事务

Redis事务允许一次执行多个命令,它的主要特点:

  • 命令在事务中按顺序执行
  • 事务执行过程中不会被其他命令中断
  • Redis事务不支持回滚
# 开始事务
MULTI
# 命令入队
SET user:1:name "Tom"
INCR user:1:visits
# 执行事务
EXEC
# 或放弃事务
DISCARD

4.2 发布订阅

Redis提供发布订阅功能,支持消息的发布和订阅。

# 订阅频道
SUBSCRIBE channel1 [channel2]
# 发布消息
PUBLISH channel1 "Hello World"
# 基于模式订阅
PSUBSCRIBE news.*

4.3 持久化

Redis支持两种持久化方式:RDB和AOF。

RDB(Redis Database):

  • 按指定时间间隔执行数据集的时间点快照
  • 配置示例:
    save 900 1
    save 300 10
    save 60 10000
    

AOF(Append Only File):

  • 记录服务器接收的每个写操作
  • 配置示例:
    appendonly yes
    appendfsync everysec
    

4.4 Lua脚本

Redis支持使用Lua脚本执行复杂的原子操作:

# 执行Lua脚本
EVAL "return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}" 2 key1 key2 arg1 arg2
# 加载脚本到缓存并返回SHA1摘要
SCRIPT LOAD "return redis.call('get', KEYS[1])"
# 使用SHA1摘要执行缓存的脚本
EVALSHA sha1 numkeys key [key ...] arg [arg ...]

4.5 Pipeline(管道)

Pipeline可以一次性发送多个命令到服务器,减少网络往返时间:

# 示例代码(伪代码)
pipeline = redis.pipeline()
pipeline.set("key1", "value1")
pipeline.set("key2", "value2")
pipeline.get("key1")
pipeline.get("key2")
results = pipeline.execute()

5. Redis实战应用

5.1 实现分布式锁

Redis实现分布式锁的基本思路:

# 获取锁(NX表示key不存在时才设置,PX设置过期时间为毫秒)
SET resource_name unique_value NX PX 10000

# 释放锁(使用Lua脚本确保原子性)
EVAL "if redis.call('get',KEYS[1]) == ARGV[1] then return redis.call('del',KEYS[1]) else return 0 end" 1 resource_name unique_value

Java实现示例:

public boolean acquireLock(String lockKey, String clientId, int expireTime) {
    String result = jedis.set(lockKey, clientId, "NX", "PX", expireTime);
    return "OK".equals(result);
}

public boolean releaseLock(String lockKey, String clientId) {
    String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
    Object result = jedis.eval(script, Collections.singletonList(lockKey), Collections.singletonList(clientId));
    return Integer.valueOf(1).equals(result);
}

5.2 缓存设计模式

Cache-Aside(旁路缓存):

  1. 读取:先查缓存,缓存命中返回;缓存未命中查数据库,并将结果放入缓存
  2. 写入:先写数据库,再删除缓存(不要更新缓存)
// 伪代码
public Data getDataById(String id) {
    // 查询缓存
    String cacheKey = "data:" + id;
    Data data = redis.get(cacheKey);
    
    // 缓存命中
    if (data != null) {
        return data;
    }
    
    // 缓存未命中,查询数据库
    data = db.query("SELECT * FROM data WHERE id = ?", id);
    
    // 将数据放入缓存
    if (data != null) {
        redis.set(cacheKey, data);
    }
    
    return data;
}

public void updateData(Data data) {
    // 更新数据库
    db.update("UPDATE data SET ... WHERE id = ?", data.getId());
    
    // 删除缓存
    redis.del("data:" + data.getId());
}

缓存穿透防护:

缓存穿透是指查询一个不存在的数据,导致每次都要去数据库查询。

解决方案:

  1. 对空值进行缓存
  2. 使用布隆过滤器
// 缓存空值
public Data getDataById(String id) {
    String cacheKey = "data:" + id;
    String value = redis.get(cacheKey);
    
    if (value != null) {
        if (value.equals("nil")) {
            return null; // 空值已被缓存
        }
        return deserialize(value);
    }
    
    Data data = db.query("SELECT * FROM data WHERE id = ?", id);
    
    if (data != null) {
        redis.set(cacheKey, serialize(data));
        return data;
    } else {
        // 缓存空值,避免缓存穿透
        redis.set(cacheKey, "nil", "EX", 60); // 设置较短的过期时间
        return null;
    }
}

缓存雪崩防护:

缓存雪崩是指大量缓存同时过期,导致大量请求落到数据库。

解决方案:

  1. 设置随机过期时间
  2. 更新时增加互斥锁
  3. 使用Redis集群提高可用性
// 设置随机过期时间
public void setWithRandomExpire(String key, String value) {
    // 在基础过期时间(如3600秒)上增加随机秒数(如0-300秒)
    int randomExpireTime = 3600 + new Random().nextInt(300);
    redis.set(key, value, "EX", randomExpireTime);
}

5.3 简单计数器实现

使用Redis实现计数器非常简单:

# 增加计数
INCR page_view:article:1001
# 获取计数
GET page_view:article:1001
# 设置过期时间(如24小时)
EXPIRE page_view:article:1001 86400

Java实现:

public long incrementPageView(String articleId) {
    String key = "page_view:article:" + articleId;
    long count = jedis.incr(key);
    
    // 如果是新键,设置过期时间
    if (count == 1) {
        jedis.expire(key, 86400);
    }
    
    return count;
}

5.4 实现排行榜

使用Sorted Set实现排行榜:

# 添加或更新分数
ZADD leaderboard 1000 user1
ZADD leaderboard 2000 user2
ZADD leaderboard 1500 user3

# 获取前三名
ZREVRANGE leaderboard 0 2 WITHSCORES

# 获取用户排名
ZREVRANK leaderboard user2

# 增加用户分数
ZINCRBY leaderboard 100 user1

Java实现:

public void updateScore(String userId, double score) {
    jedis.zadd("leaderboard", score, userId);
}

public List<Map.Entry<String, Double>> getTopPlayers(int count) {
    Set<Tuple> tuples = jedis.zrevrangeWithScores("leaderboard", 0, count - 1);
    List<Map.Entry<String, Double>> result = new ArrayList<>();
    
    for (Tuple tuple : tuples) {
        result.add(new AbstractMap.SimpleEntry<>(tuple.getElement(), tuple.getScore()));
    }
    
    return result;
}

public long getRank(String userId) {
    Long rank = jedis.zrevrank("leaderboard", userId);
    return rank != null ? rank + 1 : 0; // +1转为人类可读的排名(从1开始)
}

6. Redis高可用与集群

6.1 主从复制

主从复制可以实现数据备份和读写分离:

# 在从服务器上执行
SLAVEOF master_ip master_port

配置文件方式:

slaveof 192.168.1.10 6379

6.2 Sentinel(哨兵)

Redis Sentinel提供高可用性,通过监控主服务器状态并在主服务器故障时自动进行故障转移。

sentinel.conf基本配置:

sentinel monitor mymaster 192.168.1.10 6379 2
sentinel down-after-milliseconds mymaster 5000
sentinel failover-timeout mymaster 60000

6.3 Redis Cluster

Redis Cluster提供分片功能,可以将数据自动分散到多个节点上。

基本配置:

cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000

7. Redis性能优化

7.1 内存优化

  • 使用合适的数据结构
  • 设置合理的键过期时间
  • 使用Redis存储小而精简的对象
  • 压缩键和值
  • 合理设置maxmemory和maxmemory-policy

7.2 命令优化

  • 使用批量命令:MGET/MSET代替多次GET/SET
  • 使用Pipeline减少网络往返时间
  • 避免使用KEYS命令(使用SCAN代替)
  • 避免使用高耗时命令如SORT、LREM、SINTER

7.3 连接优化

  • 使用连接池管理连接
  • 复用连接
  • 及时关闭不使用的连接

8. Redis部署与运维

8.1 Docker部署Redis

Docker是部署Redis的便捷方式:

# 拉取Redis镜像
docker pull redis

# 运行Redis容器
docker run --name redis-server -p 6379:6379 -d redis

# 使用自定义配置文件
docker run --name redis-server -v /path/to/redis.conf:/etc/redis/redis.conf -p 6379:6379 -d redis redis-server /etc/redis/redis.conf

8.2 Redis监控

监控Redis的关键指标:

  • 内存使用情况
  • 连接数
  • 命令执行情况
  • 命中率和未命中率
  • 网络流量

监控工具:

  • Redis INFO命令
  • Redis-stat
  • Redis-monitor
  • Prometheus + Grafana

8.3 备份与恢复

备份:

# 使用SAVE命令(同步)
redis-cli SAVE

# 使用BGSAVE命令(异步)
redis-cli BGSAVE

# 复制RDB文件
cp /var/lib/redis/dump.rdb /backup/dump-$(date +%Y%m%d).rdb

恢复:

# 停止Redis服务
systemctl stop redis

# 复制RDB文件到Redis数据目录
cp /backup/dump.rdb /var/lib/redis/

# 启动Redis服务
systemctl start redis

总结

Redis是一个强大而灵活的内存数据库,本教程介绍了Redis的基础知识、常用命令、高级特性和实际应用场景。掌握Redis可以帮助我们构建更高性能、更可靠的应用系统。

作为一个内存数据库,Redis特别适合用于需要高性能读写的场景,如缓存、计数器、分布式锁、排行榜等。通过合理使用Redis的数据结构和功能,我们可以大幅提升应用系统的性能和可扩展性。

随着对Redis的深入学习和实践,你会发现它不仅是一个缓存系统,更是一个多功能的数据处理平台,可以解决很多复杂的业务问题。

相关资源

  • Redis官方文档
  • Redis高级特性详解
  • Redis集群部署

如有问题或建议,欢迎联系作者: 1412800823@qq.com

Prev
MySQL性能优化实践
Next
MinIO快速部署指南