首页>软件资讯>常见问题

常见问题

工作中Redis的15种使用场景

发布时间:2025-02-20 20:11:27人气:100


1. 缓存

Redis最常见的用途是作为缓存,用于加速应用程序的响应速度。


把频繁访问的数据放在内存中,可以减少对后端数据库的访问压力。如热点数据缓存(明星出轨),对象缓存、全页缓存、可以提升热点数据的访问速度。


SET user:1001 "{name: 'Alice', age: 30}" EX 3600  #设置1小时过期时间


2.分布式锁

日常开发中,我们经常会使用Redis做为分布式锁。可以在分布式系统中协调多节点对共享资源的访问,确保操作的原子性。


之前用redisson写了个分布式锁模板,大家可以看一下哈:


   public <T> T executeWithLock(String lockKey, long timeout, Callable<T> action) {

        RLock lock = redissonClient.getLock(lockKey);

        boolean isLock = false;


        try {

            // 尝试获取锁,最大等待时间1秒,锁自动释放时间为timeout秒

            isLock = lock.tryLock(1, timeout, TimeUnit.SECONDS);

            if (isLock) {

                try {

                    // 执行传入的操作并返回结果

                    return action.call();

                } finally {

                    // 检查是否持有锁再释放

                    if (lock.isHeldByCurrentThread()) {

                        lock.unlock();

                    }

                }

            } else {

                System.out.println("未能获取锁,稍后重试");

                return null; // 或者抛出异常

            }

        } catch (InterruptedException e) {

            // 处理异常,恢复线程中断状态

            Thread.currentThread().interrupt();

            System.out.println("获取锁时被中断");

            return null; // 或者抛出异常

        } catch (Exception e) {

            // 处理其他异常

            System.out.println("执行操作时发生异常: " + e.getMessage());

            return null; // 或者抛出异常

        }

    }

3. 排行榜

redis 经常用来做排行榜,比如游戏积分实时排名、直播送礼排名等等。


可以基于Sorted Set来实现:


实时排名更新:


ZADD game_leaderboard 1000 "player_1"  # 插入分数

ZINCRBY game_leaderboard 50 "player_1" # 增加分数

ZREVRANGE game_leaderboard 0 9 WITHSCORES  # 获取Top10

4. 计数器

redis 也经常应用作为计数器,如文章的阅读量、微博点赞数等等。


# 用户 1001 点赞文章 123

SADD article:123:likes 1001


# 获取文章 123 的点赞数

SCARD article:123:likes


# 检查用户 1001 是否点赞了文章 123

SISMEMBER article:123:likes 1001


# 用户 1001 取消点赞文章 123

SREM article:123:likes 1001

5. 消息队列

Redis 可以作为消息队列使用,特别是使用其 List 数据结构以及相关的阻塞操作(BLPOP 和 BRPOP)。这些操作使得 Redis 成为一种简单、高效的消息队列解决方案,广泛用于消息传递、任务队列等场景。


假设你有一个队列 task_queue:


生产者(Producer)向队列中添加任务:


bash

LPUSH task_queue "task1"

LPUSH task_queue "task2"

消费者(Consumer)从队列中取出任务,设置超时为 5 秒:


bash

BLPOP task_queue 5

6.会话管理

Redis 非常适合用作 会话管理,尤其是在分布式应用中。


分布式会话:解决多服务器间 Session 共享问题。

快速失效:通过 EXPIRE 实现自动会话清理。

HSET session:abBitmapc123 user_id 1001 last_active 1690000000

EXPIRE session:abc123 1800  # 30分钟过期

7. Bitmap 记录签到

Redis Bitmap是一种非常适合用于签到系统的数据结构。它通过位图(bit array)存储和操作数据,可以高效地处理大量的签到操作,特别适合于需要频繁更新并查询某个用户是否已签到的场景。


假设每个用户的签到状态通过 位图(Bitmap) 记录,每个用户对应一个唯一的 ID,通过设置和查询位来确定该用户是否签到。


设置用户 101 已签到

SETBIT sign_in_bitmap 101 1


比如查询用户 ID 为 101 的签到状态

GETBIT sign_in_bitmap 101


统计总共有多少用户已签到

BITCOUNT sign_in_bitmap

8. 地理位置服务

Redis 可以作为地理位置服务(Geolocation Service)的存储和查询引擎。Redis 提供了 GEO 数据结构,专门用于存储和查询地理位置信息。


比如类似场景:


用户打开 App,查找当前位置附近的餐厅或商店。


# 添加餐厅地理位置

GEOADD restaurants 13.361389 38.115556 "餐厅A"

GEOADD restaurants 15.087269 37.502669 "餐厅B"

GEOADD restaurants 9.191383 45.464211 "餐厅C"


# 用户当前位置:经纬度 (14, 37)

# 查找附近 100 公里内的餐厅

GEORADIUS restaurants 14 37 100 km

# 返回:餐厅A 餐厅B

9. 限流

Redis 适合用于限流(Rate Limiting)场景。限流的目的是控制某个操作在特定时间内的访问频率,比如 API 请求、短信发送、登录尝试等。Redis 的原子操作和高效性能使其成为实现限流的理想工具。


比如使用 Redis 实现滑动窗口计数器


使用 Redis 的 ZSET(有序集合)存储每次请求的时间戳。

每次请求时,移除时间窗口外的旧记录,并添加新记录。

统计当前时间窗口内的记录数,如果超过阈值则拒绝请求。

def sliding_window_rate_limit(user_id, limit=10, window_size=60):

    """

    滑动窗口限流函数

    :param user_id: 用户 ID

    :param limit: 时间窗口内的最大请求数

    :param window_size: 时间窗口大小(秒)

    :return: True(允许请求)或 False(拒绝请求)

    """

    key = f"rate_limit:{user_id}"

    current_time = int(time.time())

    window_start = current_time - window_size


    # 移除时间窗口外的旧记录

    redis_client.zremrangebyscore(key, 0, window_start)


    # 添加当前请求的时间戳

    redis_client.zadd(key, {current_time: current_time})


    # 统计时间窗口内的请求数

    request_count = redis_client.zcard(key)


    if request_count > limit:

        return False  # 超过阈值,拒绝请求

    return True  # 允许请求


# 测试滑动窗口限流

user_id = "user123"

for i in range(15):

    if sliding_window_rate_limit(user_id, limit=10, window_size=60):

        print(f"请求 {i + 1}:允许")

    else:

        print(f"请求 {i + 1}:拒绝")

    time.sleep(1)  # 模拟请求间隔

10. 发布订阅

实时消息广播


# 订阅频道

SUBSCRIBE news_updates


# 发布消息

PUBLISH news_updates "Breaking: Redis 7.0 released!"

11. 延迟任务(Delayed Task)

Redis 可以作为延迟任务的实现工具。


基于 Sorted Set 的延迟任务。

利用 Sorted Set 的 有序性 和 范围查询 特性,将任务的执行时间作为分数(score),任务数据作为成员(member),定时轮询获取到期的任务。


-- 添加延迟任务:

ZADD delayed_tasks <timestamp> "task_data"

-- 定时轮询获取到期任务

ZRANGEBYSCORE delayed_tasks 0 <current_timestamp>

12.全局ID

在分布式系统中生成唯一ID。


基于 INCR:


INCR global_id  # 返回唯一ID

基于雪花算法:


SET global_id_snowflake 0

INCR global_id_snowflake

13. 推荐模型

基于用户行为推荐商品。


基于Sorted Set:


ZADD recommendations:user1001 0.9 "product_1" 0.8 "product_2"

ZRANGE recommendations:user1001 0 9 WITHSCORES

14. 用户关注

之前在第一个公司上班的时候,看到代码,有使用redis去维护用户关注、粉丝的关系。


SADD user:1001:followers "user2"

SADD user:1002:following "user1"

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

Redis适合实现用户消息时间线(Timeline)功能.用户消息时间线通常用于展示用户动态、朋友圈、微博等场景,核心需求是按时间顺序存储和展示用户的相关消息或动态。


-- 使用 LPUSH 将新消息插入到时间线的头部:

LPUSH timeline:user1001 "New post: Hello, Redis!"


-- 使用 LRANGE 获取指定范围内的消息:

LRANGE timeline:user1001 0 9  # 获取最新的10条消息




上一条:Gurobi Quicksum添加条件:高效优化你的模型

下一条:Redis入门指南简单易懂