文章目录
-
- [Redis 简介](#Redis 简介)
- 核心特点
- 支持的数据结构
- 持久化机制
- 架构图
- 搭建本地Redis
-
- 第一步:下载zip文件并解压
- [第二步:启动 Redis 服务器](#第二步:启动 Redis 服务器)
- 第三步:打开另一个命令提示符窗口(客户端)
- 第四步:基础操作示例
- [Python 中使用 Redis](#Python 中使用 Redis)
-
- [步骤一: 安装 Redis 客户端库](#步骤一: 安装 Redis 客户端库)
- 步骤二:Python中基础使用示例
- 步骤三:运行查看结果
- 典型应用场景
- 与其他数据库对比
- 优缺点总结
- 总结
Redis 简介
Redis (Remote Dictionary Server)是一个开源的、基于内存的键值对存储系统,常被用作热点数据缓存、轻量级 NoSQL 数据库以及简单的消息代理。
核心特点
| 特点 | 说明 |
|---|---|
| 内存存储 | 数据主要在内存中,读写速度极快(微秒级) |
| 丰富的数据结构 | String、Hash、List、Set、ZSet、Geo、Stream 等 |
| 持久化 | RDB 快照 + AOF 日志,支持数据重启恢复 |
| 高可用 | 主从复制、哨兵模式、集群模式 |
| 原子操作 | 所有操作都是原子性的 |
| 单线程模型 | 核心命令执行单线程,避免锁竞争(6.0后 I/O 多线程) |
支持的数据结构
| 类型 | 底层实现 | 应用场景 |
|---|---|---|
| String | SDS(动态字符串) | 缓存、计数器、分布式锁、Session |
| Hash | dict(哈希表) | 存储对象(用户信息、商品详情) |
| List | quicklist(双向链表) | 消息队列、最新列表、栈 |
| Set | intset/hashtable | 标签系统、共同好友、去重 |
| Sorted Set | dict + skiplist | 排行榜、延时队列、带权重的任务 |
| Bitmap | SDS(位数组) | 签到统计、在线状态、布隆过滤器 |
| HyperLogLog | 概率数据结构 | UV 统计、基数估算 |
| Geo | geohash + zset | 附近的人/店铺、距离计算 |
| Stream | listpack + rax | 消息队列、事件溯源 |
持久化机制
| 特性 | RDB | AOF |
|---|---|---|
| 原理 | 定期内存快照 | 追加写命令日志 |
| 文件 | dump.rdb(二进制) | appendonly.aof(文本) |
| 恢复速度 | 快(直接加载) | 慢(重放命令) |
| 数据安全性 | 可能丢失最后一次快照后的数据 | 最多丢失1秒(可配置) |
| 文件大小 | 小(压缩) | 大 |
| 性能影响 | fork 子进程,可能阻塞 | 写入频繁,但可配置 |
| 适用场景 | 备份、灾难恢复 | 数据完整性要求高 |
架构图
┌─────────────────────────────────────────┐
│ 应用程序 (Client) │
└─────────────────┬───────────────────────┘
│ TCP连接 (端口6379)
▼
┌─────────────────────────────────────────┐
│ Redis Server │
│ ┌─────────────────────────────────────┐│
│ │ Network I/O (多路复用) ││
│ └─────────────────┬───────────────────┘│
│ ▼ │
│ ┌─────────────────────────────────────┐│
│ │ 命令处理器 (单线程核心) ││
│ └─────────────────┬───────────────────┘│
│ ▼ │
│ ┌─────────────────────────────────────┐│
│ │ 内存数据库 ││
│ │ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ ││
│ │ │String│ │ Hash│ │ List│ │ Set │ ││
│ │ └─────┘ └─────┘ └─────┘ └─────┘ ││
│ │ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ ││
│ │ │ ZSet │ │ Geo │ │ Bit │ │Stream│ ││
│ │ └─────┘ └─────┘ └─────┘ └─────┘ ││
│ └─────────────────┬───────────────────┘│
│ ▼ │
│ ┌───────────────┐ ┌───────────────┐ │
│ │ RDB持久化 │ │ AOF持久化 │ │
│ └───────────────┘ └───────────────┘ │
└─────────────────────────────────────────┘
│
▼
磁盘 (dump.rdb / appendonly.aof)
搭建本地Redis
本地为windows环境,由于Redis官方没有推出Windows版,本例中使用社区维护的基于 Redis 官方最新源码进行 Windows 移植的版本,在 Redis for Windows Releases 获取最新预编译包。
第一步:下载zip文件并解压
本例中下载了Redis-x.x.x-Windows-x64-msys2.zip文件,把下载好的 .zip 文件解压到一个文件夹中
第二步:启动 Redis 服务器
在Redis文件夹目录下,打开终端执行以下命令:
bash
redis-server.exe

看到类似这样的输出就说明成功了。
注意:这个窗口会一直显示运行日志,不要关闭它。如果关闭了,Redis 服务器就停止了。
第三步:打开另一个命令提示符窗口(客户端)
执行以下命令连接服务器:
bash
redis-cli.exe
看到提示符变成 127.0.0.1:6379> 就说明连接成功了。
第四步:基础操作示例
在 redis-cli 中输入以下命令

Python 中使用 Redis
步骤一: 安装 Redis 客户端库
bash
pip install redis
步骤二:Python中基础使用示例
创建一个 Python 文件 redis_demo.py:
python
import redis
import time
from redis import ConnectionPool
# 创建连接池(避免频繁创建连接)
pool = ConnectionPool(
host='localhost',
port=6379,
db=0,
decode_responses=True,
max_connections=10 # 最大连接数
)
# 从连接池获取连接
client = redis.Redis(connection_pool=pool)
# 测试连接
try:
client.ping()
print("✅ Redis 连接成功!")
except redis.ConnectionError:
print("❌ Redis 连接失败,请确保 Redis 服务已启动")
exit()
# 1. String 操作
print("\n--- String 操作 ---")
client.set("name", "张三")
client.set("age", 25)
client.setex("session", 3600, "user_session_data") # 设置过期时间(秒)
name = client.get("name")
age = client.get("age")
print(f"姓名: {name}, 年龄: {age}")
# 数字自增
client.set("view_count", 100)
new_count = client.incr("view_count") # 自增1
print(f"浏览量: {new_count}")
# 批量设置和获取
client.mset({"city": "北京", "country": "中国"})
cities = client.mget(["city", "country"])
print(f"地址: {cities}")
# 2. Hash 操作(适合存储对象)
print("\n--- Hash 操作 ---")
client.hset("user:1001", mapping={
"name": "李四",
"age": 28,
"email": "lisi@example.com",
"city": "上海"
})
# 获取单个字段
user_name = client.hget("user:1001", "name")
print(f"用户名: {user_name}")
# 获取所有字段
user_info = client.hgetall("user:1001")
print(f"用户信息: {user_info}")
# 获取所有字段名
fields = client.hkeys("user:1001")
print(f"字段列表: {fields}")
# 3. List 操作(队列/栈)
print("\n--- List 操作 ---")
client.lpush("tasks", "任务1", "任务2") # 从左边推入
client.rpush("tasks", "任务3") # 从右边推入
# 弹出(队列:先进先出)
task = client.lpop("tasks")
print(f"处理任务: {task}")
# 查看列表所有元素
all_tasks = client.lrange("tasks", 0, -1)
print(f"剩余任务: {all_tasks}")
# 4. Set 操作(去重集合)
print("\n--- Set 操作 ---")
client.sadd("tags", "Python", "Redis", "Database", "Python") # 重复的Python只添加一次
tags = client.smembers("tags")
print(f"标签集合: {tags}")
# 判断元素是否存在
has_redis = client.sismember("tags", "Redis")
print(f"是否包含Redis: {has_redis}")
# 5. Sorted Set 操作(排行榜)
print("\n--- Sorted Set 操作 ---")
client.zadd("ranking", {
"玩家A": 100,
"玩家B": 85,
"玩家C": 95,
"玩家D": 70
})
# 获取前三名(按分数从高到低)
top3 = client.zrevrange("ranking", 0, 2, withscores=True)
print("排行榜前三名:")
for name, score in top3:
print(f" {name}: {score}分")
# 获取玩家B的排名
rank = client.zrevrank("ranking", "玩家B")
print(f"玩家B排名: 第{rank + 1}名")
# 6. 设置键过期时间
print("\n--- 过期时间 ---")
client.setex("temp_code", 10, "123456") # 10秒后过期
print(f"剩余时间: {client.ttl('temp_code')}秒")
time.sleep(11)
expired_value = client.get("temp_code")
print(f"过期后取值: {expired_value}") # None
# 7. 删除键
print("\n--- 删除操作 ---")
client.delete("name")
exists = client.exists("name")
print(f"name键是否存在: {exists}")
# 8. 检查键类型
key_type = client.type("user:1001")
print(f"user:1001类型: {key_type}")
# 9. 获取所有键
all_keys = client.keys("*")
print(f"所有键: {all_keys}")
# 10. 使用管道(Pipeline)批量执行命令,提高性能
print("\n--- 管道操作 ---")
pipe = client.pipeline()
pipe.set("key1", "value1")
pipe.set("key2", "value2")
pipe.incr("counter")
pipe.execute()
print("批量命令执行完成")
# 1. 添加餐厅位置
restaurants = [
(116.397128, 39.916527, "肯德基(前门店)"),
(116.308048, 39.984152, "麦当劳(颐和园店)"),
(116.329294, 39.896407, "星巴克(天坛店)"),
(116.400000, 39.910000, "海底捞(东单店)"),
]
for lon, lat, name in restaurants:
client.geoadd("restaurants", (lon, lat, name))
print("✅ 餐厅位置已添加")
# 2. 查询所有餐厅坐标
positions = client.geopos("restaurants", *[name for _, _, name in restaurants])
print(f"\n餐厅坐标: {positions}")
# 3. 计算两个餐厅之间的距离
distance = client.geodist("restaurants", "肯德基(前门店)", "海底捞(东单店)", unit="km")
print(f"\n肯德基前门店 → 海底捞东单店: {distance} km")
# 使用完后不需要手动关闭,连接会自动返回池中
client.set("pool_test", "测试连接池")
步骤三:运行查看结果
在demo脚本文件夹下打开终端,输入以下命令:
bash
python redis_demo.py
结果:

典型应用场景
| 场景 | 方案 | 示例 |
|---|---|---|
| 缓存 | String + EXPIRE | 热点数据、Session |
| 计数器 | String + INCR | 点赞数、浏览数、限流 |
| 排行榜 | ZSet(ZADD + ZREVRANGE) | 游戏积分、活跃用户 |
| 消息队列 | List(LPUSH + RPOP) / Stream | 异步任务、通知 |
| 分布式锁 | SETNX + EXPIRE | 防止重复提交、限流 |
| 社交关系 | Set | 共同好友、关注关系 |
| 附近的人 | Geo | LBS 服务 |
| 去重 | Set / HyperLogLog | UV 统计、标签 |
| 位统计 | Bitmap | 签到、在线状态 |
与其他数据库对比
| 特性 | Redis | Memcached | MySQL |
|---|---|---|---|
| 存储 | 内存+磁盘 | 纯内存 | 磁盘 |
| 数据结构 | 丰富 | 简单键值 | 表格 |
| 持久化 | 支持 | 不支持 | 支持 |
| 高可用 | 原生支持 | 需外部方案 | 主从、集群 |
| QPS | 10万+ | 10万+ | 数千~数万 |
| 容量 | 受内存限制 | 受内存限制 | 海量 |
优缺点总结
- 优点
性能极高
数据结构丰富
操作原子性
高可用支持完善 - 缺点
数据容量受内存限制
内存成本较高
复杂的查询支持有限(如多条件联合查询)
总结
Redis 是目前最受欢迎的 NoSQL 数据库之一,尤其适合需要高性能读写和灵活数据结构的场景。