Redis(76)Redis作为缓存的常见使用场景有哪些?

Redis作为缓存的常见使用场景包括数据库查询缓存、会话管理、分布式锁、缓存热点数据、计数器和限流等。以下是详细的说明和代码示例:

1. 数据库查询缓存

数据库查询缓存是最常见的使用场景之一,缓存数据库查询结果以减少直接访问数据库的频率,从而提升系统性能。

示例代码:

java 复制代码
import redis.clients.jedis.Jedis;
import com.fasterxml.jackson.databind.ObjectMapper;

public class DatabaseQueryCache {
    private Jedis jedis;
    private static final ObjectMapper objectMapper = new ObjectMapper();

    public DatabaseQueryCache(Jedis jedis) {
        this.jedis = jedis;
    }

    public <T> T getCachedData(String key, Class<T> clazz, DataProvider<T> provider, int cacheTime) {
        try {
            // 尝试从缓存中获取数据
            String cacheValue = jedis.get(key);
            if (cacheValue != null) {
                return objectMapper.readValue(cacheValue, clazz);
            }

            // 如果缓存中没有数据,则从数据源中获取数据
            T data = provider.getData();
            // 将数据序列化后存储到缓存中,并设置缓存过期时间
            jedis.setex(key, cacheTime, objectMapper.writeValueAsString(data));
            return data;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    public interface DataProvider<T> {
        T getData();
    }

    public static void main(String[] args) {
        Jedis jedis = new Jedis("localhost", 6379);
        DatabaseQueryCache cache = new DatabaseQueryCache(jedis);

        String userId = "123";
        String cacheKey = "user:" + userId;
        int cacheTime = 3600; // 缓存 1 小时

        User user = cache.getCachedData(cacheKey, User.class, () -> {
            // 模拟从数据库查询用户数据
            return getUserFromDatabase(userId);
        }, cacheTime);

        System.out.println("User: " + user);
        jedis.close();
    }

    private static User getUserFromDatabase(String userId) {
        // 模拟数据库查询
        User user = new User();
        user.setId(userId);
        user.setName("John Doe");
        user.setEmail("john.doe@example.com");
        return user;
    }

    static class User {
        private String id;
        private String name;
        private String email;

        // Getters and Setters

        @Override
        public String toString() {
            return "User{id='" + id + "', name='" + name + "', email='" + email + "'}";
        }
    }
}

2. 会话管理

将用户会话信息存储在Redis中,以实现分布式会话管理。这样可以在多个服务器之间共享会话信息,提高系统的可扩展性和高可用性。

示例代码:

java 复制代码
import redis.clients.jedis.Jedis;

import java.util.UUID;

public class SessionManager {
    private Jedis jedis;

    public SessionManager(Jedis jedis) {
        this.jedis = jedis;
    }

    public String createSession(String userId) {
        String sessionId = UUID.randomUUID().toString();
        String key = "session:" + sessionId;
        jedis.hset(key, "userId", userId);
        jedis.expire(key, 3600); // 会话过期时间为1小时
        return sessionId;
    }

    public String getUserIdBySessionId(String sessionId) {
        String key = "session:" + sessionId;
        return jedis.hget(key, "userId");
    }

    public void destroySession(String sessionId) {
        String key = "session:" + sessionId;
        jedis.del(key);
    }

    public static void main(String[] args) {
        Jedis jedis = new Jedis("localhost", 6379);
        SessionManager sessionManager = new SessionManager(jedis);

        // 创建会话
        String sessionId = sessionManager.createSession("user123");
        System.out.println("Session created: " + sessionId);

        // 获取用户ID
        String userId = sessionManager.getUserIdBySessionId(sessionId);
        System.out.println("User ID: " + userId);

        // 销毁会话
        sessionManager.destroySession(sessionId);
        System.out.println("Session destroyed.");

        jedis.close();
    }
}

3. 分布式锁

Redis提供了便捷的分布式锁功能,用于在分布式系统中实现互斥访问共享资源。

示例代码:

java 复制代码
import redis.clients.jedis.Jedis;
import redis.clients.jedis.params.SetParams;

public class RedisDistributedLock {
    private Jedis jedis;
    private String lockKey;
    private String lockValue;
    private int expireTime;

    public RedisDistributedLock(Jedis jedis, String lockKey, int expireTime) {
        this.jedis = jedis;
        this.lockKey = lockKey;
        this.expireTime = expireTime;
        this.lockValue = String.valueOf(Thread.currentThread().getId());
    }

    public boolean acquireLock() {
        SetParams params = new SetParams().nx().px(expireTime);
        String result = jedis.set(lockKey, lockValue, params);
        return "OK".equals(result);
    }

    public boolean releaseLock() {
        String luaScript = "if redis.call('get', KEYS[1]) == ARGV[1] then " +
                           "return redis.call('del', KEYS[1]) else return 0 end";
        Object result = jedis.eval(luaScript, 1, lockKey, lockValue);
        return result.equals(1L);
    }

    public void executeWithLock(Runnable task) {
        if (acquireLock()) {
            try {
                task.run();
            } finally {
                boolean released = releaseLock();
                if (!released) {
                    System.out.println("Failed to release lock.");
                }
            }
        } else {
            System.out.println("Failed to acquire lock, try again later.");
        }
    }

    public static void main(String[] args) {
        Jedis jedis = new Jedis("localhost", 6379);
        RedisDistributedLock lock = new RedisDistributedLock(jedis, "resource_lock", 10000);

        lock.executeWithLock(() -> {
            System.out.println("Executing critical section.");
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
            System.out.println("Critical section completed.");
        });

        jedis.close();
    }
}

4. 缓存热点数据

将频繁访问的热点数据缓存到Redis中,以提高响应速度和系统吞吐量。

示例代码:

java 复制代码
import redis.clients.jedis.Jedis;

import java.util.HashMap;
import java.util.Map;

public class HotDataCache {
    private Jedis jedis;

    public HotDataCache(Jedis jedis) {
        this.jedis = jedis;
    }

    public Map<String, String> getHotData(String key) {
        Map<String, String> data = jedis.hgetAll(key);
        if (data.isEmpty()) {
            data = fetchDataFromDatabase(key);
            jedis.hmset(key, data);
            jedis.expire(key, 3600); // 设置缓存过期时间1小时
        }
        return data;
    }

    private Map<String, String> fetchDataFromDatabase(String key) {
        // 模拟从数据库获取热点数据
        Map<String, String> data = new HashMap<>();
        data.put("field1", "value1");
        data.put("field2", "value2");
        return data;
    }

    public static void main(String[] args) {
        Jedis jedis = new Jedis("localhost", 6379);
        HotDataCache cache = new HotDataCache(jedis);

        String key = "hot_data:123";
        Map<String, String> data = cache.getHotData(key);
        System.out.println("Hot data: " + data);

        jedis.close();
    }
}

5. 计数器和限流

使用Redis的原子操作实现计数器和限流功能,如实现API请求限流、访问计数等。

示例代码:

java 复制代码
import redis.clients.jedis.Jedis;

public class RateLimiter {
    private Jedis jedis;
    private String key;
    private int limit;
    private int expireTime;

    public RateLimiter(Jedis jedis, String key, int limit, int expireTime) {
        this.jedis = jedis;
        this.key = key;
        this.limit = limit;
        this.expireTime = expireTime;
    }

    public boolean isAllowed() {
        long count = jedis.incr(key);
        if (count == 1) {
            jedis.expire(key, expireTime); // 设置过期时间
        }
        return count <= limit;
    }

    public static void main(String[] args) {
        Jedis jedis = new Jedis("localhost", 6379);
        RateLimiter limiter = new RateLimiter(jedis, "api_rate_limiter", 100, 60); // 每分钟限制100次请求

        for (int i = 0; i < 120; i++) {
            if (limiter.isAllowed()) {
                System.out.println("Request " + (i + 1) + ": allowed");
            } else {
                System.out.println("Request " + (i
相关推荐
rannn_1114 分钟前
【SQL题解】力扣高频 SQL 50题|DAY5
数据库·后端·sql·leetcode·题解
+VX:Fegn089510 分钟前
计算机毕业设计|基于springboot + vue健康茶饮销售管理系统(源码+数据库+文档)
数据库·vue.js·spring boot·后端·课程设计
陈橘又青21 分钟前
vLLM-Ascend推理部署与性能调优深度实战指南:架构解析、环境搭建与核心配置
人工智能·后端·ai·架构·restful·数据·vllm
ChineHe26 分钟前
Gin框架基础篇004_中间件的使用与机制详解
后端·golang·gin
serendipity_hky27 分钟前
【go语言 | 第6篇】Go Modules 依赖解决
开发语言·后端·golang
weixin_425023001 小时前
Spring boot 2.7.18使用knife4j
java·spring boot·后端
IT_陈寒1 小时前
Python性能翻倍的5个隐藏技巧:让你的代码跑得比同事快50%
前端·人工智能·后端
最贪吃的虎1 小时前
Spring Boot 自动装配(Auto-Configuration)深度实现原理全解析
java·运维·spring boot·后端·mysql
Ahuuua1 小时前
Spring Bean作用域深度解析
java·后端·spring