针对java程序员来说,Redis在项目中使用非常广泛,并且在面试中也几乎是必问的知识点,重要性自然不言而喻了,自然更需要总结了,每次跳槽面试必备,复习更方便,提高复习的效率!
目录
9.Redis数据淘汰策略(共有8中,其中两种是4.0版本后新增)
[14.Redis Lua脚本](#14.Redis Lua脚本)
[21.Redis哈希槽(Hash Slot)](#21.Redis哈希槽(Hash Slot))
1.Redis的定义及简介
Redis是一个开源的内存数据库,也被称为数据结构服务器。它支持多种数据结构,如字符串、哈希表、列表、集合、有序集合等。Redis以其高性能、灵活性和丰富的功能而受到广泛欢迎,常用于缓存、会话存储、实时分析、消息队列等场景。
特性 | 描述 |
---|---|
数据类型 | 支持字符串、列表、集合、有序集合、散列等数据类型 |
性能 | 高性能,单线程模型,通过优化算法实现高吞吐量 |
数据存储 | 内存存储,可选数据持久化 |
应用场景 | 缓存、消息队列、排行榜、实时分析等 |
架构 | 支持主从复制、哨兵系统、集群等 |
语言支持 | 支持多种语言的客户端,如C、Java、Python、Go等 |
数据安全 | 支持密码保护、ACL等安全机制 |
社区和文档 | 活跃的社区支持,丰富的文档和教程 |
2.Redis数据类型
数据类型 | 描述 | 示例 |
---|---|---|
字符串 | 简单的键值对存储,常用于缓存功能 | SET key value - 设置键为"key"的值为"value" |
列表 | 字符串序列,支持原子推入和弹出操作 | LPUSH list_key value1 value2 - 将值"value1"和"value2"推入名为"list_key"的列表 |
集合 | 无序集合,自动去重 | SADD set_key value1 value2 - 将"value1"和"value2"添加到名为"set_key"的集合 |
有序集合 | 有序集合,元素有唯一的分数 | ZADD sorted_set_key 1 value1 2 value2 - 将"value1"和"value2"添加到有序集合"sorted_set_key",分别赋予分数1和2 |
哈希 | 键值对集合,适合存储对象 | HSET hash_key field1 value1 field2 value2 - 设置哈希"hash_key"中"field1"的值为"value1","field2"的值为"value2" |
位图 | 字符串类型的特殊用途,常用于状态存储 | SETBIT bitmap_key offset value - 在位图"bitmap_key"的"offset"位置设置位的值 |
地理空间 | 存储地理位置信息,支持地理查询 | GEADD geoset_key longitude latitude member - 在地理空间集合"geoset_key"中添加成员"member"的经纬度 |
使用Redis的列表数据类型可以有效地存储和管理用户会话。方便原子操作;列表的两端都可以进行原子的推入(LPUSH
)和弹出(RPUSH
)操作,这使得它们非常适合用来存储用户会话,其中会话可以按照时间顺序排列。
示例:
假设我们有一个用户会话系统,每当用户登录时,我们将其会话标识符(session ID)存储在一个列表中。我们可以使用LPUSH
将新的会话ID推入到列表的头部。
LPUSH user_sessions_session_list session_id_1234
当用户退出时,我们可以从列表中移除对应的会话ID。如果需要从列表头部移除,可以使用LPOP
命令:
LPOP user_sessions_session_list
如果需要从列表尾部移除,可以使用RPOP
命令:
RPOP user_sessions_session_list
此外,可以使用LRANGE
命令获取一定范围内的会话ID列表,例如获取最近登录的10个会话:
LRANGE user_sessions_session_list 0 9
这个命令将返回列表user_sessions_session_list
中的前10个会话ID。
使用列表存储会话的好处是可以轻松地实现会话的过期和清理。例如,可以使用LTRIM
命令来限制列表的大小,从而实现旧会话的自动清理:
LTRIM user_sessions_session_list 0 999
这个命令将保留列表中的最后1000个会话ID,自动删除更早的会话。
3.Redis持久化机制
持久化方式 | 描述 | 特点 |
---|---|---|
RDB | 将当前Redis实例的状态生成快照并保存到磁盘 | 适合做备份和灾难恢复 |
AOF | 记录服务器接收到的每一个写操作命令,并将这些命令追加到文件的末尾 | 适合做数据恢复,提供了不同的同步选项 |
混合持久化 | RDB和AOF的组合使用 | 结合了两者的优点,提供了更灵活的数据恢复方式 |
示例:配置RDB持久化策略。
配置RDB持久化,900秒内至少1个键被修改,则发起快照保存
SAVE 900 1
配置RDB持久化,300秒内至少10个键被修改,则发起快照保存
SAVE 300 10
配置RDB持久化,60秒内至少10000个键被修改,则发起快照保存
SAVE 60 10000
4.Redis事务
命令 | 描述 | 示例 |
---|---|---|
MULTI |
开始一个事务,后续命令将入队但不执行 | MULTI - 开始事务 |
EXEC |
执行所有事务中的命令 | EXEC - 提交事务 |
DISCARD |
取消事务,清空事务队列 | DISCARD - 取消事务 |
WATCH |
监视一个或多个键,如果在执行事务期间这些键被其他命令改动,则事务不执行 | WATCH key1 key2 - 监视"key1"和"key2" |
MULTI ... COMMANDS ... EXEC |
批量执行命令,如果在这个过程中发生错误,则不会执行任何命令 | MULTI <br> SET key1 value1 <br> SET key2 value2 <br> EXEC - 原子地设置两个键的值 |
示例:使用事务确保两个键同时更新。
bash
MULTI
SET key1 "value1"
SET key2 "value2"
EXEC
5.Redis发布/订阅
命令 | 描述 | 示例 |
---|---|---|
PUBLISH |
将消息发送到指定的频道 | PUBLISH channel message - 向频道"channel"发送消息"message" |
SUBSCRIBE |
订阅一个或多个频道,接收这些频道的消息 | SUBSCRIBE channel1 channel2 - 订阅"channel1"和"channel2" |
PSUBSCRIBE |
订阅一个或多个符合模式的频道 | PSUBSCRIBE pattern1 pattern2 - 订阅符合"pattern1"和"pattern2"模式的频道 |
UNSUBSCRIBE |
取消订阅一个或多个频道 | UNSUBSCRIBE channel1 channel2 - 取消订阅"channel1"和"channel2" |
PUNSUBSCRIBE |
取消订阅一个或多个符合模式的频道 | PUNSUBSCRIBE pattern1 pattern2 - 取消订阅符合"pattern1"和"pattern2"模式的频道 |
示例:使用发布/订阅机制实现消息广播。
bash
# 客户端1
SUBSCRIBE news
# 客户端2
PUBLISH news "Hello!"
# 客户端1将接收到"Hello!"消息
6.Redis主从复制
特性 | 描述 | 示例 |
---|---|---|
主服务器 | 存储数据,处理写操作 | redis-server - 启动主服务器 |
从服务器 | 读取数据,可以有多个,用于负载均衡和故障转移 | redis-server --slaveof master_host master_port - 启动从服务器并指定主服务器的地址和端口 |
数据同步 | 从服务器通过复制主服务器的数据来同步 | 使用SLAVEOF 命令或在配置文件中设置主服务器信息 |
只读模式 | 从服务器默认为只读模式,可以接受配置修改为读写 | CONFIG SET slave-read-only yes/no - 设置从服务器的只读模式 |
自动故障转移 | 哨兵系统可以监控主服务器状态,自动将一个从服务器提升为主服务器 | 使用哨兵系统(Sentinel)实现自动故障转移 |
示例:配置主从复制。
在从服务器上设置主服务器信息
SLAVEOF master_host 6379
7.Redis哨兵系统(Sentinel)
特性 | 描述 | 示例 |
---|---|---|
监控 | 持续监控主服务器和从服务器的状态 | Sentinel 通过定期发送 PING 命令来检测服务器状态 |
自动故障转移 | 检测到主服务器故障时自动进行故障转移 | Sentinel 会根据投票数决定是否进行故障转移 |
通知 | 故障转移发生时,通知系统其他部分 | 通过脚本或命令行通知系统其他部分主服务器已经变更 |
数据迁移 | 将旧的主服务器数据迁移到新的主服务器上 | Sentinel 会将旧主服务器的数据同步到新的主服务器 |
高可用 | 提供高可用性解决方案,减少系统因单点故障导致的不可用时间 | 使用 Sentinel 可以避免主服务器故障导致的服务中断 |
示例:启动 Sentinel 监控主服务器。
redis-sentinel /path/to/sentinel.conf
配置文件 sentinel.conf
中会包含如下配置:
bash
# 配置监控的主服务器信息
sentinel monitor mymaster 127.0.0.1 6379 2
# 配置故障转移所需的最小同意数
sentinel down-after-milliseconds mymaster 30000
# 配置故障转移时执行的命令
sentinel failover-timeout mymaster 900000
8.Redis集群
特性 | 描述 | 示例 |
---|---|---|
数据分片 | 数据被分割成多个部分,每个部分存储在不同的节点上 | 使用 CLUSTER MEET 创建集群节点 |
高可用 | 集群中的每个主节点都可以处理写操作,且具有从节点用于故障转移 | 使用 SLAVEOF 配置从节点 |
数据迁移 | 可以在不停止服务的情况下,将数据从一个节点迁移到另一个节点 | 使用 CLUSTER SET-SLOT 进行数据迁移 |
数据一致性 | 集群使用复制和分布式算法来保持数据一致性 | 使用 CLUSTER NODES 查看集群状态 |
数据持久性 | 支持多种数据持久化选项,如RDB和AOF | 配置持久化选项以满足数据持久性需求 |
读写分离 | 可以根据负载将读操作分配给从节点 | 使用 MOVED 错误处理客户端的读写请求 |
示例:使用Redis集群进行数据分片。
bash
# 初始化集群
redis-cli --cluster create host1:port1 host2:port2 host3:port3 --cluster-replicas 1
# 查看集群信息
redis-cli --cluster nodes
9.Redis数据淘汰策略(共有8中,其中两种是4.0版本后新增)
策略名称 | 描述 | 适用场景 |
---|---|---|
noeviction | 不删除任何数据,如果内存满了,写操作会被阻塞 | 当数据集大小相对稳定,且内存足够大时 |
allkeys-lru(Least Recently Used) | 根据最近最少使用算法删除键,无论数据类型如何 | 当需要从所有数据类型中淘汰数据时 |
allkeys-lfu(Least Frequently Used) 4.0版本后新增 | 根据键的使用频率和最近一次使用该键的时间进行淘汰。 | 适用于读多写少,且希望淘汰访问频率较低的键的场景 |
allkeys-random | 从所有键中随机删除一个键 | 当需要随机删除数据以回收内存时 |
volatile-lru | 从设置了过期时间的键中,根据最近最少使用算法删除键 | 当需要从设置了过期时间的键中回收内存时 |
volatile-lfu (4.0版本后新增) | 根据键的使用频率和最近一次使用该键的时间进行淘汰。 | 适用于读多写少,且希望淘汰访问频率较低的键的场景 |
volatile-random | 从设置了过期时间的键中随机删除一个键 | 当需要随机删除设置了过期时间的键以回收内存时 |
volatile-ttl | 删除即将过期的键 | 当需要根据键的剩余生存时间来淘汰数据时 |
示例:配置Redis使用LRU数据淘汰策略。
CONFIG SET maxmemory-policy allkeys-lru
10.Redis连接管理
命令 | 描述 | 示例 |
---|---|---|
CLIENT LIST |
列出所有客户端的连接信息 | CLIENT LIST - 显示所有客户端的连接信息 |
CLIENT KILL |
断开一个或多个客户端的连接 | CLIENT KILL ip:port - 断开指定IP和端口的客户端连接 |
CLIENT GETNAME |
获取客户端的名称 | CLIENT GETNAME - 获取当前客户端的名称 |
CLIENT SETNAME |
设置客户端的名称 | CLIENT SETNAME myname - 将当前客户端名称设置为"myname" |
CONFIG GET maxclients |
获取当前允许的最大客户端连接数 | CONFIG GET maxclients - 获取最大客户端连接数配置 |
CONFIG SET maxclients |
设置允许的最大客户端连接数 | CONFIG SET maxclients 5000 - 设置最大客户端连接数为5000 |
示例:查看当前Redis服务器的所有客户端连接。
CLIENT LIST
11.Redis性能监控
命令 | 描述 | 示例 |
---|---|---|
INFO |
提供关于Redis服务器的各种统计信息和指标 | INFO - 获取Redis服务器的详细信息 |
MONITOR |
监视服务器接收到的命令以及服务器发出的命令 | MONITOR - 实时显示所有传输给服务器的命令 |
SLOWLOG |
记录慢查询,可以设置慢查询的时间阈值 | SLOWLOG GET 10 - 获取最后10条慢查询记录 |
CLIENT PAUSE |
挂起所有客户端的命令处理,用于服务器维护 | CLIENT PAUSE 1000 - 挂起客户端1秒 |
LASTSAVE |
获取最近一次RDB持久化的时间 | LASTSAVE - 获取最后一次成功创建快照的时间 |
ROLE |
显示当前Redis实例的角色(主机或从机) | ROLE - 显示当前Redis实例的角色 |
COMMAND STATS |
获取Redis命令的统计信息,如执行次数等(5.0.0以上版本) | COMMAND STATS - 获取Redis命令的统计信息 |
示例:获取Redis服务器的统计信息。
INFO
12.Redis安全特性
命令 | 描述 | 示例 |
---|---|---|
CONFIG SET requirepass |
设置密码保护,要求客户端在连接时提供密码 | CONFIG SET requirepass mypassword - 设置密码为"mypassword" |
AUTH |
使用密码认证连接 | AUTH mypassword - 使用密码"mypassword"进行认证 |
COMMAND |
列出所有可用的Redis命令 | COMMAND - 列出所有Redis命令 |
COMMAND INFO |
获取关于特定Redis命令的信息 | COMMAND INFO GET SET - 获取"GET"和"SET"命令的信息 |
ACL SET |
在Redis 6.0及以上版本中,设置更细粒度的访问控制列表 | ACL SET myuser +@all >mykey - 创建用户并设置权限 |
ACL LIST |
列出所有用户的ACL规则 | ACL LIST - 列出所有用户的ACL规则 |
ACL WHOAMI |
显示当前客户端使用的用户名 | ACL WHOAMI - 显示当前连接的用户名称 |
ACL LOG |
查看ACL相关操作的日志 | ACL LOG - 查看ACL日志 |
示例:设置Redis服务器的密码。
CONFIG SET requirepass mypassword
13.Redis命令行工具(CLI)
命令 | 描述 | 示例 |
---|---|---|
redis-cli |
启动Redis命令行客户端 | redis-cli - 启动Redis命令行客户端 |
-h |
指定Redis服务器的主机名 | redis-cli -h myhost - 连接到名为"myhost"的Redis服务器 |
-p |
指定Redis服务器的端口 | redis-cli -p 6379 - 使用默认端口6379连接Redis服务器 |
-a |
提供连接密码 | redis-cli -a mypassword - 使用密码连接Redis服务器 |
--scan |
迭代数据库中的键,用于代替KEYS 命令 |
redis-cli --scan --pattern '*' - 扫描所有键 |
INCR |
增加键的值,如果键不存在则开始于1 | INCR mykey - 如果"mykey"不存在,将其值设为1 |
DECR |
减少键的值,如果键不存在则开始于-1 | DECR mykey - 如果"mykey"不存在,将其值设为-1 |
APPEND |
向键的值追加字符串 | APPEND mykey "message" - 向"mykey"的值追加"message" |
BITCOUNT |
计算字符串中,二进制位为1的个数 | BITCOUNT mykey - 计算"mykey"中二进制位为1的个数 |
示例:使用密码连接到Redis服务器。
redis-cli -h localhost -p 6379 -a mypassword
14.Redis Lua脚本
命令 | 描述 | 示例 |
---|---|---|
EVAL |
执行Lua脚本 | EVAL "return redis.call('SET', KEYS[1], ARGV[1])" 1 key1 value1 - 使用Lua脚本设置键值对 |
EVALSHA |
执行保存在Redis中的Lua脚本的SHA1摘要 | EVALSHA sha1_hash - 执行已保存的Lua脚本 |
SCRIPT EXISTS |
检查指定的Lua脚本是否存在 | SCRIPT EXISTS sha1_hash1 sha1_hash2 - 检查两个Lua脚本是否已存在 |
SCRIPT FLUSH |
移除所有已保存的Lua脚本 | SCRIPT FLUSH - 清除所有已保存的Lua脚本 |
SCRIPT KILL |
杀死当前正在运行的Lua脚本 | SCRIPT KILL - 强制停止当前运行的Lua脚本 |
SCRIPT LOAD |
将Lua脚本加载到Redis服务器但不执行它 | SCRIPT LOAD "return redis.call('SET', KEYS[1], ARGV[1])" - 加载Lua脚本但不执行 |
redis-cli --eval |
从命令行执行Lua脚本 | redis-cli --eval myscript.lua 1 key1 value1 - 执行名为myscript.lua的Lua脚本 |
示例:使用Lua脚本原子地设置两个键的值。
Lua
EVAL "redis.call('SET', KEYS[1], ARGV[1]); redis.call('SET', KEYS[2], ARGV[2]); return 'OK'" 2 key1 value1 key2 value2
15.Redis内存管理
命令 | 描述 | 示例 |
---|---|---|
MEMORY USAGE |
显示分配给键的内存使用量 | MEMORY USAGE mykey - 显示键"mykey"的内存使用量 |
MEMORY STATS |
提供关于内存使用情况的统计信息 | MEMORY STATS - 显示内存使用情况的统计信息 |
MEMORY PURGE |
减少内存占用,但不释放内存 | MEMORY PURGE - 尝试通过回收缓存来减少内存占用 |
MEMORY ALLOC |
显示Redis分配器的当前内存分配量 | MEMORY ALLOC - 显示当前内存分配量 |
MEMORY FREE |
显示Redis分配器的当前内存剩余量 | MEMORY FREE - 显示当前内存剩余量 |
CONFIG SET maxmemory |
设置最大内存使用量 | CONFIG SET maxmemory 100mb - 设置最大内存使用量为100MB |
CONFIG SET maxmemory-policy |
设置内存使用达到上限时的淘汰策略 | CONFIG SET maxmemory-policy allkeys-lru - 设置淘汰策略为LRU |
示例:查看键"mykey"的内存使用量。
MEMORY USAGE mykey
16.Redis超时与限制
命令 | 描述 | 示例 |
---|---|---|
CONFIG GET timeout |
获取当前的超时设置 | CONFIG GET timeout - 获取超时设置 |
CONFIG SET timeout |
设置超时时间,单位为秒 | CONFIG SET timeout 30 - 设置超时时间为30秒 |
CONFIG GET maxclients |
获取当前允许的最大客户端连接数 | CONFIG GET maxclients - 获取最大客户端连接数 |
CONFIG SET maxclients |
设置允许的最大客户端连接数 | CONFIG SET maxclients 1000 - 设置最大客户端连接数为1000 |
CONFIG GET maxmemory-samples |
获取用于检查键删除的样本数量 | CONFIG GET maxmemory-samples - 获取键删除样本数量 |
CONFIG SET maxmemory-samples |
设置用于检查键删除的样本数量 | CONFIG SET maxmemory-samples 5 - 设置键删除样本数量为5 |
COMMAND |
查看所有命令的详细信息,包括时间复杂度 | COMMAND - 查看所有命令的详细信息 |
COMMAND INFO |
查看指定命令的详细信息 | COMMAND INFO GET SET - 查看"GET"和"SET"命令的详细信息 |
示例:设置客户端超时时间。
CONFIG SET timeout 60
17.Redis管道(Pipelining)
命令 | 描述 | 示例 |
---|---|---|
PIPELINE |
表示命令将被送入管道,而不是立即执行 | redis-cli --pipeline - 使用管道执行多个命令 |
MULTI |
开始事务,后续命令将入队但不执行 | MULTI - 开始事务 |
EXEC |
执行所有事务中的命令 | EXEC - 提交事务 |
命令队列 | 将多个命令一次性发送到服务器,减少往返次数 | SET key1 value1 <br> SET key2 value2 <br> ... - 队列中的命令 |
DISCARD |
取消事务,清空事务队列 | DISCARD - 取消事务 |
TELNET |
用于测试管道功能,发送一系列命令到服务器 | redis-cli --pipe 10000 - 发送10000个命令到服务器 |
示例:使用管道执行多个命令。
redis-cli --pipe
SET key1 value1
SET key2 value2
END
18.Redis排序与排名
命令 | 描述 | 示例 |
---|---|---|
SORT |
对列表、集合或有序集合进行排序 | SORT mylist BY mylist LIMIT 0 10 ASC - 对列表"mylist"进行升序排序并获取前10个元素 |
BY |
指定排序的键或模式 | BY pattern - 根据模式排序 |
GET |
排序后获取其他键的值 | GET another_key * - 排序后获取"another_key"的值 |
ASC / DESC |
指定排序的方向,升序或降序 | ASC - 升序,DESC - 降序 |
LIMIT |
限制返回的元素数量 | LIMIT offset count - 从偏移量开始获取特定数量的元素 |
STORE |
将排序后的结果存储到另一个键 | STORE sorted_list - 将排序结果存储到"sorted_list" |
ZREVRANGE |
获取有序集合中分数从高到低的元素 | ZREVRANGE myzset 0 -1 WITHSCORES - 获取有序集合"myzset"中所有元素及其分数 |
ZRANGE |
获取有序集合中分数从低到高的元素 | ZRANGE myzset 0 -1 WITHSCORES - 获取有序集合"myzset"中所有元素及其分数 |
示例:对列表进行升序排序并获取结果。
SORT mylist ASC
19.Redis流(Streams)
命令 | 描述 | 示例 |
---|---|---|
XADD |
向流中添加一个新条目 | XADD mystream * field1 value1 field2 value2 - 向"mystream"添加新条目 |
XREAD |
从流中读取数据 | XREAD COUNT 1 STREAMS mystream 0-0 - 从"mystream"读取一个条目 |
XRANGE |
获取流中指定范围内的条目 | XRANGE mystream - + - 获取"mystream"中所有条目 |
XREVRANGE |
获取流中指定范围内的条目,按相反顺序 | XREVRANGE mystream + - COUNT 1 - 获取"mystream"中的最后一个条目 |
XLEN |
获取流中的条目数量 | XLEN mystream - 获取"mystream"中的条目数量 |
XDEL |
删除流中的一个或多个条目 | XDEL mystream ID - 删除"mystream"中的ID条目 |
XGROUP |
创建、获取、破坏消费者组 | XGROUP CREATE mystream mygroup 0 MKSTREAM - 创建消费者组 |
XREADGROUP |
从消费者组读取数据 | XREADGROUP GROUP mygroup myconsumer COUNT 1 STREAMS mystream > - 从消费者组读取数据 |
XACK |
确认消息已经被处理过 | XACK mystream mygroup ID - 确认"mystream"的"mygroup"消费者组中的ID条目 |
示例:向流"mystream"中添加一个新条目。
XADD mystream * field1 "value1" field2 "value2"
20.Redis模块
命令 | 描述 | 示例 |
---|---|---|
MODULE LIST |
列出已加载的模块 | MODULE LIST - 列出所有已加载的模块 |
MODULE LOAD |
加载一个新的模块 | MODULE LOAD /path/to/module.so - 加载指定路径的模块 |
MODULE UNLOAD |
卸载一个已加载的模块 | MODULE UNLOAD modulename - 卸载名为"modulename"的模块 |
MODULE EXISTS |
检查模块是否已加载 | MODULE EXISTS modulename - 检查"modulename"模块是否已加载 |
MODULE |
用于执行模块命令,如MODULE CREATE 等 |
MODULE CREATE mymodule - 创建一个名为"mymodule"的模块 |
自定义命令 | 模块可以提供自定义命令 | mymodule:mycommand arg1 arg2 - 使用模块提供的自定义命令 |
模块化架构 | 允许第三方开发者扩展Redis的功能 | 通过模块化架构,开发者可以添加新的数据类型、命令等 |
示例:加载一个名为"mymodule"的Redis模块。
MODULE LOAD /path/to/mymodule.so
21.Redis哈希槽(Hash Slot)
命令 | 描述 | 示例 |
---|---|---|
CLUSTER KEYSLOT |
获取与一个键名关联的哈希槽 | CLUSTER KEYSLOT mykey - 获取键"mykey"的哈希槽编号 |
CLUSTER COUNTSLOT |
获取集群中每个槽的键值对数量 | CLUSTER COUNTSLOT - 获取集群中每个哈希槽的统计信息 |
CLUSTER GETKEYSINSLOT |
获取特定哈希槽中的键 | CLUSTER GETKEYSINSLOT 0 10 - 获取哈希槽0中的前10个键 |
哈希槽分布 | Redis集群使用16384个哈希槽来分布键 | 哈希槽确保键在集群中的分布均匀 |
示例:获取键"mykey"所在的哈希槽。
CLUSTER KEYSLOT mykey
22.Redis虚拟内存
命令 | 描述 | 示例 |
---|---|---|
CONFIG SET |
设置虚拟内存相关的配置 | CONFIG SET vm-enabled yes - 启用虚拟内存 |
VMSTATS |
显示虚拟内存的统计信息 | VMSTATS - 查看虚拟内存的统计信息 |
Swap文件 | Redis使用Swap文件作为虚拟内存 | Swap文件允许Redis使用磁盘空间作为内存的扩展 |
内存回收 | Redis可以配置内存回收策略,以决定何时将数据交换到Swap文件 | 内存回收策略可以与数据淘汰策略结合使用 |
示例:启用Redis虚拟内存。
CONFIG SET vm-enabled yes
CONFIG SET vm-swap-file /var/redis/swapfile
CONFIG SET vm-max-memory 100mb
23.Redis连接池
概念 | 描述 | 示例 |
---|---|---|
连接池 | 管理数据库连接的集合,减少频繁创建和销毁连接的开销 | 使用连接池可以重用已有的数据库连接 |
池化参数 | 可以通过参数设置连接池的大小和行为 | 连接池的参数通常由客户端库提供 |
客户端库 | 许多语言提供了支持连接池的Redis客户端库 | 如Jedis(Java)、redis-py(Python)等 |
连接超时 | 连接池中的连接如果空闲超时,可能会被自动关闭 | 需要配置合适的超时时间以避免不必要的连接关闭 |
示例:在Java中使用Jedis连接池。
java
JedisPoolConfig poolConfig = new JedisPoolConfig();
poolConfig.setMaxTotal(100);
JedisPool jedisPool = new JedisPool(poolConfig, "localhost", 6379);
Jedis jedis = jedisPool.getResource();
jedis.set("key", "value");
jedis.close();
24.Redis分布式锁
命令 | 描述 | 示例 |
---|---|---|
SETNX |
设置键如果它不存在,常用于实现分布式锁 | SETNX lock_key unique_value - 尝试获取锁 |
EXPIRE |
设置键的过期时间,确保锁最终能够释放 | EXPIRE lock_key 10 - 为"lock_key"设置10秒的过期时间 |
DEL |
删除键,释放锁 | DEL lock_key - 删除"lock_key",释放锁 |
锁续期 | 锁的持有者需要定期续期以避免意外释放 | 使用定时任务或后台进程来续期锁 |
示例:使用Redis实现分布式锁。
bash
# 尝试获取锁
IF (SETNX lock_key unique_value) == 1 THEN
# 锁已被获取
# ... 执行操作 ...
# 锁操作完成后删除锁
DEL lock_key
ELSE
# 锁已被其他进程持有
END
在java应用中,尤其是SpringBoot项目中,可以使用Redisson来使用分布式锁
首先,确保你已经添加了Redisson的依赖到你的项目中。如果你使用Maven,可以在pom.xml
文件中添加如下依赖:
XML
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-boot-starter</artifactId>
<version>3.15.3</version>
</dependency>
然后,配置Redisson与你的Redis服务器连接:
python
# application.yml
spring:
redis:
host: localhost
port: 6379
password: your-redis-password
或者,如果你不使用Spring Boot,你可以直接在代码中配置:
java
Config config = new Config();
config.useSingleServer()
.setAddress("redis://localhost:6379")
.setPassword("your-redis-password");
RedissonClient redisson = Redisson.create(config);
接下来,你可以使用Redisson的RLock
对象来实现分布式锁:
java
RLock lock = redisson.getLock("myLock");
try {
// 尝试获取锁,等待时间是10秒,锁的持有时间是30秒
lock.tryLock(10, 30, TimeUnit.SECONDS);
// 业务逻辑处理
// ...
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
// 解锁
lock.unlock();
}
在这个示例中,tryLock()
方法尝试获取名为myLock
的锁。如果锁在10秒内可用,当前线程将获得锁并执行业务逻辑。如果获取成功,锁将被持有30秒,即使持有锁的线程在这段时间内执行完毕。如果需要更复杂的逻辑,例如锁续期,可以在finally
块中实现。
请注意,使用分布式锁时,要特别注意避免死锁和确保锁的释放,即使在发生异常的情况下。上面的代码中,finally
块确保了锁在操作完成后总是被释放。
此外,Redisson还提供了其他类型的锁,如公平锁、读写锁、红锁等,你可以根据需要选择使用。
25.Redis事务的高级用法
命令 | 描述 | 示例 |
---|---|---|
WATCH |
在执行事务前监控一个或多个键,如果在事务执行前这些键被修改,则事务不执行 | WATCH key1 key2 - 在事务执行前监控"key1"和"key2" |
MULTI |
开始事务,将多个命令放入队列 | MULTI - 开始事务 |
EXEC |
提交事务,执行队列中的所有命令 | EXEC - 提交事务 |
事务条件执行 | 只在满足特定条件时执行事务 | 使用WATCH 命令配合事务 |
命令队列 | 事务中的命令被放入队列,一次性发送给服务器执行 | 命令队列减少了服务器和客户端之间的通信次数 |
示例:使用WATCH
和事务来安全地递增一个值。
WATCH mycounter
val = GET mycounter
val = val + 1
MULTI
SET mycounter $val
EXEC
26.缓存常见问题
|------|---------------------------------------|--------------------------------------------------------------------------------------|
| 问题 | 出现原因 | 解决方案 |
| 缓存雪崩 | 1.缓存数据大批量同时过期;2.服务不可用,例如整个Redis服务宕机 | 1. 设置不同的过期时间,为缓存的过期时间加上随机值,避免大规模同时过期 2. 限流策略,平滑请求峰值。 3. 缓存高可用,如使用哨兵或集群。 |
| 缓存穿透 | 1. 请求不存在的缓存数据。 2.恶意攻击,频繁访问数据库中不存在的数据。 | 1. 对缓存中不存在的key设置为空值null或使用布隆过滤器拦截那些查询不存在数据的请求。 2.使用日志记录异常访问,进行限流或封禁恶意访问。 3.定期更新缓存数据。 |
| 缓存击穿 | 高并发请求同时到达,缓存中的热点数据过期 | 1. 使用互斥锁(mutex)在缓存过期时同步请求,防止大量线程同时查询数据库。 2.设置热点数据永不过期或延长过期时间。 3.实现缓存预热,提前加载热点数据。 |
好了,先总结这些,其实Redis的知识点还有不少细节,后期再抽时间继续细化,或者再开一篇博客写一些注意的细节或者面试中的高频问题