Redis 零基礎入門到實戰教程

  • Redis(Remote Dictionary Server)是一款開源、高性能、基於內存的鍵值對數據庫,支持多種數據結構,廣泛用於緩存、消息隊列、分佈式鎖等場景。本教程從基礎到實戰,幫你快速掌握 Redis 核心用法。
  • 視頻教程:https://pan.quark.cn/s/10e98d308913

一、Redis 安裝與環境準備

1. 安裝方式(推薦 3 種)

(1)Windows 安裝(適合新手)
  • 下載地址:Redis 官方 Windows 版本(選擇最新穩定版,如 3.2.100)
  • 安裝步驟:
  1. 雙擊安裝包,勾選“Add Redis to PATH”(自動配置環境變量)
  2. 默認端口 6379,無需修改,直接下一步完成安裝
  • 驗證:打開 CMD,輸入 redis-cli,出現 127.0.0.1:6379> 表示成功
(2)Linux 安裝(CentOS/Ubuntu)
  • CentOS:
# 安裝 EPEL 源
yum install epel-release -y
# 安裝 Redis
yum install redis -y
# 啓動 Redis 並設置開機自啓
systemctl start redis
systemctl enable redis
  • Ubuntu:
apt update
apt install redis-server -y
# 啓動服務
systemctl start redis-server
  • 驗證:輸入 redis-cli ping,返回 PONG 表示正常
(3)Docker 安裝(推薦開發/測試環境)
# 拉取 Redis 鏡像(默認最新穩定版)
docker pull redis
# 啓動容器(映射端口 6379,設置密碼 123456)
docker run -d -p 6379:6379 --name redis-demo redis --requirepass "123456"
# 進入容器操作 Redis
docker exec -it redis-demo redis-cli -a 123456

2. 核心配置文件(redis.conf)

關鍵配置項(修改後需重啓 Redis):

  • bind 127.0.0.1:默認只允許本地訪問,生產環境需改為服務器 IP 或 0.0.0.0(允許所有地址訪問)
  • port 6379:默認端口,可自定義(如 6380)
  • requirepass 123456:設置密碼(生產環境必須配置)
  • daemonize yes:Linux 下後台運行(默認 no,前台運行)
  • maxmemory 1gb:設置最大內存(避免內存溢出,需配合淘汰策略)
  • maxmemory-policy allkeys-lru:內存滿時淘汰策略(優先刪除最近最少使用的鍵)

二、Redis 核心數據結構(重點)

Redis 支持 5 種基礎數據結構,以及 HyperLogLog、Geo 等高級結構,核心是鍵(key)- 值(value) 映射,鍵都是字符串類型,值支持多種結構。

1. 字符串(String):最基礎的鍵值對

用途:

存儲字符串、數字(計數器)、二進制數據(如圖片 Base64),是最常用的結構。

核心命令:

命令

功能

示例

set key value

設置鍵值(覆蓋已有鍵)

set name zhangsan

get key

獲取鍵值

get name → “zhangsan”

setnx key value

僅當鍵不存在時設置(分佈式鎖核心)

setnx lock 1 → 1(成功)/ 0(失敗)

mset key1 val1 key2 val2

批量設置

mset age 20 gender male

mget key1 key2

批量獲取

mget name age → [“zhangsan”, “20”]

incr key

數字自增 1

incr count → 1(初始不存在時)

decr key

數字自減 1

decr count → 0

expire key seconds

設置過期時間(秒)

expire name 30(30 秒後過期)

setex key seconds value

原子性設置值 + 過期時間

setex code 60 123456(60 秒有效)

實戰場景:
  • 緩存用户信息(set user:1001 '{"id":1001,"name":"張三"}'
  • 計數器(文章閲讀量、接口訪問次數)
  • 驗證碼存儲(設置短期過期)

2. 哈希(Hash):適合存儲對象

用途:

存儲結構化數據(如用户、商品信息),相當於“鍵值對中的鍵值對”,支持單獨修改某個字段,無需整體更新。

核心命令:

命令

功能

示例

hset hash-key field value

設置哈希字段值

hset user:1001 name 張三 age 20

hget hash-key field

獲取哈希字段值

hget user:1001 name → “張三”

hgetall hash-key

獲取所有字段和值

hgetall user:1001 → [“name”,“張三”,“age”,“20”]

hmset hash-key f1 v1 f2 v2

批量設置字段

hmset user:1001 gender 男 city 北京

hmget hash-key f1 f2

批量獲取字段

hmget user:1001 name city → [“張三”,“北京”]

hdel hash-key field

刪除字段

hdel user:1001 age

hexists hash-key field

判斷字段是否存在

hexists user:1001 name → 1(存在)/ 0(不存在)

實戰場景:
  • 存儲用户信息(避免字符串 JSON 解析的開銷)
  • 商品詳情緩存(hset product:2001 name 手機 price 2999 stock 100

3. 列表(List):有序可重複的字符串集合

用途:

實現隊列、棧、消息列表(如朋友圈動態),底層是雙向鏈表,首尾操作效率極高(O(1)),中間操作效率低(O(n))。

核心命令:

命令

功能

示例

lpush list-key value1 value2

從列表左側插入元素

lpush msg:list a b c → 列表:[c,b,a]

rpush list-key value1 value2

從列表右側插入元素

rpush msg:list d e → 列表:[c,b,a,d,e]

lpop list-key

從左側彈出元素(刪除並返回)

lpop msg:list → “c”(列表變為 [b,a,d,e])

rpop list-key

從右側彈出元素

rpop msg:list → “e”(列表變為 [b,a,d])

lrange list-key start end

獲取指定範圍元素(0 開始,-1 表示末尾)

lrange msg:list 0 -1 → [“b”,“a”,“d”]

llen list-key

獲取列表長度

llen msg:list → 3

實戰場景:
  • 消息隊列(rpush 生產消息,lpop 消費消息,簡單場景)
  • 最新消息列表(如“最近評論”,lpush 新增,lrange 分頁查詢)
  • 棧(lpush + lpop)/ 隊列(lpush + rpop

4. 集合(Set):無序不可重複的字符串集合

用途:

去重、交集/並集/差集計算(如共同好友、標籤篩選),底層是哈希表,查詢、添加、刪除效率均為 O(1)。

核心命令:

命令

功能

示例

sadd set-key value1 value2

添加元素(重複元素自動去重)

sadd tag:1001 運動 音樂 旅行

smembers set-key

獲取所有元素

smembers tag:1001 → [“運動”,“音樂”,“旅行”]

sismember set-key value

判斷元素是否存在

sismember tag:1001 電影 → 0(不存在)

scard set-key

獲取集合大小

scard tag:1001 → 3

sinter set1 set2

求兩個集合的交集(共同元素)

sadd tag:1002 音樂 閲讀sinter tag:1001 tag:1002 → [“音樂”]

sunion set1 set2

求並集(所有元素去重)

sunion tag:1001 tag:1002 → [“運動”,“音樂”,“旅行”,“閲讀”]

sdiff set1 set2

求差集(set1 有但 set2 沒有)

sdiff tag:1001 tag:1002 → [“運動”,“旅行”]

實戰場景:
  • 用户標籤(去重存儲)
  • 共同好友推薦(交集計算)
  • 抽獎活動(srandmember set-key 隨機取元素,spop 隨機刪除元素)

5. 有序集合(Sorted Set/ZSet):有序不可重複的集合

用途:

排序場景(如排行榜、熱搜榜),每個元素關聯一個分數(score),按分數自動排序,底層是“跳錶”,兼顧排序和查詢效率。

核心命令:

命令

功能

示例

zadd zset-key score1 value1 score2 value2

添加元素(分數決定順序)

zadd rank:article 100 文章1 200 文章2 150 文章3

zrange zset-key start end [withscores]

按分數升序取元素(withscores 顯示分數)

zrange rank:article 0 -1 withscores → [“文章1”,100,“文章3”,150,“文章2”,200]

zrevrange zset-key start end

按分數降序取元素(排行榜常用)

zrevrange rank:article 0 1 → [“文章2”,“文章3”](前 2 名)

zscore zset-key value

獲取元素的分數

zscore rank:article 文章2 → 200

zincrby zset-key increment value

增加元素分數(計數器+排序)

zincrby rank:article 50 文章1 → 150(文章1 分數變為 150)

zcard zset-key

獲取元素個數

zcard rank:article → 3

實戰場景:
  • 文章閲讀量排行榜(分數=閲讀量,zrevrange 取Top N)
  • 熱搜榜(分數=搜索次數,定時更新)
  • 積分排名(用户積分作為分數)

三、Redis 高級特性

1. 過期鍵刪除策略

Redis 採用“惰性刪除 + 定期刪除”結合的策略:

  • 惰性刪除:訪問過期鍵時才刪除(節省 CPU,可能浪費內存)
  • 定期刪除:每隔一段時間掃描部分過期鍵(平衡 CPU 和內存)
  • 配合內存淘汰策略(maxmemory-policy):內存滿時自動刪除鍵,常用策略:
  • allkeys-lru:刪除所有鍵中最近最少使用的
  • volatile-lru:只刪除帶過期時間的鍵中最近最少使用的
  • noeviction:默認策略,內存滿時拒絕寫操作(推薦生產環境用 allkeys-lru

2. 持久化(避免數據丟失)

Redis 是內存數據庫,默認數據僅存於內存,重啓後丟失,需開啓持久化將數據寫入磁盤。

(1)RDB 持久化(默認開啓)
  • 原理:在指定時間間隔內,將內存中的數據快照寫入磁盤(生成 .rdb 文件)
  • 觸發方式:
  • 自動觸發:配置文件中 save 900 1(900 秒內至少 1 個鍵修改)、save 300 10
  • 手動觸發:save(阻塞 Redis,不推薦)、bgsave(後台異步執行,推薦)
  • 優點:恢復速度快,適合備份
  • 缺點:可能丟失最近一次快照後的更新數據
(2)AOF 持久化(推薦生產環境開啓)
  • 原理:記錄每一條寫命令(如 set、hset),重啓時重新執行命令恢復數據
  • 開啓方式:修改 redis.confappendonly yes,生成 .aof 文件
  • 同步策略(appendfsync):
  • always:每寫一條命令同步到磁盤(最安全,性能略低)
  • everysec:每秒同步一次(推薦,平衡安全和性能)
  • no:由操作系統決定同步時機(性能高,風險高)
  • 優點:數據丟失少(最多丟失 1 秒數據)
  • 缺點:AOF 文件體積大,恢復速度比 RDB 慢
(3)最佳實踐:
  • 生產環境開啓 AOF + RDB 雙持久化:AOF 保證數據安全性,RDB 用於快速恢復
  • 定期備份 .rdb 和 .aof 文件,防止磁盤損壞

3. 緩存常見問題與解決方案

(1)緩存穿透
  • 問題:請求不存在的鍵(如惡意查詢 user:9999,而該用户不存在),導致請求直接穿透到數據庫,壓垮數據庫
  • 解決方案:
  1. 緩存空值:對不存在的鍵,緩存 null 並設置短期過期時間(如 5 分鐘)
  2. 布隆過濾器:提前過濾不存在的鍵(適合數據量大的場景)
(2)緩存擊穿
  • 問題:某個熱點鍵過期時,大量請求同時訪問該鍵,穿透到數據庫
  • 解決方案:
  1. 互斥鎖:第一個請求獲取鎖,查詢數據庫並更新緩存,其他請求等待鎖釋放後查詢緩存
  2. 熱點鍵永不過期:定期後台更新緩存,不設置過期時間
(3)緩存雪崩
  • 問題:大量緩存鍵同時過期,或 Redis 服務宕機,導致所有請求穿透到數據庫
  • 解決方案:
  1. 過期時間隨機化:給每個鍵的過期時間加隨機值(如 expire key 3600 + rand(0, 600)),避免同時過期
  2. 服務熔斷/限流:數據庫壓力過大時,拒絕部分請求
  3. Redis 集羣:避免單點故障(後續講解)

四、Redis 集羣(高可用與擴容)

單節點 Redis 存在單點故障和內存上限問題,生產環境需部署集羣。

1. 主從複製(主從架構)

  • 原理:1 個主節點(Master)+ 多個從節點(Slave),主節點負責寫操作,從節點負責讀操作,主節點數據自動同步到從節點
  • 核心作用:
  • 讀寫分離:減輕主節點壓力(讀請求分發到從節點)
  • 容災備份:主節點故障時,從節點可切換為主節點
  • 配置步驟(以 1 主 2 從為例):
  1. 準備 3 個 Redis 實例(端口 6379、6380、6381)
  2. 從節點配置文件添加:slaveof 主節點IP 主節點端口(如 slaveof 127.0.0.1 6379
  3. 主節點設置密碼後,從節點需添加:masterauth 主節點密碼
  4. 驗證:主節點執行 info replication,查看從節點信息

2. 哨兵模式(Sentinel)

  • 問題:主從複製中,主節點故障後需手動切換從節點為主節點,不滿足高可用
  • 原理:部署多個哨兵進程(Sentinel),監控主從節點,主節點故障時自動選舉新主節點,實現故障自動切換
  • 核心功能:
  • 監控:檢查主從節點是否正常運行
  • 自動故障轉移:主節點宕機後,選舉從節點為新主,其他從節點切換到新主
  • 通知:故障時通過腳本通知管理員

3. Redis Cluster(分片集羣)

  • 問題:主從複製和哨兵模式無法解決“內存擴容”問題(單主節點內存有限)
  • 原理:將數據分片存儲到多個主節點(默認 16384 個哈希槽),每個主節點負責一部分槽,配合從節點實現高可用
  • 核心特點:
  • 分片存儲:突破單節點內存限制(如 3 主 3 從,總內存是 3 個主節點內存之和)
  • 自動路由:客户端請求根據鍵的哈希值自動路由到對應主節點
  • 容錯性:單個主節點故障,其從節點自動切換為主節點

五、Redis 實戰案例:實現分佈式鎖

分佈式鎖是 Redis 最常用的實戰場景之一,用於解決分佈式系統中併發競爭問題(如秒殺、庫存扣減)。

核心思路:

  • 利用 setnx key value 原子性:多個進程同時搶鎖,只有一個能成功(setnx 返回 1)
  • 給鎖設置過期時間:防止持有鎖的進程宕機導致鎖無法釋放
  • 釋放鎖時驗證 value:避免誤釋放其他進程的鎖(value 用唯一標識,如 UUID)

實現步驟(Python 示例):

  1. 安裝 Redis 客户端:pip install redis
  2. 代碼實現:
import redis
import uuid
import time

# 連接 Redis
redis_client = redis.Redis(
    host="127.0.0.1",
    port=6379,
    password="123456",
    decode_responses=True  # 自動解碼為字符串
)

def acquire_lock(lock_key, expire_seconds=30):
    """獲取分佈式鎖"""
    lock_value = str(uuid.uuid4())  # 唯一標識,用於釋放鎖時驗證
    # setnx + expire 原子操作(避免設置鎖後未設置過期時間進程宕機)
    success = redis_client.set(
        name=lock_key,
        value=lock_value,
        nx=True,  # 僅當鍵不存在時設置(等價於 setnx)
        ex=expire_seconds  # 過期時間(秒)
    )
    return success, lock_value

def release_lock(lock_key, lock_value):
    """釋放分佈式鎖(驗證 value,避免誤釋放)"""
    # 用 Lua 腳本保證原子性(查詢 + 刪除必須原子執行)
    lua_script = """
        if redis.call('get', KEYS[1]) == ARGV[1] then
            return redis.call('del', KEYS[1])
        else
            return 0
        end
    """
    result = redis_client.eval(lua_script, 1, lock_key, lock_value)
    return result == 1

# 測試:模擬 10 個進程搶鎖
def task(thread_id):
    lock_key = "distributed_lock"
    success, lock_value = acquire_lock(lock_key)
    if success:
        print(f"線程 {thread_id} 成功獲取鎖,開始執行任務...")
        time.sleep(2)  # 模擬任務執行
        release_lock(lock_key, lock_value)
        print(f"線程 {thread_id} 釋放鎖")
    else:
        print(f"線程 {thread_id} 搶鎖失敗,稍後重試")

# 模擬併發
if __name__ == "__main__":
    import threading
    for i in range(10):
        t = threading.Thread(target=task, args=(i,))
        t.start()

關鍵注意點:

  • 鎖的過期時間:需大於任務執行時間,避免任務未完成鎖已過期
  • 原子性:set nx ex 是原子操作,釋放鎖必須用 Lua 腳本保證原子性
  • 容錯性:如果進程持有鎖期間宕機,鎖會因過期時間自動釋放,不會死鎖

六、總結與學習資源

1. 核心要點回顧

  • Redis 是基於內存的高性能鍵值數據庫,支持 5 種核心數據結構
  • 重點掌握:String(緩存/計數)、Hash(對象存儲)、ZSet(排序)
  • 生產環境必須配置:密碼、持久化(AOF+RDB)、內存淘汰策略、集羣(高可用)
  • 避坑點:緩存穿透/擊穿/雪崩、分佈式鎖的原子性