Redis 命令是与 Redis 服务器进行通信和操作数据的核心手段。通过这些命令,开发者可以高效地管理和操作多种数据结构(如字符串、哈希、列表、集合、有序集合等),满足多样化的业务需求。 这节课我们将学习 Redis 支持的主要命令及其使用方式,帮助你更深入地理解 Redis 的核心价值。

在 Redis 中,字符串类型远不止于简单的文本存储。它不仅可以保存常规的文本、字节序列,还能高效存储整数和浮点数。更为重要的是,Redis 针对字符串数据提供了完善的数值操作能力,使我们能够直接在服务端完成各类数学运算。
以常见的场景为例,比如统计网站访问量、商品销售量等。传统实现通常涉及先从 Redis 读取数值、在应用侧加减计算后再写回。相比之下,Redis 本身就支持原子性的自增/自减,能大幅简化开发流程,并提高并发场景下的数据准确性。
|# 传统实现方式 import redis r = redis.Redis() 当前访问量 = r.get('文章:123:访问量') if 当前访问量: 新访问量 = int(当前访问量) + 1 else: 新访问量 = 1 r.set('文章:123:访问量', 新访问量)
用 Redis 的 INCR 命令一步完成:
|# Redis 原子自增操作(中文 key 和注释) r.incr('文章:123:访问量')
这样的方案不仅有效降低了网络往返的次数,更能规避并发环境下的数据竞争问题。对于需要高并发统计的业务场景而言,传统方式容易出现访问量遗漏的情况。而借助 Redis 的原子性自增命令,可确保每一次计数都精准无误。
原子性操作对于高并发高可靠的系统至关重要。无论多少客户端同时操作同一个 key,Redis 都能保证操作的完整性与一致性。
除了数值原子操作,Redis 还支持对字符串进行位级操作(bit operations),为权限管理、标记系统等场景提供了高效工具。
以权限管理为例:假设每个权限用一个二进制位表示,使用 SETBIT 和 GETBIT 命令即可灵活设置或读取指定权限位的值。
|# 设置用户权限的特定位 r.setbit('user:123:permissions', 0, 1) # 阅读权限 r.setbit('user:123:permissions', 1, 1) # 写作权限 r.setbit('user:123:permissions', 2, 0) # 管理权限 # 检查特定权限 can_read = r.getbit('user:123:permissions', 0)
这种位操作不仅节省存储空间(8个权限只需要1个字节),还能提供极快的查询速度。在处理大量用户的权限系统时,这种设计可以显著提升性能。
Redis 还为字符串提供了灵活的子串操作,包括内容追加、截取和局部替换等功能。在动态拼接消息、日志处理等实际开发场景中,这些能力能够高效且专业地满足各种字符串处理需求。
|# 动态构建用户状态消息 r.set('user:123:status', '小明') r.append('user:123:status', '正在学习Redis') # 获取部分内容 prefix = r.getrange('user:123:status', 0, 1) # "小明" # 替换特定位置的内容 r.setrange('user:123:status', 6, '精通')
凭借强大的字符串操作能力,Redis 不只是高效的缓存工具,也能够胜任各种复杂的文本处理场景。
灵活运用这些字符串命令,你会发现 Redis 已远不只是单纯的键值存储。它提供了丰富且精细的原子操作,助你以极高性能和多样方式处理各类数据需求。
在需要处理有序数据集合时,Redis 的列表结构堪称通用型“收纳柜”。它支持从头尾两端灵活插入和弹出元素,天然适合实现队列、栈以及最近访问列表等多种场景。
举例来说,搭建一个任务队列系统时,通常采用先进先出的处理逻辑。此时,Redis 的 RPUSH 和 LPOP 命令组合便是极简且高效的解决方案:
|# 工作人员提交任务到队列末尾 r.rpush('task:queue', '整理文档') r.rpush('task:queue', '审核报告') r.rpush('task:queue', '发送邮件') # 工作人员从队列头部取出任务 current_task = r.lpop('task:queue') # "整理文档"
这种设计让任务队列的实现变得非常高效而专业。你可以灵活地将任务从队列一端加入,从另一端依次取出,天然保证了严格的执行顺序,非常适合用来处理各类顺序任务流。
区别于传统的队列仅支持两端插入和弹出,Redis 的列表结构还具备随机访问与修改能力。你可以像操作数组一样,直接读取或更新列表中任意指定位置的元素:
|# 记录用户最近浏览的商品 r.lpush('user:123:recent_views', '商品A') r.lpush('user:123:recent_views', '商品B') r.lpush('user:123:recent_views', '商品C') # 查看最近的浏览记录 recent_items = r.lrange('user:123:recent_views', 0, 2) # ["商品C", "商品B", "商品A"] # 获取特定位置的商品 third_item = r.lindex('user:123:recent_views', 2) # "商品A"
凭借随机访问功能,Redis 列表不仅适合实现队列,还可以胜任诸如用户最近浏览记录、排行榜等多样化场景。
在实际业务中,随着数据持续写入,列表长度可能会不断增长。Redis 提供了 LTRIM 命令,便于你对列表按需截取,灵活地控制其长度,确保内存占用在可控范围内:
|# 只保留最近10个浏览记录 r.ltrim('user:123:recent_views', 0, 9) # 清理过期消息,只保留最新的100条 r.ltrim('chat:messages', -100, -1)
通过截取操作,可以高效管理日志记录、用户行为追踪等不断增长的数据,让内存占用始终处于可控状态,提升系统的健壮性。
LTRIM命令的参数遵循Redis的索引规则:0代表第一个元素,-1代表最后一个元素。这一设计使得区间裁剪直观、灵活,便于精确控制所需的数据范围。
除了常规弹出外,Redis列表还支持阻塞弹出(如BLPOP、BRPOP)。当列表暂时为空时,客户端可以等待新元素的到来,非常适合实现高效且可靠的生产者-消费者模式:
|# 消费者等待新任务 task = r.blpop('task:queue', timeout=30) # 最多等待30秒 if task: print('收到新任务:', task[1]) # 处理任务逻辑
|# 生产者添加任务 r.rpush('task:queue', '新任务:数据分析')
通过阻塞式弹出,消费者能够高效地等待新任务的到来,无需定时轮询,显著降低了系统资源消耗,提升了任务处理的响应效率。
Redis 同样支持在多个列表之间原子性地转移元素,这一特性在构建任务流转、消息路由等复杂业务场景时极为实用:
|# 将处理中的任务转移到完成队列 r.rpoplpush('task:processing', 'task:completed')
原子性的转移操作能够确保数据在不同列表间迁移时绝对不会丢失,这对于分布式系统中保证任务或消息的可靠性至关重要。
利用列表相关命令,你会体会到Redis在有序数据处理方面的强大与灵活。不论是实现高性能队列,还是搭建复杂的任务流,Redis列表都能为你提供专业且高效的支持。
在需要数据去重和快速集合计算的场景下,Redis集合类型(Set)是一种极为实用的解决方案。它不仅天生保证元素不重复,还内建了丰富的数学集合操作,极大地提升了标签管理、用户关系分析、权限控制等业务的处理效率。
以博客系统的标签管理为例:你可能希望每篇文章拥有一组唯一标签,并能够随时判断某个标签是否已被分配。Redis集合天生具备这些能力:
|# 为文章添加标签 r.sadd('article:123:tags', 'JavaScript') r.sadd('article:123:tags', 'Web开发') r.sadd('article:123:tags', '前端') # 即使重复添加也不会有影响 r.sadd('article:123:tags', 'JavaScript') # 返回0,表示没有新元素被添加 # 检查标签是否存在 has_tag = r.sismember('article:123:tags', 'React') # False # 获取所有标签 all_tags = r.smembers('article:123:tags'
得益于集合的天然唯一性,使用 Redis Set 可以极为高效地满足去重需求。开发者无需编写任何额外校验逻辑,重复元素会被自动屏蔽,保证数据的一致性和准确性。
集合不维护元素顺序,因此在需要从数据集中随机抽取元素时非常适用。例如,可用于实现抽奖功能、内容推荐等业务需求:
|# 记录参与抽奖的用户 r.sadd('lottery:participants', 'user1', 'user2', 'user3', 'user4', 'user5') # 随机抽取一个获奖者 winner = r.srandmember('lottery:participants') # 从集合中随机移除一个元素(用于一次性优惠券等) lucky_user = r.spop('lottery:participants')
类似的随机操作,在游戏化激励、内容推荐等业务中极为常见,能够高效满足抽奖、分发福利、动态推荐等多样化需求。
集合类型的核心价值体现在其强大的数学运算能力,包括交集、并集与差集。这些集合运算为客户标签管理、社交关系分析等复杂场景提供了坚实的数据支撑和高效的计算方式。
|# 记录不同用户的兴趣标签 r.sadd('user:张三:兴趣', '篮球', '编程', '旅行') r.sadd('user:李四:兴趣', '编程', '音乐', '旅行') r.sadd('user:王五:兴趣', '篮球', '摄影', '音乐') # 找到张三和李四都感兴趣的标签(交集) common_interests = r.sinter('user:张三:兴趣', 'user:李四:兴趣') # ["编程", "旅行"] # 找到所有用户涉及的兴趣标签(并集) all_interests
这些集合运算完全由Redis在服务端执行,无需将大量数据拉取到应用程序层再进行处理,显著提升了运算效率和系统性能。
集合运算的时间复杂度通常和集合的元素数量成正比。在处理超大规模集合时,建议提前评估性能开销,合理设计数据结构。
对于那些需要反复查询或在多个地方复用的集合运算结果,Redis 支持将运算的输出直接存储到新的集合键中,大大提升了后续访问的效率和共享的便利性。
|# 衔接上面的标签示例,将张三和李四的共同兴趣保存到新集合 r.sinterstore('common:zhangsan_lisi', 'user:张三:兴趣', 'user:李四:兴趣') # 后续可以直接查询两人共有的兴趣标签 common_interests = r.smembers('common:zhangsan_lisi')
借助 sinterstore 等命令,可以直接将运算结果保存为新的集合键,避免了多次重复计算,这对于高频访问或需要复用查询结果的场景尤为高效。
综合来看,Redis 的集合操作不仅在唯一元素管理、关系型数据计算方面展现出很高的性能,还极大简化了服务端的数据处理流程。
当面对结构化数据存储需求时,Redis 哈希类型提供了灵活且专业的支持。它允许我们将同一实体的多个属性集中在一个键下,便于高效管理,比如常见的用户账户信息、配置信息、统计字段等。
假设我们开发用户管理系统,需要存储每位用户的详细资料。如果采用传统方案,常常需要为每个属性设置独立的键,既容易混乱又不易维护。而采用 Redis 哈希结构,可以将这些字段有序聚合,极大提升数据管理和访问的便捷性:
|# 将用户信息存储在哈希中 r.hmset('user:123', { 'name': '小明', 'age': '25', 'email': 'xiaoming@example.com', 'city': '北京' }) # 获取用户的特定信息 user_name = r.hget('user:123', 'name') # "小明" user_email = r.hget('user:123', 'email') # "xiaoming@example.com" # 批量获取多个字段
采用哈希结构可以将同一实体的数据有机整合在一个键下,实现高效、集中式的数据管理与查询。例如,完整的用户信息只需存储在单一哈希键中,避免了多键分散带来的复杂性。
Redis 哈希类型为字段级的数据管理提供了细致且高效的指令,便于开发者灵活实现属性的新增、删除、修改和读取:
|# 检查字段是否存在 has_age = r.hexists('user:123', 'age') # True # 获取哈希中所有字段的数量 field_count = r.hlen('user:123') # 4 # 删除特定字段 r.hdel('user:123', 'age') # 更新现有字段 r.hset('user:123', 'city', '上海') # 增加数值字段 r.hincrby('user:123', 'login_count', 1)
通过上述设计,哈希不仅能够高效存储结构化字符串,还支持原子性的数值运算,对于各类数据统计、行为计数等业务场景尤为适用。
当需要一次性查看对象的所有属性、支持快速调试或数据同步时,Redis 哈希为开发者提供了专业的批量访问指令:
|# 获取所有字段名 fields = r.hkeys('user:123') # ["name", "email", "city", "login_count", "score"] # 获取所有字段值 values = r.hvals('user:123') # ["小明", "xiaoming@example.com", "上海", "2", "0.5"] # 获取完整的字段-值对 user_data = r.hgetall('user:123') # {"name": "小明", "email": "xiaoming@example.com", "city": "上海", "login_count": "2", "score": "0.5"}
HGETALL命令会返回哈希中的所有数据。在哈希字段较多时,需要注意内存使用和网络传输开销。
哈希结构在实际项目中的应用非常丰富,例如,在一个电商平台,每个商品的多个属性(如名称、价格、库存、分类、评价等)可以统一存放在同一个哈希结构下,方便集中管理和高效查询。例如,某件无线耳机的商品信息可以利用哈希一次性写入:
|# 设置商品详细信息 r.hmset('product:456', { 'name': '无线耳机', 'price': '299', 'stock': '50', 'category': '电子产品', 'rating': '4.5' }) # 查询商品当前库存 current_stock = r.hget('product:456', 'stock') # 增加销量,自动创建字段并递增 r.hincrby('product:456', 'sales'
在高并发的抢购、秒杀场景中,hincrby等命令能保证多个用户同时操作时库存不会出错,因为每条命令都是原子执行,极大地提升了安全性和一致性。
而社交应用中,用户的发帖数、粉丝数、获赞数等动态指标也很适合用哈希结构统一记录。例如:
|# 新发一条帖子 r.hincrby('user:123:stats', 'posts', 1) # 用户获得新粉丝 r.hincrby('user:123:stats', 'followers', 1) # 帖子获赞 r.hincrby('user:123:stats', 'likes', 5) # 查询统计数据 user_stats = r.hgetall('user:123:stats') # 结果类似:{'posts': '12', 'followers': '203', 'likes': '56'}
通过将所有统计信息聚合存储在一个哈希键下,既简化了结构,又便于批量读取和运算。
在实际开发中,常常会遇到既需要数据唯一性、又希望按照某种顺序进行排序的业务需求。Redis 的有序集合结构,正为此提供了高效、专业的解决方案。它为每个成员分配一个可排序的分数(score),从而实现自动排序,并支持高效的排名与区间检索。
例如在一款在线游戏中,系统需实时维护玩家积分排行榜,保证玩家唯一且随积分自动排序。此时,使用 Redis 的有序集合,可以轻松实现这一需求:
|# 添加玩家得分 r.zadd('game:leaderboard', {'player1': 1500, 'player2': 1200, 'player3': 1800}) # 增加玩家得分 r.zincrby('game:leaderboard', 100, 'player1') # 得分变为1600 # 获取玩家得分 score = r.zscore('game:leaderboard', 'player1') # 1600 # 获取排行榜大小 total_players = r.zcard('game:leaderboard'
这种设计让分数管理和排名查询变得异常简单。你可以实时更新分数,系统会自动维护排序。 有序集合最强大的功能在于它能提供丰富的排名查询,例如,获取玩家排名、获取前三名玩家、获取倒数第一名等:
|# 获取玩家排名(从小到大) rank = r.zrank('game:leaderboard', 'player1') # 1(排名从0开始) # 获取前三名玩家 top_players = r.zrange('game:leaderboard', 0, 2, withscores=True) # [("player2", 1200), ("player1", 1600), ("player3", 1800)] # 获取倒数第一名(从大到小排名) reverse_rank = r.zrevrank('game:leaderboard', 'player1') # 1 # 从高分到低分获取前三名 top_players_desc = r.zrevrange(
这种双向排名查询能力让排行榜实现变得极为便捷。
同时有序集合还支持基于分数范围的操作,非常适合处理时间窗口、等级区间等需求:
|# 添加更多玩家数据 r.zadd('game:leaderboard', {'player4': 800, 'player5': 950, 'player6': 2000}) # 获取得分在1000-1500之间的玩家 mid_range = r.zrangebyscore('game:leaderboard', 1000, 1500) # ["player2", "player5", "player1"] # 获取得分高于1500的玩家数量 high_score_count = r.zcount('game:leaderboard', 1500, float('inf'))
有序集合的分数范围查询使用了数学区间表示法:-inf表示负无穷,+inf表示正无穷。这种设计让范围查询变得灵活而精确。
与普通集合类似,有序集合同样支持交集和并集等集合运算。但与普通集合仅仅关注成员不同,有序集合在进行这些操作时还需要结合每个成员的分数字段进行综合处理。 例如,在交集和并集时,可以指定分数的聚合方式(如求和、取最大值或平均值),以决定同名成员最终的分数结果。这种机制让我们可以实现不同数据源的排行融合、筛选出多条件下都符合的成员,或者统计在多个排行榜中的综合表现,满足复杂的数据分析需求:
|# 创建两个有序集合 r.zadd('math:scores', {'alice': 85, 'bob': 92, 'charlie': 78}) r.zadd('english:scores', {'alice': 88, 'bob': 79, 'diana': 95}) # 计算两科成绩的平均分(交集) r.zinterstore('avg:scores', ['math:scores', 'english:scores'], aggregate=
在各类对实时通信有较高要求的应用场景中,Redis 发布订阅系统提供了一种高效、低延迟的消息分发方案。通过发布者(Publisher)向指定频道(Channel)发送消息,所有已订阅(Subscriber)该频道的客户端都能即时接收,实现一对多的异步通信。 这一机制广泛应用于即时通讯、实时通知、系统监控、事件驱动架构等领域,能够有效支撑高并发环境下的消息广播与动态数据分发需求。
以典型的聊天室系统为例,用户可通过 Redis 发布订阅机制发送和接收来自不同频道(即不同“房间”)的信息:
|import redis import threading import time # 订阅者监听聊天频道 def subscriber_handler(): subscriber = r.pubsub() subscriber.subscribe('chat:room1') for message in subscriber.listen(): if message['type'] == 'message': print(f"收到来自{message['channel']}的消息:
这种设计让消息传递变得异常简单。一个发布者可以向多个订阅者广播消息,而订阅者可以同时监听多个频道。
发布订阅系统提供了灵活而详细的订阅管理机制,允许客户端根据实际需求动态调整订阅频道。具体包括:
|# 订阅多个频道 subscriber.subscribe('news:sports', 'news:tech', 'news:entertainment') # 退订特定频道 subscriber.unsubscribe('news:sports') # 退订所有频道 subscriber.unsubscribe() # 模式订阅(支持通配符) subscriber.psubscribe('news:*') # 订阅所有以news:开头的频道 # 取消模式订阅 subscriber.punsubscribe('news:*')
这些管理能力使得开发者能够更加细粒度地控制消息通道的监听与处理,满足复杂业务场景下对于订阅管理的各种需求。
Redis的发布订阅系统不会持久化消息。如果订阅者在消息发送时离线,将无法收到该消息。在需要可靠消息传递的场景中,应该考虑其他解决方案。
发布订阅系统在高并发场景下表现出色,能够快速处理大量消息的发布与分发。其核心机制基于事件驱动,即每当有消息发布到某个频道时,Redis 会同步将消息推送给所有当前已订阅该频道的客户端。 由于采用了高效的 I/O 多路复用技术,Redis 能够在极短时间内将同一消息分发给成百上千个订阅者,无需额外存储和队列中转,大大降低了时延和资源消耗。 同时,发布操作始终为 O(N) 复杂度,N 为当前频道的订阅者数量,因此在订阅者数量适中的情况下依然能维持极高的吞吐能力。这使得 Redis 发布订阅非常适合用于实时数据推送、通知广播等对时效性和并发能力要求较高的场景。
|import json # 发布实时通知 notification = { 'type': 'friend_request', 'from': 'user456', 'message': '小明请求添加你为好友' } r.publish('user:123:notifications', json.dumps(notification)) # 发布系统事件 event = { 'event': 'user_login', 'user_id': '123', 'timestamp': time.time() }
尽管发布订阅非常强大,但在实际应用中也存在一些局限性,比如消息不会持久化,导致离线订阅者可能会错过消息;缺乏确认机制,发布者无法获知消息是否被订阅者接收;同时,如果有大量消息积压,也会带来较高的内存消耗。因此,在设计系统时需要充分权衡这些因素。
在需要可靠消息传递的场景中,可以考虑使用Redis列表或流(Stream)来实现更稳定的消息队列系统。
除了基础的数据结构操作外,Redis还具备高效的排序、原子性事务和键过期等高级特性,为各类复杂业务场景提供了强有力的支撑,使其不仅是高速缓存,更是一套完整的内存数据平台。
Redis的 SORT 命令功能丰富,可作用于列表、集合及有序集合。它不仅支持对自身元素排序,还允许根据外部键的值自定义排序逻辑,实现灵活的数据处理需求:
|# 创建测试数据 r.rpush('students', '小明', '小红', '小刚') r.set('score:小明', '95') r.set('score:小红', '87') r.set('score:小刚', '92') # 按姓名字母顺序排序 alphabetical = r.sort('students', alpha=True) # ["小刚", "小明", "小红"] # 按成绩排序(从高到低) by_score =
这种排序能力在处理排行榜、搜索结果排序等场景时非常有用。
SORT命令的时间复杂度是O(N+M*log(M)),其中N是排序元素数量,M是结果集大小。在处理大数据集时需要注意性能。
在分布式系统或并发场景下,保证多步操作的原子性至关重要。Redis 通过事务(Transaction)机制,为开发者提供了一种确保一系列命令以“要么全部成功,要么全部不执行”原则完成的能力。 具体来说,Redis 事务允许将多个命令打包在一起提交执行,所有命令会被顺序排队,最终统一提交。如果在事务执行过程中发生错误,可以选择放弃整个事务,确保数据的完整性和一致性。在实际业务中,这种机制广泛应用于转账、库存扣减等对原子性强依赖的场景。
|# 使用pipeline创建事务 pipeline = r.pipeline() # 转账操作:从账户张三转100元到账户李四 pipeline.decrby('account:zhangsan', 100) pipeline.incrby('account:lisi', 100) # 记录转账日志 transfer_record = { 'from': '张三', 'to': '李四', 'amount': 100, 'timestamp': time.time() } pipeline.rpush('transfer:log'
这种事务机制保证了操作的原子性,避免了并发访问时的数据不一致问题。
Redis提供了灵活的键过期机制,可以实现数据的自动失效与清理,非常适合用于缓存和临时数据等需要生命周期管理的场景:
|# 设置键过期时间(秒) r.set('cache:user:123', '用户信息') r.expire('cache:user:123', 3600) # 1小时后过期 # 设置键在指定时间戳过期 r.set('temp:token', '临时令牌') r.expireat('temp:token', int(time.time()) + 86400) # 明天过期 # 检查剩余生存时间 ttl = r.ttl('cache:user:123') # 返回剩余秒数 # 取消过期时间 r.persist('cache:user:123'
借助自动过期机制,缓存的生命周期管理变得高效且可靠,无需开发者额外编写清理流程。
通过这些高级命令,你会发现Redis远不止是一个简单的键值存储。它提供了丰富的高级特性,让你在构建复杂应用时能够得心应手。合理运用这些功能,可以显著提升应用的性能和可靠性。
首先,我们来设置一些初始数据:
|# 连接到 Redis redis-cli # 设置博客文章的访问量 SET article:1001:views 150 SET article:1002:views 89 SET article:1003:views 234 # 设置用户信息 SET user:alice:status "小明正在学习Redis" SET user:bob:bio "热爱编程的技术宅"
现在,请完成以下操作:
|# 1. 增加访问量 INCR article:1001:views # 返回: (integer) 151 # 2. 追加状态信息 APPEND user:alice:status ",进步很快!" # 返回: (integer) 25 (新字符串长度) # 验证结果: GET user:alice:status # "小明正在学习Redis,进步很快!" # 3. 获取部分字符串 GETRANGE user:bob:bio 0 3 # "热爱编程"
让我们创建一些任务队列数据:
|# 创建任务队列 RPUSH task:queue "整理文档" RPUSH task:queue "审核报告" RPUSH task:queue "发送邮件" RPUSH task:queue "数据备份" # 创建用户浏览历史 LPUSH user:alice:history "首页" LPUSH user:alice:history "产品列表" LPUSH user:alice:history "商品详情" LPUSH user:alice:history "购物车"
请完成以下任务:
|# 1. 取出任务 LPOP task:queue # "整理文档" # 查看剩余任务 LRANGE task:queue 0 -1 # 1) "审核报告" # 2) "发送邮件" # 3) "数据备份" # 2. 查看浏览历史 LRANGE user:alice:history 0 4 # 1) "购物车" # 2) "商品详情" # 3) "产品列表" # 4) "首页" # 3. 移动任务到完成队列 RPOPLPUSH task:queue task:completed # "数据备份" # 查看完成队列 LRANGE task:completed 0 -1 # 1) "数据备份"
创建一些用户标签数据:
|# 添加用户兴趣标签 SADD user:alice:interests "编程" "阅读" "音乐" "旅行" SADD user:bob:interests "编程" "游戏" "音乐" "摄影" SADD user:charlie:interests "阅读" "音乐" "电影" "烹饪" # 添加抽奖参与者 SADD lottery:participants "alice" "bob" "charlie" "david" "eve"
请完成以下操作:
|# 1. 检查兴趣 SISMEMBER user:alice:interests "游戏" # (integer) 0 (表示不存在) SISMEMBER user:alice:interests "编程" # (integer) 1 (表示存在) # 2. 求交集(共同兴趣) SINTER user:alice:interests user:bob:interests # 1) "编程" # 2) "音乐" # 3. 随机抽奖 SRANDMEMBER lottery:participants # "charlie" (每次运行结果可能不同) # 查看剩余参与者 SCARD lottery:participants # (integer) 5 (集合大小不变,随机获取不移除元素)
设置用户信息数据:
|# 设置用户信息 HMSET user:1001 name "张三" age "25" email "zhangsan@example.com" city "北京" HMSET user:1002 name "李四" age "30" email "lisi@example.com" city "上海" HMSET user:1003 name "王五" age "28" email "wangwu@example.com" city "广州" # 设置商品信息 HMSET product:2001 name "无线耳机" price "299" stock "50"
请完成以下操作:
|# 1. 获取多个字段 HMGET user:1001 name email # 1) "张三" # 2) "zhangsan@example.com" # 2. 增加销量 HINCRBY product:2001 sales 1 # (integer) 1 (返回新值) HINCRBY product:2001 sales 3 # (integer) 4 (继续增加) # 3. 获取所有信息 HGETALL user:1002 # 1) "name" # 2) "李四" # 3) "age" # 4) "30" # 5) "email" # 6) "lisi@example.com" # 7) "city" # 8) "上海"
创建游戏排行榜数据:
|# 添加玩家分数 ZADD game:leaderboard 1500 "alice" 1200 "bob" 1800 "charlie" 800 "david" ZADD game:leaderboard 950 "eve" 2000 "frank" # 添加更多玩家 ZADD game:scores:math 85 "alice" 92 "bob" 78 "charlie" 88 "diana" ZADD game:scores:english 88 "alice" 79 "bob" 95 "diana" 82 "eve"
请完成以下操作:
|# 1. 获取前三名(从高到低) ZREVRANGE game:leaderboard 0 2 WITHSCORES # 1) "frank" # 2) "2000" # 3) "charlie" # 4) "1800" # 5) "alice" # 6) "1500" # 2. 获取排名(从低到高排名) ZRANK game:leaderboard alice # (integer) 3 (排名从0开始) # 从高到低排名 ZREVRANK game:leaderboard alice # (integer) 1 (表示第二名) # 3. 范围查询 ZRANGEBYSCORE game:scores:math 80 90 # 1) "alice" # 2) "diana"
首先启动一个订阅者(在新终端窗口中):
|# 终端1:启动订阅者 redis-cli SUBSCRIBE chat:room1
然后在另一个终端执行发布操作:
|# 终端2:发布消息 redis-cli PUBLISH chat:room1 "大家好!欢迎来到Redis聊天室" PUBLISH chat:room1 "今天我们学习Redis命令"
请观察订阅者终端收到的消息内容。
|# 订阅者终端应该会收到类似如下消息: # 1) "subscribe" # 订阅确认 # 2) "chat:room1" # 频道名 # 3) (integer) 1 # 订阅数量 # 1) "message" # 消息类型 # 2) "chat:room1" # 来源频道 # 3) "大家好!欢迎来到Redis聊天室" # 消息内容 # 1) "message" # 2) "chat:room1" # 3) "今天我们学习Redis命令"
创建银行账户数据:
|# 设置账户余额 SET account:alice 1000 SET account:bob 500 # 创建转账日志列表 RPUSH transfer:log "系统初始化完成"
请使用事务完成从 alice 转账 200 元到 bob 的操作:
|# 开始事务 MULTI # 转账操作 DECRBY account:alice 200 INCRBY account:bob 200 # 记录转账日志 RPUSH transfer:log "alice 转账 200 元给 bob" # 执行事务 EXEC # 返回结果: # 1) (integer) 800 # alice 余额变为 800 # 2) (integer) 700 # bob 余额变为 700 # 3) (integer) 2 # 日志列表长度 # 验证结果 GET account:alice # "800" GET account:bob # "700" LRANGE transfer:log 0 -1
设置一些临时数据:
|# 设置缓存数据 SET cache:user:profile "用户信息缓存" SET cache:article:list "文章列表缓存" # 设置临时令牌 SET temp:token:abc123 "临时访问令牌" SET temp:session:xyz789 "会话数据"
请完成以下操作:
|# 1. 设置过期时间(秒) EXPIRE cache:user:profile 300 # (integer) 1 (成功) # 2. 设置令牌过期 EXPIRE temp:token:abc123 60 # (integer) 1 # 3. 检查剩余时间 TTL cache:user:profile # (integer) 295 (剩余秒数,每次查询会递减) TTL temp:token:abc123 # (integer) 58 TTL cache:article:list # (integer) -1 (-1表示没有设置过期时间) # 等待一段时间后再次检查 TTL temp:token:abc123 # (integer) -2 (-2表示键已过期或不存在)