Redis核心概念、数据类型与高可用架构详解
1. Redis核心概念与适用场景
Redis(Remote Dictionary Server)是一个开源的、基于内存的键值存储系统,它支持多种数据结构,包括字符串(strings)、哈希(hashes)、列表(lists)、集合(sets)、有序集合(sorted sets)等。与传统的关系型数据库不同,Redis将数据存储在内存中,这使得它的读写速度极快,通常能达到微秒级别的响应时间。
Redis最初由Salvatore Sanfilippo开发,现在由Redis Labs维护。它的设计目标是成为一个高性能的键值存储系统,同时提供丰富的数据结构和操作命令。Redis不仅可以用作缓存,还可以作为消息队列、会话存储、实时分析系统等多种用途。
1.1 Redis的核心特性
Redis之所以广受欢迎,主要得益于以下几个核心特性:
内存存储:Redis将所有数据保存在内存中,这使得它的读写速度非常快。当然,Redis也提供了持久化机制,可以将内存中的数据定期保存到磁盘上,防止数据丢失。
丰富的数据结构:Redis不仅仅支持简单的键值对存储,还提供了多种高级数据结构:
- 字符串(Strings):最基本的键值对
- 哈希(Hashes):适合存储对象
- 列表(Lists):有序的字符串集合
- 集合(Sets):无序的唯一字符串集合
- 有序集合(Sorted Sets):带分数的集合,可以按分数排序
- 位图(Bitmaps):位操作
- HyperLogLogs:基数估算
- 地理空间索引(Geospatial indexes):地理位置相关操作
原子操作:Redis的所有操作都是原子性的,这意味着在多客户端并发访问时,不会出现数据不一致的问题。
持久化:Redis提供了两种持久化方式:
- RDB(Redis Database):定时快照
- AOF(Append Only File):记录所有写操作
高可用和分布式:Redis支持主从复制、哨兵模式和集群模式,可以构建高可用的分布式系统。
发布/订阅:Redis内置了发布/订阅功能,可以用作简单的消息队列。
1.2 Redis的适用场景
Redis虽然功能强大,但并不是万能的。以下是Redis最擅长的几种应用场景:
缓存:这是Redis最常见的用途。将热点数据存储在Redis中,可以显著提高应用的响应速度,减轻后端数据库的压力。
会话存储:Web应用通常需要存储用户会话信息。使用Redis存储会话数据,比传统的基于文件的会话存储更高效,特别是在分布式系统中。
排行榜/计数器:Redis的有序集合非常适合实现排行榜功能。它的原子性操作也适合实现计数器。
消息队列:Redis的列表和发布/订阅功能可以用作简单的消息队列系统。
实时系统:需要快速响应的系统,如实时分析、实时推荐等,都可以利用Redis的高性能特性。
分布式锁:Redis的原子性操作和过期特性可以用来实现分布式锁。
1.3 Redis的局限性
虽然Redis功能强大,但也有一些局限性需要注意:
内存限制:由于数据存储在内存中,Redis的数据量受限于可用内存大小。虽然可以使用LRU等策略淘汰旧数据,但对于大数据量的场景,可能需要考虑其他解决方案。
持久化性能:虽然Redis提供了持久化功能,但在数据量很大时,RDB快照和AOF重写可能会影响性能。
单线程模型:Redis使用单线程处理命令(6.0版本后引入了多线程I/O),这意味着复杂的操作可能会阻塞其他请求。
事务限制:Redis的事务不像关系型数据库那样支持回滚。如果事务中的某个命令失败,其他命令仍然会执行。
在实际应用中,我们需要根据具体需求权衡Redis的优势和局限性,合理设计系统架构。
2. Redis安装与配置
2.1 在不同操作系统上安装Redis
Redis可以运行在多种操作系统上,包括Linux、macOS和Windows。下面我们分别介绍在不同系统上的安装方法。
2.1.1 Linux系统安装Redis
在Linux上安装Redis通常有以下几种方式:
使用包管理器安装(推荐): 对于基于Debian的系统(如Ubuntu):
sudo apt update sudo apt install redis-server对于基于RHEL的系统(如CentOS):
sudo yum install epel-release sudo yum install redis从源码编译安装: 如果需要特定版本的Redis,可以从源码编译安装:
wget https://download.redis.io/releases/redis-6.2.6.tar.gz tar xzf redis-6.2.6.tar.gz cd redis-6.2.6 make sudo make install使用Docker运行Redis:
docker run --name some-redis -d redis
2.1.2 Windows系统安装Redis
官方Redis不支持Windows,但微软维护了一个Windows兼容版本:
下载Windows版Redis: 可以从GitHub仓库下载最新版本:https://github.com/microsoftarchive/redis/releases
解压并运行: 下载后解压zip文件,然后运行redis-server.exe启动服务器,redis-cli.exe启动客户端。
作为服务安装(可选):
redis-server --service-install redis.windows.conf --loglevel verbose
注意:生产环境建议使用Linux系统运行Redis,Windows版本主要用于开发和测试。
2.1.3 macOS系统安装Redis
在macOS上,可以使用Homebrew安装Redis:
brew install redis启动Redis服务:
brew services start redis或者手动启动:
redis-server /usr/local/etc/redis.conf2.2 Redis配置文件详解
Redis的配置文件通常名为redis.conf,它包含了Redis运行时的各种参数设置。下面介绍一些重要的配置项:
网络相关配置:
bind 127.0.0.1 # 绑定的IP地址 port 6379 # 监听端口 protected-mode yes # 保护模式通用配置:
daemonize yes # 是否以守护进程运行 pidfile /var/run/redis.pid # pid文件位置 loglevel notice # 日志级别 logfile "" # 日志文件路径,空表示标准输出 databases 16 # 数据库数量持久化配置:
save 900 1 # 900秒内至少有1个key被修改则触发保存 save 300 10 # 300秒内至少有10个key被修改则触发保存 save 60 10000 # 60秒内至少有10000个key被修改则触发保存 rdbcompression yes # 是否压缩RDB文件 dbfilename dump.rdb # RDB文件名 dir ./ # 工作目录 appendonly no # 是否开启AOF appendfilename "appendonly.aof" # AOF文件名内存管理:
maxmemory 100mb # 最大内存限制 maxmemory-policy volatile-lru # 内存达到上限时的策略安全配置:
requirepass foobared # 设置密码客户端配置:
maxclients 10000 # 最大客户端连接数 timeout 0 # 客户端空闲超时时间,0表示不超时高级配置:
hash-max-ziplist-entries 512 # 哈希使用ziplist的阈值 hash-max-ziplist-value 64 # 哈希使用ziplist的阈值
在实际应用中,我们需要根据服务器的硬件配置和应用需求调整这些参数。例如,对于内存有限的服务器,应该设置合理的maxmemory和maxmemory-policy;对于安全性要求高的环境,应该设置requirepass并限制bind IP。
2.3 Redis服务管理
安装完成后,我们需要知道如何管理Redis服务:
启动Redis:
redis-server /path/to/redis.conf停止Redis: 可以使用客户端发送SHUTDOWN命令:
redis-cli shutdown或者直接kill进程:
kill `cat /var/run/redis.pid`重启Redis: 先停止再启动,或者使用:
redis-cli shutdown && redis-server /path/to/redis.conf查看Redis状态:
redis-cli ping # 应该返回PONG redis-cli info # 查看详细信息设置开机启动(Linux): 对于systemd系统:
sudo systemctl enable redis
对于Windows系统,可以通过服务管理器来启动、停止和设置自动启动Redis服务。
3. Redis数据类型与常用命令
Redis支持多种数据类型,每种类型都有其特定的用途和操作命令。理解这些数据类型及其适用场景是高效使用Redis的关键。
3.1 字符串(Strings)
字符串是Redis最基本的数据类型,可以存储文本、数字或二进制数据(最大512MB)。
常用命令:
SET key value:设置键值对GET key:获取键的值DEL key:删除键INCR key:将键的值加1DECR key:将键的值减1INCRBY key increment:将键的值增加指定数值DECRBY key decrement:将键的值减少指定数值APPEND key value:追加值STRLEN key:获取值的长度SETEX key seconds value:设置键值对并指定过期时间SETNX key value:键不存在时才设置
使用场景:
- 缓存HTML片段或页面
- 计数器
- 存储用户会话信息
- 简单的键值存储
示例:
127.0.0.1:6379> SET user:1000 "John Doe" OK 127.0.0.1:6379> GET user:1000 "John Doe" 127.0.0.1:6379> INCR counter (integer) 1 127.0.0.1:6379> INCR counter (integer) 2 127.0.0.1:6379> SETEX session:1234 3600 "user_data" OK3.2 哈希(Hashes)
哈希是字段和值的映射表,适合存储对象。
常用命令:
HSET key field value:设置哈希字段的值HGET key field:获取哈希字段的值HGETALL key:获取所有字段和值HDEL key field:删除哈希字段HKEYS key:获取所有字段名HVALS key:获取所有字段值HLEN key:获取字段数量HINCRBY key field increment:增加哈希字段的数值
使用场景:
- 存储用户对象(姓名、年龄、邮箱等)
- 存储产品信息
- 存储任何需要多个字段的对象
示例:
127.0.0.1:6379> HSET user:1000 name "John Doe" age 30 email "john@example.com" (integer) 3 127.0.0.1:6379> HGET user:1000 name "John Doe" 127.0.0.1:6379> HGETALL user:1000 1) "name" 2) "John Doe" 3) "age" 4) "30" 5) "email" 6) "john@example.com" 127.0.0.1:6379> HINCRBY user:1000 age 1 (integer) 313.3 列表(Lists)
列表是简单的字符串列表,按照插入顺序排序,可以在头部或尾部添加元素。
常用命令:
LPUSH key value:从列表头部插入值RPUSH key value:从列表尾部插入值LPOP key:移除并返回列表头部的元素RPOP key:移除并返回列表尾部的元素LRANGE key start stop:获取列表指定范围的元素LLEN key:获取列表长度LINDEX key index:获取列表指定位置的元素LREM key count value:移除列表中与value相等的元素
使用场景:
- 消息队列
- 最新消息列表
- 记录用户的操作历史
示例:
127.0.0.1:6379> LPUSH messages "hello" (integer) 1 127.0.0.1:6379> LPUSH messages "world" (integer) 2 127.0.0.1:6379> LRANGE messages 0 -1 1) "world" 2) "hello" 127.0.0.1:6379> RPUSH messages "!" (integer) 3 127.0.0.1:6379> LRANGE messages 0 -1 1) "world" 2) "hello" 3) "!"3.4 集合(Sets)
集合是字符串的无序集合,元素唯一不重复。
常用命令:
SADD key member:向集合添加元素SMEMBERS key:获取集合所有元素SISMEMBER key member:判断元素是否在集合中SCARD key:获取集合元素数量SREM key member:移除集合元素SINTER key1 key2:返回多个集合的交集SUNION key1 key2:返回多个集合的并集SDIFF key1 key2:返回第一个集合与其他集合的差集
使用场景:
- 标签系统
- 好友关系
- 唯一IP记录
- 投票系统(防止重复投票)
示例:
127.0.0.1:6379> SADD tags "redis" "database" "nosql" (integer) 3 127.0.0.1:6379> SMEMBERS tags 1) "nosql" 2) "database" 3) "redis" 127.0.0.1:6379> SADD tags "redis" (integer) 0 # 已经存在,不添加 127.0.0.1:6379> SISMEMBER tags "database" (integer) 13.5 有序集合(Sorted Sets)
有序集合类似于集合,但每个元素都关联一个分数(score),用于排序。
常用命令:
ZADD key score member:向有序集合添加元素ZRANGE key start stop [WITHSCORES]:按分数升序返回元素ZREVRANGE key start stop [WITHSCORES]:按分数降序返回元素ZRANK key member:返回元素的升序排名ZREVRANK key member:返回元素的降序排名ZSCORE key member:返回元素的分数ZCARD key:返回元素数量ZCOUNT key min max:返回分数范围内的元素数量ZREM key member:移除元素
使用场景:
- 排行榜
- 带权重的消息队列
- 范围查询(如时间范围)
示例:
127.0.0.1:6379> ZADD leaderboard 100 "player1" 200 "player2" 300 "player3" (integer) 3 127.0.0.1:6379> ZRANGE leaderboard 0 -1 WITHSCORES 1) "player1" 2) "100" 3) "player2" 4) "200" 5) "player3" 6) "300" 127.0.0.1:6379> ZREVRANGE leaderboard 0 1 WITHSCORES 1) "player3" 2) "300" 3) "player2" 4) "200" 127.0.0.1:6379> ZINCRBY leaderboard 50 "player1" "150"3.6 其他数据类型
除了上述五种主要数据类型,Redis还支持:
位图(Bitmaps): 实际上是字符串的位操作,可以用来实现布隆过滤器、用户在线状态等。
HyperLogLogs: 用于基数统计(估算集合中不重复元素的数量),占用空间固定。
地理空间索引(Geospatial indexes): 可以存储地理位置信息,并进行距离计算等操作。
流(Streams)(Redis 5.0+): 消息队列的增强实现,支持消费者组等高级特性。
4. Redis高级特性与实战应用
4.1 Redis持久化机制
Redis提供了两种持久化方式:RDB(Redis Database)和AOF(Append Only File)。理解这两种机制对于保证数据安全至关重要。
4.1.1 RDB持久化
RDB是Redis默认的持久化方式,它会在指定时间间隔内生成数据集的时间点快照。
工作原理:
- Redis会fork一个子进程
- 子进程将数据集写入临时RDB文件
- 写入完成后,替换旧的RDB文件
优点:
- 紧凑的单一文件,适合备份
- 恢复大数据集时比AOF快
- 最大化Redis性能(父进程不需要磁盘I/O)
缺点:
- 可能会丢失最后一次快照后的数据
- 数据集很大时,fork可能会耗时较长
配置示例:
save 900 1 # 15分钟内至少有1个key变化 save 300 10 # 5分钟内至少有10个key变化 save 60 10000 # 1分钟内至少有10000个key变化 dbfilename dump.rdb dir ./4.1.2 AOF持久化
AOF记录服务器接收到的每个写操作,并在服务器启动时重新执行这些操作来重建数据集。
工作原理:
- 所有写命令被追加到AOF缓冲区
- 根据配置的同步策略,将缓冲区内容写入AOF文件
- 当AOF文件过大时,会进行重写(rewrite)以压缩文件
同步策略:
appendfsync always:每个写命令都同步到磁盘,最安全但性能最低appendfsync everysec:每秒同步一次,折中方案(默认)appendfsync no:由操作系统决定何时同步,性能最好但可能丢失数据
优点:
- 数据安全性更高(最多丢失1秒数据)
- AOF文件易于理解和解析
- 自动处理AOF文件过大问题(重写)
缺点:
- AOF文件通常比RDB文件大
- 恢复速度比RDB慢
- 在某些情况下AOF可能比RDB慢
配置示例:
appendonly yes appendfilename "appendonly.aof" appendfsync everysec auto-aof-rewrite-percentage 100 auto-aof-rewrite-min-size 64mb4.1.3 如何选择持久化方式
- 如果数据安全性要求不高,可以只使用RDB
- 如果数据不能丢失,应该使用AOF
- 也可以同时启用两种持久化方式(推荐)
- 生产环境建议至少使用AOF的
appendfsync everysec配置
4.2 Redis事务
Redis事务允许一次执行多个命令,并且保证这些命令按顺序执行,中间不会被其他客户端命令打断。
事务相关命令:
MULTI:标记事务开始EXEC:执行事务中的所有命令DISCARD:取消事务WATCH key:监视一个或多个key,如果在事务执行前这些key被其他命令改动,则事务被打断UNWATCH:取消所有WATCH
事务特性:
- 原子性:Redis事务是原子性的,但与传统数据库不同,它不支持回滚。如果事务中某个命令失败,其他命令仍然会执行。
- 隔离性:事务中的所有命令都会序列化、按顺序执行,不会被其他客户端命令打断。
- 一致性:事务可以保证命令失败时数据的一致性。
- 持久性:取决于Redis的持久化配置。
示例:
127.0.0.1:6379> WATCH balance OK 127.0.0.1:6379> MULTI OK 127.0.0.1:6379> DECRBY balance 10 QUEUED 127.0.0.1:6379> INCRBY debt 10 QUEUED 127.0.0.1:6379> EXEC 1) (integer) 90 2) (integer) 10注意事项:
- Redis事务不支持回滚,如果某个命令失败,需要客户端自己处理
- WATCH可以实现乐观锁,但要注意性能影响
- 事务中的命令不会立即执行,而是在EXEC时一起执行
4.3 Redis发布/订阅
Redis的发布/订阅(Pub/Sub)功能可以实现消息的广播。
相关命令:
PUBLISH channel message:向指定频道发布消息SUBSCRIBE channel [channel ...]:订阅一个或多个频道PSUBSCRIBE pattern [pattern ...]:订阅匹配模式的频道UNSUBSCRIBE [channel [channel ...]]:退订频道PUNSUBSCRIBE [pattern [pattern ...]]:退订匹配模式的频道
特点:
- 消息是即时的,没有持久化
- 订阅者只能收到订阅后发布的消息
- 适合简单的消息通知场景
示例:
# 客户端1订阅频道 127.0.0.1:6379> SUBSCRIBE news Reading messages... (press Ctrl-C to quit) 1) "subscribe" 2) "news" 3) (integer) 1 # 客户端2发布消息 127.0.0.1:6379> PUBLISH news "hello world" (integer) 1 # 客户端1收到消息 1) "message" 2) "news" 3) "hello world"使用场景:
- 实时通知系统
- 简单的聊天应用
- 事件广播
局限性:
- 消息不持久化,订阅者离线时会丢失消息
- 没有消息确认机制
- 不适合可靠的消息队列场景
4.4 Lua脚本
Redis支持使用Lua脚本执行复杂的操作,这些操作是原子性的。
优点:
- 减少网络开销(多个操作可以在一个脚本中完成)
- 原子性执行
- 复用性(脚本可以被缓存)
相关命令:
EVAL script numkeys key [key ...] arg [arg ...]:执行Lua脚本EVALSHA sha1 numkeys key [key ...] arg [arg ...]:通过SHA1执行缓存的脚本SCRIPT LOAD script:加载脚本到缓存SCRIPT EXISTS sha1 [sha1 ...]:检查脚本是否在缓存中SCRIPT FLUSH:清空脚本缓存SCRIPT KILL:杀死正在运行的脚本
示例:
-- 限流脚本:限制1分钟内最多访问10次 local key = KEYS[1] local limit = tonumber(ARGV[1]) local expire_time = tonumber(ARGV[2]) local current = tonumber(redis.call('GET', key) or "0") if current + 1 > limit then return 0 else redis.call('INCR', key) if current == 0 then redis.call('EXPIRE', key, expire_time) end return 1 end使用方式:
redis-cli --eval rate_limiter.lua rate:user1 , 10 60注意事项:
- 脚本应该尽量简单,避免长时间运行的脚本阻塞Redis
- 脚本中的错误不会回滚已经执行的操作
- 可以使用
redis.replicate_commands()来确保脚本在集群环境中的正确复制
4.5 Redis模块
Redis 4.0引入了模块系统,允许开发者扩展Redis的功能。一些常用的模块包括:
- RediSearch:全文搜索功能
- RedisJSON:原生JSON支持
- RedisGraph:图数据库功能
- RedisTimeSeries:时间序列数据处理
- RedisBloom:布隆过滤器等概率数据结构
加载模块: 在redis.conf中配置:
loadmodule /path/to/module.so或者启动时指定:
redis-server --loadmodule /path/to/module.so使用示例(RedisJSON):
127.0.0.1:6379> JSON.SET user:1000 . '{"name":"John","age":30}' OK 127.0.0.1:6379> JSON.GET user:1000 "{\"name\":\"John\",\"age\":30}" 127.0.0.1:6379> JSON.GET user:1000 .name "\"John\""模块为Redis提供了强大的扩展能力,可以根据项目需求选择合适的模块来增强Redis的功能。
5. Redis高可用与集群
5.1 Redis主从复制
主从复制是Redis高可用的基础,它允许从服务器(slave)精确复制主服务器(master)的数据。
工作原理:
- 从服务器连接主服务器,发送SYNC命令
- 主服务器执行BGSAVE生成RDB文件,同时缓冲新的写命令
- 主服务器将RDB文件发送给从服务器
- 从服务器载入RDB文件
- 主服务器将缓冲的写命令发送给从服务器
- 之后主服务器的每个写命令都会发送给从服务器
配置方法: 在从服务器的redis.conf中配置:
replicaof <masterip> <masterport> masterauth <master-password> # 如果主服务器有密码 replica-read-only yes # 从服务器只读或者运行时使用命令:
REPLICAOF 127.0.0.1 6379 CONFIG SET replica-read-only yes优点:
- 数据冗余,提高数据安全性
- 读写分离,提高性能
- 故障恢复的基础
缺点:
- 主从复制是异步的,可能会有数据不一致的窗口期
- 主服务器故障时需要手动干预
5.2 Redis哨兵(Sentinel)
哨兵是Redis官方提供的高可用解决方案,它可以监控主从服务器,并在主服务器故障时自动进行故障转移。
主要功能:
- 监控:检查主从服务器是否正常运行
- 通知:当被监控的Redis实例出现问题时,可以通过API通知管理员
- 自动故障转移:如果主服务器不可用,可以自动将一个从服务器升级为主服务器,并让其他从服务器复制新的主服务器
- 配置提供者:客户端可以查询哨兵获取当前Redis主服务器的地址
配置方法: 创建sentinel.conf配置文件:
port 26379 sentinel monitor mymaster 127.0.0.1 6379 2 sentinel down-after-milliseconds mymaster 5000 sentinel failover-timeout mymaster 60000 sentinel parallel-syncs mymaster 1启动哨兵:
redis-sentinel /path/to/sentinel.conf关键配置项:
sentinel monitor <master-name> <ip> <port> <quorum>:定义监控的主服务器sentinel down-after-milliseconds <master-name> <milliseconds>:认为服务器不可用的时间阈值sentinel failover-timeout <master-name> <milliseconds>:故障转移超时时间sentinel parallel-syncs <master-name> <num>:故障转移后同时同步的从服务器数量
客户端连接: 客户端应该连接哨兵获取当前的主服务器地址,而不是直接连接主服务器。大多数Redis客户端都支持哨兵模式。
5.3 Redis集群
Redis集群是Redis的分布式解决方案,它通过分片(sharding)将数据分布在多个节点上,并提供一定程度的可用性。
集群特点:
- 数据自动分片到多个节点
- 部分节点故障时仍能继续工作
- 所有节点相互连接,使用gossip协议传播信息
- 客户端可以直接连接任意节点,节点会重定向请求
数据分片: Redis集群使用哈希槽(hash slot)来分片,共有16384个槽。每个键通过CRC16算法计算后取模16384确定其槽位。
集群配置:
- 修改每个节点的redis.conf:
cluster-enabled yes cluster-config-file nodes-6379.conf cluster-node-timeout 15000- 启动所有节点后,使用redis-cli创建集群:
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:查看集群节点CLUSTER MEET:将节点加入集群CLUSTER FORGET:从集群中移除节点CLUSTER REPLICATE:将当前节点设置为指定节点的从节点
客户端使用: 大多数Redis客户端支持集群模式,可以自动处理重定向。也可以使用redis-cli连接集群:
redis-cli -c -p 7000 # -c表示集群模式注意事项:
- 集群不支持多键操作,除非这些键在同一个槽
- 集群的最小主节点数是3
- 建议每个主节点至少有一个从节点
- 集群不支持SELECT命令,只能使用数据库0
5.4 Redis高可用方案选择
根据不同的需求场景,可以选择不同的高可用方案:
单机模式:
- 适用场景:开发环境、测试环境
- 特点:简单,无高可用
主从复制+哨兵:
- 适用场景:中小规模生产环境,读写分离
- 特点:自动故障转移,读写分离,配置简单
Redis集群:
- 适用场景:大规模生产环境,需要水平扩展
- 特点:数据分片,自动故障转移,可扩展性强
云服务商托管方案:
- 适用场景:不想自己维护Redis基础设施
- 特点:简单易用,但成本较高
选择方案时需要考虑数据量、吞吐量、可用性要求、运维能力等因素。对于大多数中小规模应用,主从复制+哨兵已经足够;对于大规模应用或需要水平扩展的场景,应该选择Redis集群。
6. Redis性能优化与监控
6.1 Redis性能优化
Redis虽然性能很高,但在高并发或大数据量场景下,仍然需要进行优化。
6.1.1 内存优化
使用适当的数据类型:
- 小哈希使用ziplist编码(在redis.conf中配置
hash-max-ziplist-entries和hash-max-ziplist-value) - 使用整数而不是字符串存储数字
- 使用位图(bitmap)存储布尔值
- 小哈希使用ziplist编码(在redis.conf中配置
使用内存淘汰策略: 在redis.conf中配置:
maxmemory 4gb # 设置最大内存 maxmemory-policy allkeys-lru # 内存淘汰策略可选策略:
volatile-lru:从设置了过期时间的key中使用LRU算法淘汰allkeys-lru:从所有key中使用LRU算法淘汰volatile-random:从设置了过期时间的key中随机淘汰allkeys-random:从所有key中随机淘汰volatile-ttl:淘汰剩余生存时间最短的keynoeviction:不淘汰,返回错误(默认)
使用Hash分片: 对于大Hash,可以分成多个小Hash存储,减少单个key的大小。
设置合理的过期时间: 为缓存数据设置过期时间,避免无用数据长期占用内存。
6.1.2 命令优化
避免使用慢命令:
KEYS:使用SCAN代替FLUSHALL/FLUSHDB:谨慎使用MONITOR:仅用于调试- 大集合的
SMEMBERS:使用SSCAN
批量操作:
- 使用
MSET/MGET代替多个SET/GET - 使用
Pipeline减少网络往返 - 使用
Lua脚本组合多个操作
- 使用
合理使用事务:
- 避免事务中包含太多命令
- 使用
WATCH实现乐观锁
6.1.3 网络优化
使用连接池: 客户端应该使用连接池,避免频繁创建和关闭连接。
减少网络往返:
- 使用Pipeline批量发送命令
- 使用
MGET/MSET等批量命令 - 客户端缓存热点数据
选择合适的客户端: 选择性能好、功能全的客户端库,如Jedis(Java)、redis-py(Python)等。
6.1.4 持久化优化
RDB优化:
- 在低峰期执行
BGSAVE - 设置合理的
save配置 - 对于大实例,可以关闭RDB,只使用AOF
- 在低峰期执行
AOF优化:
- 使用
appendfsync everysec平衡性能和数据安全 - 定期检查AOF重写条件
- 在低峰期手动执行
BGREWRITEAOF
- 使用
避免同时使用RDB和AOF: 对于非常大的实例,可以只使用AOF,避免fork操作导致的内存问题。
6.2 Redis监控
监控是保证Redis稳定运行的重要手段,主要包括以下几个方面:
6.2.1 使用INFO命令
INFO命令可以获取Redis的各种状态信息,包括:
- Server:Redis服务器信息
- Clients:客户端连接信息
- Memory:内存使用情况
- Persistence:持久化信息
- Stats:一般统计信息
- Replication:主从复制信息
- CPU:CPU使用情况
- Cluster:集群信息
- Keyspace:数据库相关信息
示例:
redis-cli info memory # 只获取内存相关信息 redis-cli info stats # 只获取统计信息6.2.2 监控关键指标
- 内存使用:
used_memory:Redis分配的内存总量