Redis学习笔记

文章目录

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 数据库之一,尤其适合需要高性能读写和灵活数据结构的场景。

相关推荐
一写代码就开心4 小时前
redis-cli 客户端查询set集合里面的具体数据
数据库·redis·缓存
Irissgwe6 小时前
redis之典型应用-缓存cache
数据库·redis·缓存·缓存击穿·缓存雪崩·redis淘汰策略
gQ85v10Db7 小时前
Redis分布式锁进阶第三十一篇
数据库·redis·分布式
身如柳絮随风扬7 小时前
购物车服务设计:基于 Redis Hash 的高效实现
数据库·redis
Thanks_ks9 小时前
分布式锁:Redis 与 Redisson 的工程实践与避坑指南
java·redis·分布式锁·redisson·微服务架构·并发编程·高可用
Kiyra10 小时前
Query Rewrite 不是越智能越好:RAG 检索的精确词保护与动态召回
redis·websocket·junit·单元测试·json
无盐海10 小时前
Foundatio,内存,Redis 缓存
数据库·redis·缓存
未若君雅裁11 小时前
Redis 分布式锁与 Redisson:从抢券超卖讲到 WatchDog、可重入和 RedLock
redis·分布式
shark-chili11 小时前
基于claude code的redis慢查询指令复刻实践
数据库·redis·缓存