什么是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)
1 2 3 4 5 6 7 8 9 10 11 12 13
| SET key "value"
GET key
SETEX key 60 "value"
INCR counter DECR counter INCRBY counter 10
|
2. 哈希(Hash)
1 2 3 4 5 6 7 8 9 10 11 12 13
| 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)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| LPUSH mylist "a" LPUSH mylist "b"
RPUSH mylist "c"
LRANGE mylist 0 -1
LPOP mylist RPOP mylist
LLEN mylist
|
4. 集合(Set)
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| SADD myset "a" "b" "c"
SMEMBERS myset
SISMEMBER myset "a"
SCARD myset
SPOP myset
|
5. 有序集合(Sorted Set)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| 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)
1 2 3 4 5 6 7 8 9
| SETBIT mybitmap 0 1 SETBIT mybitmap 1 0
GETBIT mybitmap 0
BITCOUNT mybitmap
|
2. HyperLogLog
1 2 3 4 5 6 7 8
| PFADD visitors "user1" "user2" "user3"
PFCOUNT visitors
PFMERGE all_visitors visitors1 visitors2
|
3. 地理空间(Geo)
1 2 3 4 5 6 7 8 9 10 11
| 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
|
事务
基本事务
1 2 3 4 5 6 7 8 9 10 11 12 13
| MULTI
SET key1 "value1" SET key2 "value2" INCR counter
EXEC
DISCARD
|
乐观锁(WATCH)
1 2 3 4 5 6 7
| WATCH mykey
MULTI SET mykey "newvalue" EXEC
|
发布订阅
发布者
1 2
| PUBLISH news "Hello subscribers!"
|
订阅者
1 2 3 4 5 6 7 8
| SUBSCRIBE news
SUBSCRIBE news sports
PSUBSCRIBE news.*
|
持久化
1. RDB(快照)
1 2 3 4 5 6 7 8
| save 900 1 save 300 10 save 60 10000
SAVE BGSAVE
|
2. AOF(追加文件)
1 2 3
| appendonly yes appendfsync everysec
|
主从复制
配置主服务器
配置从服务器
1 2 3
| port 6380 slaveof 127.0.0.1 6379
|
查看复制状态
1 2 3 4 5
| INFO replication
INFO replication
|
Redis Sentinel(哨兵)
配置哨兵
1 2 3 4
| sentinel monitor mymaster 127.0.0.1 6379 2 sentinel down-after-milliseconds mymaster 5000 sentinel failover-timeout mymaster 60000
|
启动哨兵
1
| redis-sentinel sentinel.conf
|
Redis Cluster(集群)
集群配置
1 2 3 4
| 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
|
集群操作
1 2 3 4 5 6 7 8
| CLUSTER INFO
CLUSTER NODES
redis-cli --cluster add-node 127.0.0.1:7006 127.0.0.1:7000
|
性能优化
1. 内存优化
1 2 3 4 5
| maxmemory 2gb
maxmemory-policy allkeys-lru
|
2. 连接优化
1 2 3 4 5
| maxclients 10000
tcp-backlog 511
|
3. 慢查询日志
1 2 3
| slowlog-log-slower-than 10000 slowlog-max-len 128
|
缓存应用
1. 缓存穿透
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| 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. 缓存雪崩
1 2 3 4 5
| def set_cache(key, value, base_expire=3600): expire = base_expire + random.randint(-600, 600) r.setex(key, expire, value)
|
3. 缓存击穿
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| 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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| import redis import json
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作为缓存
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| 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. 查看统计信息
1 2 3 4 5 6 7 8 9 10 11
| INFO server
INFO memory
INFO clients
INFO stats
|
2. 慢查询分析
1 2 3 4 5
| SLOWLOG GET 10
SLOWLOG RESET
|
3. 内存分析
1 2 3 4 5
| MEMORY USAGE key
OBJECT ENCODING key
|
优缺点分析
优点
- 极高的性能
- 丰富的数据结构
- 支持持久化
- 高可用性
- 易于扩展
缺点
- 内存消耗大
- 单线程模型
- 不支持复杂查询
- 数据一致性较弱
学习资源推荐
总结
Redis作为内存数据库的王者,凭借其极高的性能和丰富的数据结构,在现代应用架构中扮演着重要角色。无论是作为缓存、消息队列还是实时数据处理系统,Redis都能提供出色的性能表现。对于需要高性能、低延迟的应用场景,Redis是不可或缺的技术选择。