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
相关推荐
Victor3564 小时前
Redis(77)Redis缓存的优点和缺点是什么?
后端
摇滚侠7 小时前
Spring Boot 3零基础教程,WEB 开发 静态资源默认配置 笔记27
spring boot·笔记·后端
天若有情6739 小时前
Java Swing 实战:从零打造经典黄金矿工游戏
java·后端·游戏·黄金矿工·swin
一只叫煤球的猫9 小时前
建了索引还是慢?索引失效原因有哪些?这10个坑你踩了几个
后端·mysql·性能优化
magic3341656311 小时前
Springboot整合MinIO文件服务(windows版本)
windows·spring boot·后端·minio·文件对象存储
开心-开心急了11 小时前
Flask入门教程——李辉 第一、二章关键知识梳理(更新一次)
后端·python·flask
掘金码甲哥11 小时前
调试grpc的哼哈二将,你值得拥有
后端
小学鸡!12 小时前
Spring Boot实现日志链路追踪
java·spring boot·后端
用户214118326360213 小时前
OpenSpec 实战:用规范驱动开发破解 AI 编程协作难题
后端