什么是Redis?
Redis(Remote Dictionary Server)是一個開源的、基于內存的數據結構存儲系統,可以用作數據庫、緩存和消息代理。它支持多種數據結構,如字符串、哈希、列表、集合、有序集合等,具有極高的性能和豐富的功能。
核心特性
1. 內存存儲
- 數據主要存儲在內存中,讀寫速度極快
- 支持持久化到磁盤,保證數據安全
- 支持數據過期自動刪除
2. 豐富的數據結構
- String:字符串
- Hash:哈希表
- List:列表
- Set:集合
- Sorted Set:有序集合
- Bitmap:位圖
- HyperLogLog:基數統計
- Stream:流數據
3. 高性能
- 單線程模型,避免上下文切換
- 基于內存操作,讀寫性能極高
- 支持管道(pipeline)批量操作
4. 高可用
- 主從復制
- Redis Sentinel(哨兵)
- Redis Cluster(集群)
數據結構與操作
1. 字符串(String)
# 設置值
SET key "value"# 獲取值
GET key# 設置帶過期時間
SETEX key 60 "value"# 數值操作
INCR counter
DECR counter
INCRBY counter 10
2. 哈希(Hash)
# 設置哈希字段
HSET user:1000 name "John"
HSET user:1000 email "john@example.com"
HMSET user:1000 name "John" email "john@example.com" age 30# 獲取哈希字段
HGET user:1000 name
HGETALL user:1000
HMGET user:1000 name email# 哈希操作
HINCRBY user:1000 age 1
HLEN user:1000
3. 列表(List)
# 從左側插入
LPUSH mylist "a"
LPUSH mylist "b"# 從右側插入
RPUSH mylist "c"# 獲取列表
LRANGE mylist 0 -1# 彈出元素
LPOP mylist
RPOP mylist# 列表長度
LLEN mylist
4. 集合(Set)
# 添加元素
SADD myset "a" "b" "c"# 獲取所有元素
SMEMBERS myset# 檢查元素是否存在
SISMEMBER myset "a"# 獲取集合大小
SCARD myset# 隨機彈出元素
SPOP myset
5. 有序集合(Sorted Set)
# 添加元素
ZADD leaderboard 100 "Alice" 200 "Bob" 150 "Charlie"# 獲取排名
ZRANGE leaderboard 0 -1
ZREVRANGE leaderboard 0 -1# 獲取分數
ZSCORE leaderboard "Alice"# 按分數范圍獲取
ZRANGEBYSCORE leaderboard 100 200# 獲取排名
ZRANK leaderboard "Alice"
高級數據結構
1. 位圖(Bitmap)
# 設置位
SETBIT mybitmap 0 1
SETBIT mybitmap 1 0# 獲取位
GETBIT mybitmap 0# 統計位數
BITCOUNT mybitmap
2. HyperLogLog
# 添加元素
PFADD visitors "user1" "user2" "user3"# 獲取基數
PFCOUNT visitors# 合并
PFMERGE all_visitors visitors1 visitors2
3. 地理空間(Geo)
# 添加地理位置
GEOADD locations 13.361389 38.115556 "Palermo" 15.087269 37.502669 "Catania"# 計算距離
GEODIST locations "Palermo" "Catania"# 獲取位置
GEOPOS locations "Palermo"# 半徑查詢
GEORADIUS locations 15 37 100 km
事務
基本事務
# 開始事務
MULTI# 命令入隊
SET key1 "value1"
SET key2 "value2"
INCR counter# 執行事務
EXEC# 取消事務
DISCARD
樂觀鎖(WATCH)
# 監視鍵
WATCH mykey# 檢查并執行
MULTI
SET mykey "newvalue"
EXEC
發布訂閱
發布者
# 發布消息
PUBLISH news "Hello subscribers!"
訂閱者
# 訂閱頻道
SUBSCRIBE news# 訂閱多個頻道
SUBSCRIBE news sports# 模式訂閱
PSUBSCRIBE news.*
持久化
1. RDB(快照)
# 配置文件
save 900 1 # 900秒內至少1個鍵被修改
save 300 10 # 300秒內至少10個鍵被修改
save 60 10000 # 60秒內至少10000個鍵被修改# 手動保存
SAVE # 同步保存
BGSAVE # 異步保存
2. AOF(追加文件)
# 配置AOF
appendonly yes
appendfsync everysec # 每秒同步一次
主從復制
配置主服務器
# 主服務器配置
port 6379
配置從服務器
# 從服務器配置
port 6380
slaveof 127.0.0.1 6379
查看復制狀態
# 在主服務器上
INFO replication# 在從服務器上
INFO replication
Redis Sentinel(哨兵)
配置哨兵
# sentinel.conf
sentinel monitor mymaster 127.0.0.1 6379 2
sentinel down-after-milliseconds mymaster 5000
sentinel failover-timeout mymaster 60000
啟動哨兵
redis-sentinel sentinel.conf
Redis Cluster(集群)
集群配置
# 創建集群
redis-cli --cluster create 127.0.0.1:7000 127.0.0.1:7001 \
127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005 \
--cluster-replicas 1
集群操作
# 查看集群信息
CLUSTER INFO# 查看節點信息
CLUSTER NODES# 添加節點
redis-cli --cluster add-node 127.0.0.1:7006 127.0.0.1:7000
性能優化
1. 內存優化
# 設置最大內存
maxmemory 2gb# 內存淘汰策略
maxmemory-policy allkeys-lru
2. 連接優化
# 最大連接數
maxclients 10000# TCP backlog
tcp-backlog 511
3. 慢查詢日志
# 啟用慢查詢
slowlog-log-slower-than 10000
slowlog-max-len 128
緩存應用
1. 緩存穿透
# 使用布隆過濾器
import redis
r = redis.Redis()def get_user(user_id):# 先檢查布隆過濾器if not r.exists(f"user:{user_id}"):return None# 從緩存獲取user = r.get(f"user:{user_id}")if user:return json.loads(user)# 從數據庫獲取user = db.get_user(user_id)if user:r.setex(f"user:{user_id}", 3600, json.dumps(user))else:# 緩存空值,防止穿透r.setex(f"user:{user_id}", 300, "null")return user
2. 緩存雪崩
# 隨機過期時間
def set_cache(key, value, base_expire=3600):# 添加隨機偏移,避免同時過期expire = base_expire + random.randint(-600, 600)r.setex(key, expire, value)
3. 緩存擊穿
# 使用互斥鎖
def get_hot_data(key):value = r.get(key)if value:return value# 獲取鎖lock_key = f"lock:{key}"if r.set(lock_key, 1, nx=True, ex=5):try:# 從數據庫獲取數據value = db.get_data(key)r.setex(key, 3600, value)return valuefinally:r.delete(lock_key)else:# 等待并重試time.sleep(0.1)return r.get(key)
與Python集成
使用redis-py
import redis
import json# 連接Redis
r = redis.Redis(host='localhost', port=6379, db=0)# 字符串操作
r.set('name', 'Alice')
name = r.get('name')# 哈希操作
r.hset('user:1000', mapping={'name': 'John','email': 'john@example.com','age': 30
})
user = r.hgetall('user:1000')# 列表操作
r.lpush('tasks', 'task1', 'task2')
tasks = r.lrange('tasks', 0, -1)# 集合操作
r.sadd('tags', 'python', 'redis', 'database')
tags = r.smembers('tags')# 有序集合
r.zadd('scores', {'Alice': 100, 'Bob': 200})
top_scores = r.zrevrange('scores', 0, 10, withscores=True)
使用Redis作為緩存
import redis
from functools import wrapsr = redis.Redis()def cache_decorator(expire_time=3600):def decorator(func):@wraps(func)def wrapper(*args, **kwargs):cache_key = f"{func.__name__}:{str(args)}:{str(kwargs)}"cached = r.get(cache_key)if cached:return json.loads(cached)result = func(*args, **kwargs)r.setex(cache_key, expire_time, json.dumps(result))return resultreturn wrapperreturn decorator@cache_decorator(expire_time=1800)
def get_user_profile(user_id):# 模擬數據庫查詢return {"id": user_id, "name": "John", "email": "john@example.com"}
常見應用場景
1. 緩存系統
- 頁面緩存
- 數據緩存
- 會話緩存
2. 計數器
- 網站訪問量
- 點贊數
- 庫存管理
3. 消息隊列
- 任務隊列
- 發布訂閱
- 實時消息
4. 排行榜
- 游戲排行榜
- 熱門文章
- 用戶積分
5. 實時系統
- 在線用戶
- 實時統計
- 地理位置
監控與管理
1. 查看統計信息
# 查看服務器信息
INFO server# 查看內存使用
INFO memory# 查看客戶端連接
INFO clients# 查看統計信息
INFO stats
2. 慢查詢分析
# 查看慢查詢
SLOWLOG GET 10# 清空慢查詢日志
SLOWLOG RESET
3. 內存分析
# 查看內存使用
MEMORY USAGE key# 查看鍵的編碼
OBJECT ENCODING key
優缺點分析
優點
- 極高的性能
- 豐富的數據結構
- 支持持久化
- 高可用性
- 易于擴展
缺點
- 內存消耗大
- 單線程模型
- 不支持復雜查詢
- 數據一致性較弱
學習資源推薦
- 官方文檔:https://redis.io/documentation
- 在線教程:Redis Tutorial
- 書籍:《Redis設計與實現》、《Redis實戰》
- 實踐項目:緩存系統、實時排行榜、消息隊列
總結
Redis作為內存數據庫的王者,憑借其極高的性能和豐富的數據結構,在現代應用架構中扮演著重要角色。無論是作為緩存、消息隊列還是實時數據處理系統,Redis都能提供出色的性能表現。對于需要高性能、低延遲的應用場景,Redis是不可或缺的技術選擇。