Redis 新手教程:从零开始学习 Redis
1. Redis 简介:不仅仅是缓存
Redis (REmote DIctionary Server) 远不止一个简单的键值对 (key-value) 存储系统。它是一个开源的、内存中的数据结构存储,可以用作数据库、缓存和消息中间件。Redis 以其卓越的性能、丰富的数据结构和强大的功能而闻名,使其成为现代 Web 应用程序、实时分析、游戏排行榜、会话管理等场景的理想选择。
为什么选择 Redis?
- 速度极快: Redis 将所有数据存储在内存中,避免了磁盘 I/O 的开销,因此读写速度非常快,通常在微秒级别。
- 丰富的数据结构: Redis 不仅仅支持简单的字符串键值对,还提供了列表 (List)、集合 (Set)、有序集合 (Sorted Set)、哈希 (Hash) 和位图 (Bitmap) 等多种数据结构,可以满足各种不同的应用需求。
- 持久化: Redis 支持两种持久化方式:RDB (Redis Database) 快照和 AOF (Append Only File) 日志,可以将内存中的数据保存到磁盘,防止数据丢失。
- 发布/订阅 (Pub/Sub): Redis 内置了发布/订阅功能,可以实现消息的实时分发,用于构建聊天室、实时通知等应用。
- 事务: Redis 支持事务操作,可以将多个命令打包成一个原子操作,保证数据的一致性。
- Lua 脚本: Redis 允许使用 Lua 脚本执行复杂的逻辑,减少网络开销,提高性能。
- 高可用和分布式: Redis 支持主从复制、哨兵 (Sentinel) 和集群 (Cluster) 模式,可以实现高可用性和水平扩展。
- 丰富的客户端支持: Redis 有各种编程语言的客户端库,如 Python、Java、Node.js、PHP、Go 等,方便开发者使用。
2. 安装和配置 Redis
在开始使用 Redis 之前,我们需要先安装和配置它。
2.1. 在 Linux 上安装 (以 Ubuntu 为例)
“`bash
更新软件包列表
sudo apt update
安装 Redis
sudo apt install redis-server
启动 Redis 服务
sudo systemctl start redis-server
检查 Redis 服务状态
sudo systemctl status redis-server
设置 Redis 开机自启
sudo systemctl enable redis-server
“`
2.2. 在 macOS 上安装
“`bash
使用 Homebrew 安装
brew install redis
启动 Redis 服务
brew services start redis
停止 Redis 服务
brew services stop redis
“`
2.3. 在 Windows 上安装
- 下载 Redis: 访问 Redis 官方下载页面 (https://redis.io/download/) 或 GitHub 上的 Windows 版本 (https://github.com/microsoftarchive/redis/releases),下载最新版本的 Redis 压缩包。
- 解压 Redis: 将下载的压缩包解压到你想要安装 Redis 的目录 (例如
C:\Redis
)。 - 运行 Redis:
- 打开命令提示符 (CMD) 或 PowerShell。
- 切换到 Redis 解压目录 (例如
cd C:\Redis
)。 - 运行
redis-server.exe
启动 Redis 服务器。 - (可选) 可以使用
redis-cli.exe
启动 Redis 客户端,连接到服务器并执行命令。
- (推荐) 将 Redis 添加到系统环境变量: 为了方便使用,可以将 Redis 的路径添加到系统环境变量
PATH
中。这样就可以在任何目录下直接运行redis-server
和redis-cli
命令。
2.4. Redis 配置文件 (redis.conf)
Redis 的主要配置文件是 redis.conf
,它包含了各种配置选项。以下是一些常见的配置项:
bind
: 绑定的 IP 地址,默认是127.0.0.1
(只允许本地连接)。如果要允许远程连接,可以设置为0.0.0.0
或指定的 IP 地址。port
: Redis 服务器监听的端口,默认是6379
。requirepass
: 设置 Redis 访问密码 (可选,建议设置)。daemonize
: 是否以守护进程模式运行,默认是no
。设置为yes
后,Redis 将在后台运行。logfile
: 指定日志文件的路径。databases
: 设置数据库的数量,默认是 16 个。maxmemory
: 设置 Redis 可以使用的最大内存量 (可选)。maxmemory-policy
: 当内存达到最大限制时,Redis 如何处理新的写入操作的策略 (例如noeviction
、allkeys-lru
、volatile-lru
等)。appendonly
: 是否开启 AOF 持久化,默认是no
。appendfilename
: AOF 文件的名称。save
: 设置 RDB 快照的触发条件 (例如save 900 1
表示 900 秒内至少有 1 个键被修改就触发快照)。
修改完 redis.conf
后,需要重启 Redis 服务才能使配置生效。
3. Redis 数据类型和常用命令
Redis 支持多种数据类型,每种类型都有其独特的用途和操作命令。
3.1. 字符串 (String)
字符串是 Redis 最基本的数据类型,可以存储文本、数字或二进制数据。
常用命令:
SET key value
: 设置键值对。GET key
: 获取键对应的值。INCR key
: 将键的值递增 1 (如果值是数字)。DECR key
: 将键的值递减 1 (如果值是数字)。APPEND key value
: 将值追加到键的现有值后面。STRLEN key
: 获取键的值的长度。SETEX key seconds value
: 设置键值对,并指定过期时间 (秒)。SETNX key value
: 仅当键不存在时才设置键值对 (SET if Not eXists)。MSET key1 value1 key2 value2 ...
: 一次设置多个键值对MGET key1 key2 ...
: 一次获取多个键的值
示例:
SET name "Alice"
GET name # 输出: "Alice"
INCR age # 假设 age 不存在,则创建并设置为 1
INCR age # age 变为 2
SETEX session_id 3600 "user123" # 设置 session_id,过期时间为 1 小时
3.2. 列表 (List)
列表是一个有序的字符串集合,可以在列表的头部或尾部添加、删除元素。
常用命令:
LPUSH key value1 value2 ...
: 将一个或多个值插入到列表头部。RPUSH key value1 value2 ...
: 将一个或多个值插入到列表尾部。LPOP key
: 移除并返回列表的头部元素。RPOP key
: 移除并返回列表的尾部元素。LINDEX key index
: 获取列表指定索引位置的元素。LLEN key
: 获取列表的长度。LRANGE key start stop
: 获取列表指定范围内的元素 (包括 start 和 stop)。LREM key count value
: 从列表中移除指定数量的元素。LTRIM key start stop
: 对列表进行修剪,只保留指定范围内的元素。
示例:
LPUSH tasks "task1"
LPUSH tasks "task2"
RPUSH tasks "task3"
LRANGE tasks 0 -1 # 输出: ["task2", "task1", "task3"]
LPOP tasks # 输出: "task2"
3.3. 集合 (Set)
集合是一个无序的、不重复的字符串集合。
常用命令:
SADD key member1 member2 ...
: 向集合添加一个或多个成员。SREM key member1 member2 ...
: 从集合中移除一个或多个成员。SMEMBERS key
: 获取集合中的所有成员。SISMEMBER key member
: 判断成员是否在集合中。SCARD key
: 获取集合的成员数量。SINTER key1 key2 ...
: 获取多个集合的交集。SUNION key1 key2 ...
: 获取多个集合的并集。SDIFF key1 key2 ...
: 获取多个集合的差集。
示例:
SADD tags "programming"
SADD tags "python"
SADD tags "redis"
SMEMBERS tags # 输出: ["programming", "python", "redis"] (顺序可能不同)
SISMEMBER tags "java" # 输出: 0 (false)
3.4. 有序集合 (Sorted Set)
有序集合与集合类似,但每个成员都关联一个分数 (score),用于对成员进行排序。
常用命令:
ZADD key score1 member1 score2 member2 ...
: 向有序集合添加一个或多个成员,并指定分数。ZREM key member1 member2 ...
: 从有序集合中移除一个或多个成员。ZRANGE key start stop [WITHSCORES]
: 获取有序集合指定范围内的成员 (按分数从小到大排序)。ZREVRANGE key start stop [WITHSCORES]
: 获取有序集合指定范围内的成员 (按分数从大到小排序)。ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count]
: 获取有序集合指定分数范围内的成员。ZSCORE key member
: 获取成员的分数。ZCARD key
: 获取有序集合的成员数量。ZCOUNT key min max
: 计算有序集合指定分数范围内的成员数量。ZINCRBY key increment member
: 为成员的分数增加指定的值。
示例:
ZADD leaderboard 100 "Alice"
ZADD leaderboard 90 "Bob"
ZADD leaderboard 80 "Charlie"
ZRANGE leaderboard 0 -1 WITHSCORES # 输出: [["Charlie", "80"], ["Bob", "90"], ["Alice", "100"]]
ZREVRANGE leaderboard 0 1 # 输出: ["Alice", "Bob"]
3.5. 哈希 (Hash)
哈希是一个键值对集合,其中每个键都映射到一个值。
常用命令:
HSET key field value
: 设置哈希中指定字段的值。HGET key field
: 获取哈希中指定字段的值。HMSET key field1 value1 field2 value2 ...
: 同时设置哈希中多个字段的值。HMGET key field1 field2 ...
: 同时获取哈希中多个字段的值。HGETALL key
: 获取哈希中所有字段和值。HKEYS key
: 获取哈希中所有字段。HVALS key
: 获取哈希中所有值。HDEL key field1 field2 ...
: 删除哈希中一个或多个字段。HEXISTS key field
: 判断哈希中是否存在指定字段。HLEN key
: 获取哈希中字段的数量。
示例:
HSET user:1 name "Alice"
HSET user:1 age 30
HGET user:1 name # 输出: "Alice"
HMGET user:1 name age # 输出: ["Alice", "30"]
HGETALL user:1 # 输出: ["name", "Alice", "age", "30"]
3.6 位图(Bitmap)
位图是由0和1组成的二进制位数组. 可以用来表示用户的某些状态,比如是否签到,是否是会员等.
常用命令
* SETBIT key offset value
: 对 key 所储存的字符串值,设置或清除指定偏移量上的位(bit)。
* GETBIT key offset
: 对 key 所储存的字符串值,获取指定偏移量上的位(bit)。
* BITCOUNT key [start end]
: 计算给定字符串中,被设置为 1 的比特位的数量。
* BITOP operation destkey key [key ...]
: 对一个或多个保存二进制位的字符串 key 进行位元操作,并将结果保存到 destkey 上。
3.7 HyperLogLog
HyperLogLog 是一种概率数据结构,用于估算集合中唯一元素的数量.
常用命令:
* PFADD key element [element ...]
: 添加指定元素到 HyperLogLog 中。
* PFCOUNT key [key ...]
: 返回给定 HyperLogLog 的基数估算值。
* PFMERGE destkey sourcekey [sourcekey ...]
: 将多个 HyperLogLog 合并为一个 HyperLogLog。
4. Redis 客户端
Redis 有多种客户端可以使用,包括命令行客户端和各种编程语言的客户端库。
4.1. 命令行客户端 (redis-cli)
redis-cli
是 Redis 自带的命令行客户端,可以方便地连接到 Redis 服务器并执行命令。
连接到 Redis 服务器:
“`bash
连接到本地默认端口的 Redis 服务器
redis-cli
连接到指定主机和端口的 Redis 服务器
redis-cli -h
连接到需要密码验证的 Redis 服务器
redis-cli -h
在 redis-cli
中执行命令:
“`
执行 PING 命令,检查服务器是否正常运行
PING
执行 SET 命令
SET mykey “Hello Redis”
执行 GET 命令
GET mykey
“`
4.2. Python 客户端 (redis-py)
redis-py
是 Python 中最常用的 Redis 客户端库。
安装 redis-py
:
bash
pip install redis
使用 redis-py
连接到 Redis 服务器并执行命令:
“`python
import redis
连接到本地默认端口的 Redis 服务器
r = redis.Redis(host=’localhost’, port=6379, db=0)
连接到需要密码验证的 Redis 服务器
r = redis.Redis(host=’localhost’, port=6379, db=0, password=’your_password’)
执行 SET 命令
r.set(‘mykey’, ‘Hello Redis’)
执行 GET 命令
value = r.get(‘mykey’)
print(value) # 输出: b’Hello Redis’ (注意:返回的是字节串)
执行其他命令
r.lpush(‘mylist’, ‘item1’)
r.lpush(‘mylist’, ‘item2’)
mylist = r.lrange(‘mylist’, 0, -1)
print(mylist) # 输出: [b’item2′, b’item1′]
“`
5. Redis 持久化
Redis 支持两种持久化方式:RDB 和 AOF。
5.1. RDB (Redis Database) 快照
RDB 是 Redis 默认的持久化方式,它会在指定的时间间隔内将内存中的数据快照保存到磁盘上的一个二进制文件中 (默认文件名是 dump.rdb
)。
RDB 的优点:
- 性能高: RDB 是一个紧凑的二进制文件,非常适合用于备份和灾难恢复。
- 恢复速度快: 在 Redis 重启时,可以直接加载 RDB 文件来恢复数据,速度比 AOF 快。
RDB 的缺点:
- 数据丢失: 如果 Redis 在两次快照之间发生故障,可能会丢失最后一次快照之后的数据。
- Fork 开销: 在生成 RDB 快照时,Redis 需要 fork 一个子进程来执行写操作,如果数据集很大,可能会导致 fork 操作耗时较长。
RDB 配置 (redis.conf):
“`
设置 RDB 快照的触发条件
save 900 1 # 900 秒内至少有 1 个键被修改
save 300 10 # 300 秒内至少有 10 个键被修改
save 60 10000 # 60 秒内至少有 10000 个键被修改
设置 RDB 文件的名称
dbfilename dump.rdb
设置 RDB 文件的保存目录
dir ./
“`
5.2. AOF (Append Only File) 日志
AOF 持久化会将 Redis 执行的每个写命令追加到 AOF 文件 (默认文件名是 appendonly.aof
) 的末尾。在 Redis 重启时,会重新执行 AOF 文件中的命令来恢复数据。
AOF 的优点:
- 数据更安全: AOF 可以配置不同的同步策略 (例如
always
、everysec
、no
),可以最大程度地减少数据丢失的风险。 - 可读性好: AOF 文件是一个纯文本文件,可以方便地查看和编辑。
AOF 的缺点:
- 文件大小: AOF 文件通常比 RDB 文件大,因为 AOF 记录了每个写命令。
- 恢复速度: 在 Redis 重启时,需要重新执行 AOF 文件中的所有命令,恢复速度比 RDB 慢。
- 性能: AOF 的性能比 RDB 略低,因为需要频繁地进行磁盘 I/O 操作。
AOF 配置 (redis.conf):
“`
开启 AOF 持久化
appendonly yes
设置 AOF 文件的名称
appendfilename “appendonly.aof”
设置 AOF 同步策略
appendfsync always # 每个写命令都立即同步到磁盘 (最安全,性能最差)
appendfsync everysec # 每秒同步一次 (默认值,兼顾安全性和性能)
appendfsync no # 不主动同步,由操作系统决定何时同步 (性能最好,数据丢失风险最大)
设置 AOF 重写 (rewrite) 的触发条件
auto-aof-rewrite-percentage 100 # 当 AOF 文件大小比上次重写后的大小增长了 100% 时触发重写
auto-aof-rewrite-min-size 64mb # 当 AOF 文件大小至少达到 64MB 时才触发重写
“`
AOF 重写:
由于 AOF 文件会不断追加写命令,文件大小会越来越大。为了减小 AOF 文件的大小,Redis 提供了 AOF 重写机制。AOF 重写会创建一个新的 AOF 文件,其中包含重建当前数据集所需的最小命令集。
5.3. RDB 和 AOF 的选择
- 如果可以容忍一定程度的数据丢失,并且更关注性能,可以选择 RDB。
- 如果对数据安全性要求很高,不能容忍数据丢失,可以选择 AOF。
- 也可以同时开启 RDB 和 AOF,这样可以兼顾性能和安全性。 在 Redis 重启时,会优先使用 AOF 文件来恢复数据 (因为 AOF 文件通常包含更完整的数据)。
6. Redis 发布/订阅 (Pub/Sub)
Redis 的发布/订阅功能允许客户端订阅一个或多个频道 (channel),当有发布者向这些频道发布消息时,所有订阅者都会收到消息。
常用命令:
SUBSCRIBE channel1 channel2 ...
: 订阅一个或多个频道。PUBLISH channel message
: 向指定频道发布消息。UNSUBSCRIBE [channel1 channel2 ...]
: 取消订阅一个或多个频道 (如果不指定频道,则取消所有订阅)。PSUBSCRIBE pattern1 pattern2 ...
: 使用模式匹配订阅频道 (例如PSUBSCRIBE news.*
可以订阅所有以news.
开头的频道)。PUNSUBSCRIBE [pattern1 pattern2 ...]
: 取消使用模式匹配的订阅。
示例:
客户端 1 (订阅者):
redis-cli
SUBSCRIBE news.sports
客户端 2 (发布者):
redis-cli
PUBLISH news.sports "Real Madrid wins the Champions League!"
客户端 1 (订阅者) 将收到消息:
1) "message"
2) "news.sports"
3) "Real Madrid wins the Champions League!"
7. Redis 事务
Redis 事务可以将多个命令打包成一个原子操作,保证这些命令要么全部执行成功,要么全部不执行。
常用命令:
MULTI
: 开启一个事务。EXEC
: 执行事务中的所有命令。DISCARD
: 取消事务,放弃执行事务中的所有命令。WATCH key1 key2 ...
: 监视一个或多个键,如果在事务执行之前这些键被修改,则事务会被打断。UNWATCH
: 取消所有监视。
示例:
MULTI
SET key1 "value1"
INCR key2
EXEC
乐观锁 (Optimistic Locking):
Redis 使用 WATCH
命令实现乐观锁机制。在执行事务之前,可以先使用 WATCH
命令监视一个或多个键。如果在事务执行之前 (即 EXEC
命令之前),这些键被其他客户端修改,则事务会被打断,EXEC
命令会返回 nil
。
示例:
WATCH mykey
val = GET mykey
val = val + 1 # 假设 val 是数字
MULTI
SET mykey val
EXEC
如果 mykey
在 WATCH
和 EXEC
之间被其他客户端修改,则 EXEC
会返回 nil
,事务不会执行。
8. Redis Lua 脚本
Redis 允许使用 Lua 脚本执行复杂的逻辑,减少网络开销,提高性能。
常用命令:
EVAL script numkeys key [key ...] arg [arg ...]
: 执行 Lua 脚本。script
:Lua 脚本代码。numkeys
:脚本中使用的键的数量。key [key ...]
:脚本中使用的键。arg [arg ...]
:传递给脚本的参数。
EVALSHA sha1 numkeys key [key ...] arg [arg ...]
: 使用脚本的 SHA1 校验和执行 Lua 脚本 (需要先使用SCRIPT LOAD
命令加载脚本)。SCRIPT LOAD script
: 将 Lua 脚本加载到 Redis 服务器,返回脚本的 SHA1 校验和。SCRIPT EXISTS sha1 [sha1 ...]
: 检查一个或多个脚本的 SHA1 校验和是否存在。SCRIPT FLUSH
: 清除所有已加载的 Lua 脚本。SCRIPT KILL
: 杀死当前正在运行的 Lua 脚本。
示例:
lua
-- Lua 脚本示例 (increment.lua)
local key = KEYS[1]
local increment = tonumber(ARGV[1])
local current = redis.call('GET', key)
if current then
current = tonumber(current)
else
current = 0
end
redis.call('SET', key, current + increment)
return current + increment
在 redis-cli
中执行 Lua 脚本:
EVAL "$(cat increment.lua)" 1 mykey 10
在 Python 中执行 Lua 脚本:
“`python
import redis
r = redis.Redis()
加载 Lua 脚本
with open(‘increment.lua’, ‘r’) as f:
script = f.read()
sha1 = r.script_load(script)
执行 Lua 脚本
result = r.evalsha(sha1, 1, ‘mykey’, 10)
print(result)
“`
9. Redis 高可用和分布式
Redis 提供了多种方式来实现高可用性和水平扩展。
9.1 主从复制 (Master-Slave Replication)
Redis 主从复制允许将一个 Redis 服务器 (master) 的数据复制到多个 Redis 服务器 (slave)。主服务器负责处理写请求,从服务器负责处理读请求,从而实现读写分离,提高性能。
配置主从复制 (redis.conf):
- Master (不需要特殊配置): 默认情况下,Redis 服务器就是主服务器。
- Slave:
replicaof <master_host> <master_port> # 或者 slaveof <master_host> <master_port>
masterauth <master_password> # 如果 master 设置了密码
修改后需要重启 Redis 服务器。
9.2. 哨兵 (Sentinel)
Redis Sentinel 是一个分布式系统,用于监控 Redis 主服务器和从服务器的健康状态,并在主服务器发生故障时自动进行故障转移 (failover)。
Sentinel 的主要功能:
- 监控 (Monitoring): Sentinel 会持续检查 Redis 服务器是否正常运行。
- 通知 (Notification): Sentinel 可以通过 API 或发布/订阅的方式通知管理员或其他应用程序 Redis 服务器的状态变化。
- 自动故障转移 (Automatic failover): 当 Sentinel 检测到主服务器发生故障时,会自动将一个从服务器提升为新的主服务器,并更新其他从服务器的配置。
- 配置提供者 (Configuration provider): 客户端可以连接到 Sentinel 来获取当前 Redis 集群的主服务器地址。
配置 Sentinel (sentinel.conf):
“`
监听的端口
port 26379
监控的主服务器 (mymaster 是自定义的名称)
sentinel monitor mymaster 127.0.0.1 6379 2
设置 Sentinel 的 down-after-milliseconds 选项 (单位:毫秒)
如果 Redis 服务器在这个时间内没有响应,Sentinel 就会认为它已经下线
sentinel down-after-milliseconds mymaster 30000
设置 Sentinel 的 failover-timeout 选项 (单位:毫秒)
如果在故障转移过程中超过这个时间,Sentinel 就会认为故障转移失败
sentinel failover-timeout mymaster 180000
设置 Sentinel 的 parallel-syncs 选项
指定在故障转移后可以同时同步数据的从服务器数量
sentinel parallel-syncs mymaster 1
如果 master 设置了密码
sentinel auth-pass mymaster
“`
启动 Sentinel:
bash
redis-sentinel /path/to/sentinel.conf
9.3. 集群 (Cluster)
Redis Cluster 是 Redis 官方提供的分布式解决方案,可以将数据自动分片 (sharding) 到多个 Redis 节点上,实现水平扩展和高可用性。
Redis Cluster 的主要特点:
- 数据分片: Redis Cluster 将数据分成多个槽 (slot),每个槽可以存储一部分数据。每个 Redis 节点负责管理一部分槽。
- 自动故障转移: 当一个主节点发生故障时,Redis Cluster 会自动将一个从节点提升为新的主节点。
- 客户端路由: 客户端可以连接到集群中的任何一个节点,Redis Cluster 会自动将请求路由到正确的节点。
- 在线扩容和缩容: 可以在不停止服务的情况下添加或删除节点。
配置 Redis Cluster:
创建至少6个redis实例(3主3从, 建议奇数个master),并修改如下配置:
cluster-enabled yes
cluster-config-file nodes.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-replicas 1
表示每个主节点配置一个从节点。
连接 Redis Cluster:
bash
redis-cli -c -h <host> -p <port>
-c
选项表示启用集群模式。
10. 总结
本教程介绍了 Redis 的基本概念、安装配置、数据类型、常用命令、持久化、发布/订阅、事务、Lua 脚本以及高可用和分布式解决方案。通过本教程,你应该已经对 Redis 有了一个全面的了解,并可以开始在你的项目中使用 Redis 了。
要深入学习 Redis,建议阅读 Redis 官方文档 (https://redis.io/documentation),并参考一些优秀的 Redis 书籍和博客文章。
希望这篇教程对你有所帮助!