找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

2849

积分

0

好友

372

主题
发表于 昨天 03:29 | 查看: 1| 回复: 0

大家好,今天我们来聊聊 Redis。作为开发者,你可能经常听到“缓存”是 Redis 的首要用途。这没错,但除了缓存,Redis 凭借其丰富的数据结构和出色的性能,在实际开发中能玩的“花样”可太多了。从简单的计数到复杂的社交关系,它都能派上用场。下面就让我们一起梳理一下 Redis 在业务中那些常见且实用的 16 个场景,并看看具体如何用代码实现。

1、缓存

这是 Redis 的“本职工作”。使用 String 类型,可以轻松实现热点数据缓存,例如经常被查询的报表数据,或者像“明星八卦”这类突发性热点新闻。此外,对象缓存、全页缓存(Full Page Cache)也都是典型的应用,能极大提升热点数据的访问速度,减轻数据库压力。

2、数据共享分布式

同样是 String 类型,由于 Redis 是一个独立的分布式服务,它可以在多个应用实例之间轻松共享数据。一个典型的例子就是分布式 Session。在 Spring 生态中,可以很方便地通过引入 spring-session-data-redis 来实现。

<dependency>
    <groupId>org.springframework.session</groupId>
    <artifactId>spring-session-data-redis</artifactId>
</dependency>

3、分布式锁

利用 String 类型的 setnx 命令,只有键不存在时才能设置成功,从而实现锁的获取。

public static boolean getLock(String key) {
    Long flag = jedis.setnx(key, "1");
    if (flag == 1) {
        jedis.expire(key, 10);
    }
    return flag == 1;
}

public static void releaseLock(String key) {
    jedis.del(key);
}

4、全局ID

利用 Integer 类型的 incrby 命令的原子性,可以生成全局唯一的递增ID。这在分库分表场景下特别有用,应用可以一次性申请一个区段(例如 incrby userid 1000),然后在本地分配,避免频繁请求 Redis。

5、计数器

使用 Integer 类型的 incr 命令。比如文章的阅读量、微博的点赞数。这类计数对实时性要求可以有一定延迟,通常是先快速写入 Redis,再通过定时任务同步到数据库。

6、限流

同样是 incr 命令,可以用于简单的限流。以访问者的 IP 和其他信息(如用户ID、接口路径)组合作为 key,访问一次计数加一。如果在规定时间内计数超过阈值,则拒绝服务。

7、位统计(Bitmap)

这是 String 类型提供的一种强大功能。字符在 Redis 中以 8 位二进制存储,我们可以操作这些二进制位。

set k1 a
setbit k1 6 1
setbit k1 7 0
get k1
/* 6 7 代表的a的二进制位的修改
a 对应的ASCII码是97,转换为二进制数据是01100001
b 对应的ASCII码是98,转换为二进制数据是01100010

因为bit非常节省空间(1 MB=8388608 bit),可以用来做大数据量的统计。
*/

例如,可以用它来做在线用户统计、留存用户分析。

setbit onlineusers 0 1
setbit onlineusers 1 1
setbit onlineusers 2 0

Bitmap 支持按位与(AND)、按位或(OR)等操作:

BITOP AND destkey key [key...] ,对一个或多个 key 求逻辑并,并将结果保存到 destkey 。      
BITOP OR destkey key [key...] ,对一个或多个 key 求逻辑或,并将结果保存到 destkey 。 
BITOP XOR destkey key [key...] ,对一个或多个 key 求逻辑异或,并将结果保存到 destkey 。 
BITOP NOT destkey key ,对给定 key 求逻辑非,并将结果保存到 destkey 。

比如,要计算出连续7天都在线的用户:

BITOP “AND” “7_days_both_online_users” “day_1_online_users” “day_2_online_users” ...  “day_7_online_users”

8、购物车

可以使用 Hash 结构来实现(String 能做的 Hash 基本都能做,且 Hash 结构更直观)。

  • Key:用户ID
  • Field:商品ID
  • Value:商品数量

购物车数据结构示意图

对应操作:

  • 增加商品数量:hincrby
  • 减少商品数量:hdecrby
  • 删除商品:hdel
  • 获取购物车所有商品:hgetall
  • 统计商品种类数:hlen

9、用户消息时间线(Timeline)

使用 List 类型,其底层是双向链表,插入有序的特性天然适合作为消息时间线。新消息通过 lpush 插入列表头部,读取时按顺序取出即可。

10、消息队列

List 提供了两个阻塞式弹出操作 blpop/brpop,可以设置超时时间,这使其能作为一个简单的消息队列。

  • blpop key1 timeout:移除并获取列表的第一个元素,如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。
  • brpop key1 timeout:移除并获取列表的最后一个元素,如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。

这其实就类似于 Java 中的阻塞队列(BlockingQueue)。概念是相通的,知识越迁移,学习成本越低。

  • 队列(先进先出)rpush(右进)结合 blpop(左出)
  • 栈(先进后出)rpush(右进)结合 brpop(右出)

11、抽奖

利用 Set 类型的 spopsrandmember 命令,可以随机返回集合中的一个或多个元素,非常适合抽奖场景。

spop myset # 随机移除并返回一个元素,可用于“抽一个奖并核销”

12、点赞、签到、打卡

使用 Set 类型来维护一个对象(如微博、帖子)的所有点赞用户。假设微博ID是 t1001,用户ID是 u3001,可以用键 like:t1001 来维护这条微博的点赞用户集合。

点赞评论互动截图

  • 点赞sadd like:t1001 u3001
  • 取消点赞srem like:t1001 u3001
  • 检查是否点过赞sismember like:t1001 u3001
  • 获取所有点赞用户smembers like:t1001
  • 获取点赞总数scard like:t1001

是不是比用数据库查询和去重要简单直观得多?

13、商品标签

同样使用 Set 类型来维护商品的所有标签。例如,商品ID i5001 的标签集合可以用 tags:i5001 来存储。

商品评价标签云

sadd tags:i5001 画面清晰细腻
sadd tags:i5001 真彩清晰显示屏
sadd tags:i5001 流程至极

14、商品筛选

Set 类型支持求交集、并集、差集,这使得多维度筛选商品变得异常高效。

// 获取差集
sdiff set1 set2
// 获取交集(intersection )
sinter set1 set2
// 获取并集
sunion set1 set2

假设新上市了 iPhone11,我们将其添加到各个维度的集合中:

商品筛选参数界面

sadd brand:apple iPhone11
sadd os:ios iPhone11
sadd screensize:6.0-6.24 iPhone11
sadd screentype:lcd iPhone11

现在,要筛选出“苹果品牌、iOS系统、屏幕尺寸在6.0-6.24英寸之间、LCD屏幕材质”的商品,只需一个命令:

sinter brand:apple os:ios screensize:6.0-6.24 screentype:lcd

15、用户关注、推荐模型

我们可以用 Set 来维护用户的关注列表(follow)和粉丝列表(fans)。

模拟用户1和用户2相互关注:

sadd 1:follow 2   # 用户1关注了用户2
sadd 2:fans 1     # 用户2的粉丝集合加入用户1
sadd 1:fans 2     # 用户1的粉丝集合加入用户2
sadd 2:follow 1   # 用户2关注了用户1

业务计算示例:

  • “我关注的人也关注了他”(取交集):
    sinter 1:follow 2:fans # 查询用户1的关注者中,有哪些人也关注了用户2
  • “可能认识的人”(取差集):
    # 用户1可能认识的人(用户2的关注者中,用户1还没关注的)
    sdiff 2:follow 1:follow
    # 用户2可能认识的人(用户1的关注者中,用户2还没关注的)
    sdiff 1:follow 2:follow

16、排行榜

使用 Sorted Set(有序集合)可以轻松实现各类排行榜。分数(score)用于排序,成员(member)是排名的对象。

例如,ID 为 6001 的新闻被点击一次:

zincrby hotNews:20190926 1 n6001

获取 2019年9月26日 点击量最高的前15条新闻:

zrevrange hotNews:20190926 0 15 withscores

热搜排行榜示意图


总结
从缓存到分布式锁,从消息队列到复杂的关系计算,Redis 的身影遍布现代应用的各个角落。它就像一个多面手,工具趁手与否,关键看开发者对它的特性理解有多深。希望这16个场景能给你带来一些启发,在实际项目中灵活运用。如果你对其中某个场景的细节有更深入的兴趣,或者想探讨其他技术话题,欢迎来 云栈社区 交流分享。




上一篇:ComfyUI 新手入门:8节点工作流从零搭建,SD1.5模型生成首张图片
下一篇:光纤端面研磨成8度角的作用:APC连接器如何降低回波损耗
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-2-5 02:02 , Processed in 0.355217 second(s), 40 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表