16个Redis应用场景大揭秘,你用过几个?

小熊学Java:https://javaxiaobear.cn
【2024年】编程资料大合集,年度精选资源一键收藏

今天来聊聊Redis的那些事儿,你可能不知道,Redis在我们的日常开发中有着超多的应用场景,下面我就来给大家逐一揭秘!

1. 缓存

Redis 使用 String 类型存储热点数据。
例如:热点数据缓存(例如报表、明星出轨),对象缓存、全页缓存、可以提升热点数据的访问数据。

命令:

SET hot_report:reportId 数据内容 EX 3600
GET hot_report:reportId

Java 实现:

/**
 * 缓存热点数据(例如报表、明星新闻等)
 * 
 * @param reportId 缓存的唯一标识(报表 ID)
 * @return 热点数据(从缓存或数据库加载)
 */
public String getHotData(String reportId) {
    String key = "hot_report:" + reportId; // 构造 Redis 缓存的 Key
    String data = redisUtil.get(key);     // 从 Redis 获取缓存数据
    if (data == null) {                   // 如果 Redis 缓存不存在,则从数据库查询
        data = "数据内容";                 // 模拟数据库查询
        redisUtil.set(key, data, 3600);   // 将数据存入 Redis,设置过期时间为 3600 秒
    }
    return data;
}

2. 分布式数据共享

String 类型,因为 Redis 是分布式的独立服务,可以在多个应用之间共享,使用 Redis 实现分布式 Session。

命令:

SET session:sessionId userInfo EX 3600
GET session:sessionId

Java 实现:

/**
 * 保存分布式 Session 数据
 *
 * @param sessionId 用户的 Session ID
 * @param userInfo 用户相关信息
 */
public void saveSession(String sessionId, String userInfo) {
    String key = "session:" + sessionId;  // 构造 Redis Key
    redisUtil.set(key, userInfo, 3600);   // 存入 Redis,过期时间为 1 小时
}

/**
 * 获取分布式 Session 数据
 *
 * @param sessionId 用户的 Session ID
 * @return 用户相关信息
 */
public String getSession(String sessionId) {
    String key = "session:" + sessionId;  // 构造 Redis Key
    return redisUtil.get(key);            // 从 Redis 获取用户数据
}

3. 分布式锁

Redis 利用 SETNXEXPIRE 实现分布式锁。利用Redis的SETNX命令和过期时间,可以实现分布式锁。保证多个进程或线程在访问共享资源时的互斥性,防止数据冲突。

命令:

SETNX lock:key 1
EXPIRE lock:key 10
DEL lock:key

Java 实现:

/**
 * 获取分布式锁
 *
 * @param key 锁的 Key
 * @param value 锁的唯一标识(防止误删)
 * @param timeout 锁的过期时间(秒)
 * @return 是否成功获取锁
 */
public boolean lock(String key, String value, long timeout) {
    Boolean result = redisTemplate.opsForValue().setIfAbsent(key, value, timeout, TimeUnit.SECONDS); // SETNX + EXPIRE
    return result != null && result;  // 返回是否成功加锁
}

/**
 * 释放分布式锁
 *
 * @param key 锁的 Key
 * @param value 锁的唯一标识(防止误删)
 */
public void unlock(String key, String value) {
    String currentValue = redisUtil.get(key); // 获取当前锁的值
    if (value.equals(currentValue)) {        // 确认锁是当前线程持有
        redisUtil.delete(key);               // 删除锁
    }
}

4. 全局 ID

Redis 利用 INCRBY 方法生成全局唯一 ID。Redis可以生成全局唯一的ID。通过原子操作,如INCR命令,可以生成自增ID,适用于订单号、用户ID等需要唯一标识的场景。

命令:

INCRBY userid 1000

Java 实现:

/**
 * 获取全局唯一 ID
 *
 * @param key Redis 中自增的 Key
 * @return 自增的唯一 ID
 */
public long getNextId(String key) {
    return redisUtil.increment(key, 1); // 每次调用自增 1
}

5. 计数器

int类型,incr方法

Redis 使用 INCR 实现计数功能,例如统计阅读量、点赞数。

例如:文章的阅读量、微博点赞数、允许一定的延迟,先写入Redis再定时同步到数据库

命令:

INCR article:view:articleId
GET article:view:articleId

Java 实现:

/**
 * 增加文章阅读量
 *
 * @param articleId 文章的唯一 ID
 */
public void increaseViewCount(String articleId) {
    String key = "article:view:" + articleId; // 构造 Redis Key
    redisUtil.increment(key, 1);             // 阅读量自增 1
}

/**
 * 获取文章阅读量
 *
 * @param articleId 文章的唯一 ID
 * @return 阅读量
 */
public long getViewCount(String articleId) {
    String key = "article:view:" + articleId; // 构造 Redis Key
    return Long.parseLong(redisUtil.get(key)); // 从 Redis 获取阅读量
}

6. 限流

Redis 使用 INCREXPIRE 限制单位时间内的操作次数。
以访问者的ip和其他信息作为key,访问一次增加一次计数,超过次数则返回false

利用Redis的固定窗口、滑动窗口等算法,可以实现限流功能。防止系统被过多请求压垮,如限制每个用户每秒只能访问某个接口10次。

命令:

INCR rate_limit:userId:action
EXPIRE rate_limit:userId:action 60

Java 实现:

/**
 * 判断用户是否被限流(每分钟限制 5 次)
 *
 * @param userId 用户 ID
 * @param action 限流的操作
 * @return 是否允许操作
 */
public boolean isAllowed(String userId, String action) {
    String key = "rate_limit:" + userId + ":" + action; // 构造 Redis Key
    long count = redisUtil.increment(key, 1);           // 自增计数
    if (count == 1) {
        redisTemplate.expire(key, 60, TimeUnit.SECONDS); // 如果是第一次操作,设置过期时间为 60 秒
    }
    return count <= 5; // 超过 5 次操作则限流
}

7. 在线用户统计

Redis 使用 BITMAP 记录用户在线状态。
String类型的bitcount(1.6.6的bitmap数据结构介绍)

字符是以8位二进制存储的

命令:

SETBIT online_users userId 1
BITCOUNT online_users

Java 实现:

/**
 * 标记用户为在线状态
 *
 * @param userId 用户 ID
 */
public void markOnline(String userId) {
    redisTemplate.opsForValue().setBit("online_users", Long.parseLong(userId), true); // SETBIT
}

/**
 * 获取在线用户数量
 *
 * @return 在线用户数量
 */
public long countOnlineUsers() {
    return redisTemplate.opsForValue().bitCount("online_users"); // BITCOUNT
}

8. 购物车

String 或hash。所有String可以做的hash都可以做

Redis 使用 HASH 类型实现购物车功能。

key:用户id;field:商品id;value:商品数量。

+1:hincr。-1:hdecr。删除:hdel。全选:hgetall。商品数:hlen。

命令:

HSET cart:userId productId quantity
HGETALL cart:userId

Java 实现:

/**
 * 将商品加入购物车
 *
 * @param userId 用户 ID
 * @param productId 商品 ID
 * @param quantity 商品数量
 */
public void addToCart(String userId, String productId, int quantity) {
    redisUtil.setHash("cart:" + userId, productId, String.valueOf(quantity)); // HSET
}

/**
 * 获取购物车所有商品
 *
 * @param userId 用户 ID
 * @return 商品列表
 */
public Map<Object, Object> getCart(String userId) {
    return redisTemplate.opsForHash().entries("cart:" + userId); // HGETALL
}

好的,以下是剩余部分的实现代码,包含了消息队列、点赞、签到、商品标签、筛选、推荐模型、排行榜等功能,均保留了原有 Redis 命令并添加详细注释。


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

Redis 使用 LIST 类型实现消息时间线,消息按插入顺序排列。

命令:

LPUSH timeline:userId message
LRANGE timeline:userId 0 9

Java 实现:

/**
 * 将消息加入用户时间线
 *
 * @param userId 用户 ID
 * @param message 消息内容
 */
public void addToTimeline(String userId, String message) {
    String key = "timeline:" + userId;        // 构造 Redis Key
    redisTemplate.opsForList().leftPush(key, message); // LPUSH
}

/**
 * 获取用户时间线最近的 N 条消息
 *
 * @param userId 用户 ID
 * @param count 获取的消息数量
 * @return 消息列表
 */
public List<String> getTimeline(String userId, int count) {
    String key = "timeline:" + userId;         // 构造 Redis Key
    return redisTemplate.opsForList().range(key, 0, count - 1); // LRANGE
}

10. 消息队列

List提供了两个阻塞的弹出操作:blpop/brpop,可以设置超时时间

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

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

上面的操作。其实就是java的阻塞队列。学习的东西越多。学习成本越低

  • 队列:先进先除:rpush blpop,左头右尾,右边进入队列,左边出队列

  • 栈:先进后出:rpush brpop

Redis 使用 LIST 类型实现队列功能,支持阻塞操作。

命令:

RPUSH queue:messages message
BLPOP queue:messages 0

Java 实现:

/**
 * 将消息放入消息队列
 *
 * @param message 消息内容
 */
public void enqueueMessage(String message) {
    String key = "queue:messages";           // 队列 Key
    redisTemplate.opsForList().rightPush(key, message); // RPUSH
}

/**
 * 从消息队列中取出消息(阻塞操作)
 *
 * @return 消息内容
 */
public String dequeueMessage() {
    String key = "queue:messages";           // 队列 Key
    return redisTemplate.opsForList().leftPop(key, 0, TimeUnit.SECONDS); // BLPOP
}

11. 抽奖

Redis 使用 SPOP 随机弹出集合中的元素。

命令:

SADD lottery:participants userId
SPOP lottery:participants

Java 实现:

/**
 * 添加用户到抽奖池
 *
 * @param userId 用户 ID
 */
public void addToLottery(String userId) {
    String key = "lottery:participants";    // 抽奖池 Key
    redisTemplate.opsForSet().add(key, userId); // SADD
}

/**
 * 随机抽取一位获奖者
 *
 * @return 获奖者的用户 ID
 */
public String drawWinner() {
    String key = "lottery:participants";    // 抽奖池 Key
    return redisTemplate.opsForSet().pop(key); // SPOP
}

12. 点赞、签到、打卡

假如微博ID是t1001,用户ID是u3001

用 like:t1001 来维护 t1001 这条微博的所有点赞用户

点赞了这条微博:sadd like:t1001 u3001

取消点赞:srem like:t1001 u3001

是否点赞:sismember like:t1001 u3001

点赞的所有用户:smembers like:t1001

点赞数:scard like:t1001

Redis 使用 SET 类型记录点赞用户。

命令:

SADD like:postId userId
SREM like:postId userId
SCARD like:postId

Java 实现:

/**
 * 点赞
 *
 * @param postId 帖子 ID
 * @param userId 用户 ID
 */
public void likePost(String postId, String userId) {
    String key = "like:" + postId;         // 点赞集合 Key
    redisTemplate.opsForSet().add(key, userId); // SADD
}

/**
 * 取消点赞
 *
 * @param postId 帖子 ID
 * @param userId 用户 ID
 */
public void unlikePost(String postId, String userId) {
    String key = "like:" + postId;         // 点赞集合 Key
    redisTemplate.opsForSet().remove(key, userId); // SREM
}

/**
 * 获取点赞数
 *
 * @param postId 帖子 ID
 * @return 点赞人数
 */
public long getLikes(String postId) {
    String key = "like:" + postId;         // 点赞集合 Key
    return redisTemplate.opsForSet().size(key); // SCARD
}

13. 商品标签

Redis 使用 SET 类型存储商品标签。

命令:

SADD tags:itemId tag
SMEMBERS tags:itemId

Java 实现:

/**
 * 添加商品标签
 *
 * @param itemId 商品 ID
 * @param tag 标签内容
 */
public void addTagToItem(String itemId, String tag) {
    String key = "tags:" + itemId;         // 商品标签 Key
    redisTemplate.opsForSet().add(key, tag); // SADD
}

/**
 * 获取商品的所有标签
 *
 * @param itemId 商品 ID
 * @return 标签列表
 */
public Set<String> getItemTags(String itemId) {
    String key = "tags:" + itemId;         // 商品标签 Key
    return redisTemplate.opsForSet().members(key); // SMEMBERS
}

14. 商品筛选

Redis 使用 SET 类型实现筛选功能,通过交集、并集、差集操作过滤商品。

命令:

SINTER set1 set2
SUNION set1 set2
SDIFF set1 set2

Java 实现:

/**
 * 获取多个条件筛选的交集(AND 筛选)
 *
 * @param keys 条件对应的 Key 集合
 * @return 满足条件的商品集合
 */
public Set<String> intersectKeys(String... keys) {
    return redisTemplate.opsForSet().intersect(Arrays.asList(keys)); // SINTER
}

/**
 * 获取多个条件筛选的并集(OR 筛选)
 *
 * @param keys 条件对应的 Key 集合
 * @return 满足条件的商品集合
 */
public Set<String> unionKeys(String... keys) {
    return redisTemplate.opsForSet().union(Arrays.asList(keys)); // SUNION
}

/**
 * 获取多个条件筛选的差集(NOT 筛选)
 *
 * @param keys 条件对应的 Key 集合
 * @return 满足条件的商品集合
 */
public Set<String> diffKeys(String... keys) {
    return redisTemplate.opsForSet().difference(Arrays.asList(keys)); // SDIFF
}

15. 用户关注和推荐模型

Redis 使用 SET 类型实现关注、粉丝和推荐功能。

命令:

SADD user:follow:userId targetUserId
SINTER user:follow:userId user:follow:targetUserId

Java 实现:

/**
 * 关注用户
 *
 * @param userId 当前用户 ID
 * @param targetUserId 被关注用户 ID
 */
public void followUser(String userId, String targetUserId) {
    String key = "user:follow:" + userId;  // 关注列表 Key
    redisTemplate.opsForSet().add(key, targetUserId); // SADD
}

/**
 * 获取共同关注用户(推荐好友)
 *
 * @param userId 当前用户 ID
 * @param otherUserId 其他用户 ID
 * @return 共同关注的用户集合
 */
public Set<String> getCommonFollow(String userId, String otherUserId) {
    String key1 = "user:follow:" + userId;   // 用户 1 的关注列表
    String key2 = "user:follow:" + otherUserId; // 用户 2 的关注列表
    return redisTemplate.opsForSet().intersect(key1, key2); // SINTER
}

16. 排行榜

Redis 使用 ZSET 类型实现排行榜功能。

命令:

ZINCRBY leaderboard:date score userId
ZREVRANGE leaderboard:date 0 9 WITHSCORES

Java 实现:

/**
 * 增加用户分数
 *
 * @param date 排行榜日期(如 2025-01-08)
 * @param userId 用户 ID
 * @param score 增加的分数
 */
public void increaseScore(String date, String userId, double score) {
    String key = "leaderboard:" + date;    // 排行榜 Key
    redisTemplate.opsForZSet().incrementScore(key, userId, score); // ZINCRBY
}

/**
 * 获取排行榜前 N 名
 *
 * @param date 排行榜日期(如 2025-01-08)
 * @param count 获取的排名数量
 * @return 排行榜列表(包含用户 ID 和分数)
 */
public Set<ZSetOperations.TypedTuple<String>> getTopRank(String date, int count) {
    String key = "leaderboard:" + date;   // 排行榜 Key
    return redisTemplate.opsForZSet().reverseRangeWithScores(key, 0, count - 1); // ZREVRANGE WITHSCORES
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小熊学Java

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值