Redis 7 天学习笔记 · Day 1

发布时间:2026/10/31 2:04:31
Redis 7 天学习笔记 · Day 1

Redis 7 天学习笔记 · Day 1

主题:Redis 是什么 + 跑通第一个缓存

环境:Ubuntu 22.04/24.04 虚拟机 + Python 3 + Redis

一句话总结:Redis 是内存里的键值数据库,挡在 MySQL 前面当缓存,用空间换时间。


一、今日核心认知

  1. Redis 是内存里的“键值字典”:给一个 key,还一个 value。
  2. 它和 MySQL 不是替代关系:MySQL 是真相来源(硬盘,不能丢),Redis 是加速层(内存,丢了可重建)。
  3. 缓存必须有过期时间(TTL):否则数据库改了,缓存还是旧值,用户一直看到旧数据。
  4. 缓存本身只有三行代码:get查缓存 → 未命中查库 →setex写回。其余全是脚手架。

二、概念速记

1. 为什么需要 Redis

同一个数据被反复从硬盘读,硬盘慢、数据库扛不住。把查过的结果临时放内存,下次直接拿,不打扰数据库。

2. 内存 vs 硬盘

硬盘(MySQL)内存(Redis)
速度毫秒级微秒级
断电数据还在数据消失
容量大小
定位真相来源加速副本

3. 键值对长什么样

"user:1001" → {"id":"1001","name":"用户1001"} "hello" → "world" "article:42:views" → "1532"

常用命令:

SET key value # 存 GET key # 取 DEL key # 删 SETEX key 60 value # 存 + 60 秒后自动过期 TTL key # 看还剩几秒 # ≥0 剩余秒数 # -1 key 存在,但没设过期时间(永不过期) # -2 key 已不存在

4. 请求链路

用户 → Redis(快,先查) ↓ 没有(未命中) MySQL(慢,再查) ↓ 查到了 写回 Redis(下次就快)

“加个缓存” = 在数据库前面加一层 Redis。

5. 为什么必须过期

  • 内存贵且小,不能全放。
  • 数据会过时:数据库改了,缓存不失效就会返回旧值。
  • 过期不是缺陷,是缓存保持“大致正确”的机制。

三、环境与安装(Ubuntu)

# 1. 更新 + 基础工具sudoaptupdate&&sudoaptupgrade-ysudoaptinstall-ycurlvimnet-tools# 2. 安装 Redis(22.04 给 6.0.16,24.04 给 7.0.15,Day1–6 够用)sudoaptinstall-yredis-serversudosystemctlenable--nowredis-server# 3. 验证redis-cli PING# 期望 PONGredis-cli INFO server|grepredis_version

关键路径:

内容路径
配置文件/etc/redis/redis.conf
日志/var/log/redis/redis-server.log
数据目录/var/lib/redis/

启动时overcommit_memory、THP、TCP backlog的 warning 今天不用管。

Python 环境:

mkdir-p~/redis-7days&&cd~/redis-7days python3-mvenv venvsourcevenv/bin/activate pipinstallredis

Ubuntu 24.04 有 PEP 668 保护,必须用 venv,否则pip install报externally-managed-environment。

每次新终端:cd ~/redis-7days && source venv/bin/activate。


四、代码笔记:day1_demo.py

importredis,time,json# host 用 127.0.0.1 而非 localhost:避免解析到 ::1 而 Redis 只监听 IPv4r=redis.Redis(host="127.0.0.1",port=6379,db=0,decode_responses=True)try:r.ping()print("[OK] Redis 连接成功\n")exceptredis.ConnectionError:print("[ERROR] 连不上 Redis")print(" 排查顺序:")print(" 1. sudo systemctl status redis-server # 服务是否在跑")print(" 2. redis-cli PING # 命令行能否连上")print(" 3. ss -lntp | grep 6379 # 端口是否在监听")print(" 4. sudo ufw status # 本机防火墙是否拦截(概率极低)")raisedefslow_database_query(user_id:str)->dict:time.sleep(2)# 模拟硬盘上的 MySQL 查询return{"id":user_id,"name":f"用户{user_id}","email":f"user{user_id}@example.com"}defget_user(user_id:str)->dict:cache_key=f"user:{user_id}"cached=r.get(cache_key)# ① 先查内存ifcachedisnotNone:print(f" [缓存命中] key={cache_key}")returnjson.loads(cached)print(f" [缓存未命中] key={cache_key},去查数据库...")data=slow_database_query(user_id)# ② 未命中才查库r.setex(cache_key,60,json.dumps(data))# ③ 写回内存,60 秒过期print(f" [已回写缓存] key={cache_key},TTL=60s")returndataif__name__=="__main__":uid="1001"start=time.perf_counter();get_user(uid);t1=time.perf_counter()-start start=time.perf_counter();get_user(uid);t2=time.perf_counter()-startprint(f"\n第一次:{t1:.3f}s 第二次:{t2:.3f}s 加速比:{t1/t2:.1f}倍")

真正要记住的只有三行:

代码作用要点
r.get(cache_key)查缓存未命中返回None,不是报错
slow_database_query()查库真实项目里是 SQL
r.setex(key, 60, val)回写 + 过期每个缓存 key 都要有 TTL

r.ping()失败时,最可能是 Redis 服务没启动;其次检查端口是否被监听;防火墙或bind配置导致127.0.0.1不通的概率极低,Day 1 通常不用处理。


五、验证实验记录

redis-cli
KEYS user:* # 期望:1) "user:1001" TTL user:1001 # 期望:≤60 的数字,倒计时中 # -1 说明没设过期时间(本 Demo 不该出现) # -2 说明 key 已不存在(等 60 秒后即为此值) GET user:1001 # 期望:与 Python 输出的 JSON 一致

等 60 秒后再执行TTL user:1001→ 返回-2,缓存自动消失。
→ 第一次亲眼看到“过期”发生。


六、问题与处理

问题处理
pip install报externally-managed-environment没进 venv,source venv/bin/activate
Python 报ConnectionRefusedError先redis-cli PING确认服务活着;host 用127.0.0.1
两次都“未命中”key 之前跑过已过期,或换了user_id,等 60 秒或换 ID
宿主机 RedisInsight 连不上虚拟机正常,默认bind 127.0.0.1
重启后 Redis 没起来sudo systemctl enable redis-server

七、交付物 Checklist

  • 截图 1:Demo 终端输出,第一次 ≥1.5s,第二次 ≤0.05s,加速比 ≥30 倍
  • 截图 2:redis-cli里KEYS/TTL/GET的输出
  • 一句话:100 字内解释“第二次为什么快”,必须含“内存”“没查数据库”
    • 示例:“第一次没命中,执行了sleep(2)的假查库并把结果写回 Redis;第二次直接从本机内存拿到 JSON,绕过了那段 2 秒等待。”