什么是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)
bash
# 设置值
SET key "value"
# 获取值
GET key
# 设置带过期时间
SETEX key 60 "value"
# 数值操作
INCR counter
DECR counter
INCRBY counter 10
2. 哈希(Hash)
bash
# 设置哈希字段
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)
bash
# 从左侧插入
LPUSH mylist "a"
LPUSH mylist "b"
# 从右侧插入
RPUSH mylist "c"
# 获取列表
LRANGE mylist 0 -1
# 弹出元素
LPOP mylist
RPOP mylist
# 列表长度
LLEN mylist
4. 集合(Set)
bash
# 添加元素
SADD myset "a" "b" "c"
# 获取所有元素
SMEMBERS myset
# 检查元素是否存在
SISMEMBER myset "a"
# 获取集合大小
SCARD myset
# 随机弹出元素
SPOP myset
5. 有序集合(Sorted Set)
bash
# 添加元素
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)
bash
# 设置位
SETBIT mybitmap 0 1
SETBIT mybitmap 1 0
# 获取位
GETBIT mybitmap 0
# 统计位数
BITCOUNT mybitmap
2. HyperLogLog
bash
# 添加元素
PFADD visitors "user1" "user2" "user3"
# 获取基数
PFCOUNT visitors
# 合并
PFMERGE all_visitors visitors1 visitors2
3. 地理空间(Geo)
bash
# 添加地理位置
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
事务
基本事务
bash
# 开始事务
MULTI
# 命令入队
SET key1 "value1"
SET key2 "value2"
INCR counter
# 执行事务
EXEC
# 取消事务
DISCARD
乐观锁(WATCH)
bash
# 监视键
WATCH mykey
# 检查并执行
MULTI
SET mykey "newvalue"
EXEC
发布订阅
发布者
bash
# 发布消息
PUBLISH news "Hello subscribers!"
订阅者
bash
# 订阅频道
SUBSCRIBE news
# 订阅多个频道
SUBSCRIBE news sports
# 模式订阅
PSUBSCRIBE news.*
持久化
1. RDB(快照)
bash
# 配置文件
save 900 1 # 900秒内至少1个键被修改
save 300 10 # 300秒内至少10个键被修改
save 60 10000 # 60秒内至少10000个键被修改
# 手动保存
SAVE # 同步保存
BGSAVE # 异步保存
2. AOF(追加文件)
bash
# 配置AOF
appendonly yes
appendfsync everysec # 每秒同步一次
主从复制
配置主服务器
bash
# 主服务器配置
port 6379
配置从服务器
bash
# 从服务器配置
port 6380
slaveof 127.0.0.1 6379
查看复制状态
bash
# 在主服务器上
INFO replication
# 在从服务器上
INFO replication
Redis Sentinel(哨兵)
配置哨兵
bash
# sentinel.conf
sentinel monitor mymaster 127.0.0.1 6379 2
sentinel down-after-milliseconds mymaster 5000
sentinel failover-timeout mymaster 60000
启动哨兵
bash
redis-sentinel sentinel.conf
Redis Cluster(集群)
集群配置
bash
# 创建集群
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
集群操作
bash
# 查看集群信息
CLUSTER INFO
# 查看节点信息
CLUSTER NODES
# 添加节点
redis-cli --cluster add-node 127.0.0.1:7006 127.0.0.1:7000
性能优化
1. 内存优化
bash
# 设置最大内存
maxmemory 2gb
# 内存淘汰策略
maxmemory-policy allkeys-lru
2. 连接优化
bash
# 最大连接数
maxclients 10000
# TCP backlog
tcp-backlog 511
3. 慢查询日志
bash
# 启用慢查询
slowlog-log-slower-than 10000
slowlog-max-len 128
缓存应用
1. 缓存穿透
python
# 使用布隆过滤器
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. 缓存雪崩
python
# 随机过期时间
def set_cache(key, value, base_expire=3600):
# 添加随机偏移,避免同时过期
expire = base_expire + random.randint(-600, 600)
r.setex(key, expire, value)
3. 缓存击穿
python
# 使用互斥锁
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 value
finally:
r.delete(lock_key)
else:
# 等待并重试
time.sleep(0.1)
return r.get(key)
与Python集成
使用redis-py
python
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作为缓存
python
import redis
from functools import wraps
r = 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 result
return wrapper
return 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. 查看统计信息
bash
# 查看服务器信息
INFO server
# 查看内存使用
INFO memory
# 查看客户端连接
INFO clients
# 查看统计信息
INFO stats
2. 慢查询分析
bash
# 查看慢查询
SLOWLOG GET 10
# 清空慢查询日志
SLOWLOG RESET
3. 内存分析
bash
# 查看内存使用
MEMORY USAGE key
# 查看键的编码
OBJECT ENCODING key
优缺点分析
优点
- 极高的性能
- 丰富的数据结构
- 支持持久化
- 高可用性
- 易于扩展
缺点
- 内存消耗大
- 单线程模型
- 不支持复杂查询
- 数据一致性较弱
学习资源推荐
- 官方文档:https://redis.io/documentation
- 在线教程:Redis Tutorial
- 书籍:《Redis设计与实现》、《Redis实战》
- 实践项目:缓存系统、实时排行榜、消息队列
总结
Redis作为内存数据库的王者,凭借其极高的性能和丰富的数据结构,在现代应用架构中扮演着重要角色。无论是作为缓存、消息队列还是实时数据处理系统,Redis都能提供出色的性能表现。对于需要高性能、低延迟的应用场景,Redis是不可或缺的技术选择。