Redis应用场景深度解析引言Redis作为高性能的内存数据存储系统在互联网应用中有着广泛的应用场景。本文将详细介绍Redis在缓存、会话存储、计数器、消息队列、分布式锁、排行榜、实时分析等场景的具体应用帮助开发者更好地在实际项目中应用Redis。缓存应用1.1 页面缓存import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Component; import javax.servlet.*; import javax.servlet.http.*; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.concurrent.TimeUnit; Component public class RedisPageCacheFilter implements Filter { Autowired private RedisTemplateString, Object redisTemplate; private static final String CACHE_PREFIX page:; private static final int CACHE_TTL 300; // 5分钟 Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest httpRequest (HttpServletRequest) request; HttpServletResponse httpResponse (HttpServletResponse) response; String uri httpRequest.getRequestURI(); String queryString httpRequest.getQueryString(); String cacheKey CACHE_PREFIX uri (queryString ! null ? ? queryString : ); // 检查缓存 byte[] cachedResponse (byte[]) redisTemplate.opsForValue() .get(cacheKey); if (cachedResponse ! null) { httpResponse.getOutputStream().write(cachedResponse); return; } // 包装响应以捕获输出 CachedBodyHttpServletResponse wrappedResponse new CachedBodyHttpServletResponse(httpResponse); chain.doFilter(request, wrappedResponse); // 缓存响应 byte[] body wrappedResponse.getBody(); if (body.length 0) { redisTemplate.opsForValue().set(cacheKey, body, CACHE_TTL, TimeUnit.SECONDS); } } }1.2 对象缓存public class RedisObjectCache { Autowired private RedisTemplateString, String redisTemplate; private static final String USER_PREFIX user:; private static final String CATEGORY_PREFIX category:; /** * 用户缓存 */ public void cacheUser(User user, long ttlSeconds) { String key USER_PREFIX user.getId(); redisTemplate.opsForValue().set(key, toJson(user), ttlSeconds, TimeUnit.SECONDS); } public User getCachedUser(Long userId) { String key USER_PREFIX userId; String json redisTemplate.opsForValue().get(key); return json ! null ? fromJson(json, User.class) : null; } public void invalidateUser(Long userId) { String key USER_PREFIX userId; redisTemplate.delete(key); } /** * 商品分类缓存 */ public void cacheCategories(ListCategory categories) { String key CATEGORY_PREFIX all; redisTemplate.opsForValue().set(key, toJson(categories), 1, TimeUnit.HOURS); } public ListCategory getCachedCategories() { String key CATEGORY_PREFIX all; String json redisTemplate.opsForValue().get(key); return json ! null ? fromJsonList(json, Category.class) : null; } /** * 多级缓存 */ public String getProductWithMultiLevelCache(Long productId) { // L1: 本地缓存 String localCache localCacheManager.get(product: productId); if (localCache ! null) { return localCache; } // L2: Redis缓存 String key product: productId; String cached redisTemplate.opsForValue().get(key); if (cached ! null) { // 回填本地缓存 localCacheManager.put(key, cached, 60, TimeUnit.SECONDS); return cached; } // L3: 数据库 Product product productService.getProduct(productId); String productJson toJson(product); // 回填Redis缓存 redisTemplate.opsForValue().set(key, productJson, 30, TimeUnit.MINUTES); return productJson; } }会话存储2.1 分布式会话import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.session.web.http.CookieSerializer; import org.springframework.session.web.http.DefaultCookieSerializer; Configuration EnableRedisHttpSession( maxInactiveIntervalInSeconds 1800, // 30分钟 redisNamespace spring:session ) public class RedisSessionConfig { Bean public CookieSerializer cookieSerializer() { DefaultCookieSerializer serializer new DefaultCookieSerializer(); serializer.setCookieName(SESSIONID); serializer.setCookiePath(/); serializer.setDomainNamePattern(^.?\\.(\\w\\.[a-z])$); serializer.setUseHttpOnlyCookie(true); serializer.setUseSecureCookie(true); return serializer; } }2.2 自定义会话管理public class RedisSessionManager { Autowired private RedisTemplateString, Object redisTemplate; private static final String SESSION_PREFIX session:; private static final int SESSION_TTL 1800; // 30分钟 /** * 创建会话 */ public String createSession(String userId, MapString, Object attributes) { String sessionId UUID.randomUUID().toString(); String key SESSION_PREFIX sessionId; MapString, Object sessionData new HashMap(); sessionData.put(userId, userId); sessionData.put(createdAt, System.currentTimeMillis()); sessionData.put(attributes, attributes); redisTemplate.opsForHash().putAll(key, sessionData); redisTemplate.expire(key, SESSION_TTL, TimeUnit.SECONDS); return sessionId; } /** * 获取会话 */ public MapObject, Object getSession(String sessionId) { String key SESSION_PREFIX sessionId; MapObject, Object session redisTemplate.opsForHash() .entries(key); if (!session.isEmpty()) { // 刷新过期时间 redisTemplate.expire(key, SESSION_TTL, TimeUnit.SECONDS); } return session; } /** * 更新会话属性 */ public void updateSession(String sessionId, String attribute, Object value) { String key SESSION_PREFIX sessionId; redisTemplate.opsForHash().put(key, attribute, value); redisTemplate.expire(key, SESSION_TTL, TimeUnit.SECONDS); } /** * 删除会话 */ public void destroySession(String sessionId) { String key SESSION_PREFIX sessionId; redisTemplate.delete(key); } /** * 校验会话 */ public boolean validateSession(String sessionId) { String key SESSION_PREFIX sessionId; return Boolean.TRUE.equals(redisTemplate.hasKey(key)); } }计数器应用3.1 访问计数器public class AccessCounter { Autowired private RedisTemplateString, String redisTemplate; private static final String DAILY_PREFIX counter:daily:; private static final String MONTHLY_PREFIX counter:monthly:; private static final String PAGE_PREFIX counter:page:; /** * 页面访问计数 */ public void incrementPageView(String pageId) { String dailyKey DAILY_PREFIX getToday() : pageId; String monthlyKey MONTHLY_PREFIX getCurrentMonth() : pageId; String pageKey PAGE_PREFIX pageId; redisTemplate.opsForValue().increment(dailyKey); redisTemplate.opsForValue().increment(monthlyKey); redisTemplate.opsForValue().increment(pageKey); // 设置过期时间 redisTemplate.expire(dailyKey, 2, TimeUnit.DAYS); redisTemplate.expire(monthlyKey, 35, TimeUnit.DAYS); } /** * 获取日访问量 */ public long getDailyPV(String pageId, String date) { String key DAILY_PREFIX date : pageId; String value redisTemplate.opsForValue().get(key); return value ! null ? Long.parseLong(value) : 0; } /** * 获取月访问量 */ public long getMonthlyPV(String pageId, String yearMonth) { String key MONTHLY_PREFIX yearMonth : pageId; String value redisTemplate.opsForValue().get(key); return value ! null ? Long.parseLong(value) : 0; } /** * 获取总访问量 */ public long getTotalPV(String pageId) { String key PAGE_PREFIX pageId; String value redisTemplate.opsForValue().get(key); return value ! null ? Long.parseLong(value) : 0; } /** * 批量获取统计数据 */ public MapString, Long getPageStatistics(ListString pageIds) { ListString dailyKeys pageIds.stream() .map(id - DAILY_PREFIX getToday() : id) .collect(Collectors.toList()); ListString values redisTemplate.opsForValue().multiGet(dailyKeys); MapString, Long stats new HashMap(); for (int i 0; i pageIds.size(); i) { String value values.get(i); stats.put(pageIds.get(i), value ! null ? Long.parseLong(value) : 0); } return stats; } }3.2 用户行为统计public class UserBehaviorStatistics { Autowired private RedisTemplateString, Object redisTemplate; private static final String UV_PREFIX uv:daily:; private static final String ACTION_PREFIX action:user:; /** * 记录日活跃用户 */ public void recordDailyUV(String date, String userId) { String key UV_PREFIX date; redisTemplate.opsForSet().add(key, userId); } /** * 获取日活跃用户数 */ public long getDailyUV(String date) { String key UV_PREFIX date; return redisTemplate.opsForSet().size(key); } /** * 记录用户行为 */ public void recordUserAction(String userId, String actionType) { String key ACTION_PREFIX userId : actionType; redisTemplate.opsForValue().increment(key); redisTemplate.expire(key, 30, TimeUnit.DAYS); } /** * 获取用户行为统计 */ public MapString, Long getUserActions(String userId, ListString actionTypes) { MapString, Long actions new HashMap(); for (String actionType : actionTypes) { String key ACTION_PREFIX userId : actionType; String value redisTemplate.opsForValue().get(key); actions.put(actionType, value ! null ? Long.parseLong(value) : 0); } return actions; } /** * 实时统计指标 */ public MapString, Object getRealtimeMetrics() { MapString, Object metrics new HashMap(); // 获取当前在线用户数 String onlineKey online:users; metrics.put(onlineUsers, redisTemplate.opsForSet().size(onlineKey)); // 获取今日新增用户 String today getToday(); metrics.put(todayNewUsers, redisTemplate.opsForHyperLogLog().size(newusers: today)); // 获取今日PV metrics.put(todayPV, getDailyTotalPV(today)); return metrics; } private long getDailyTotalPV(String date) { SetString keys redisTemplate.keys(DAILY_PREFIX date :*); long total 0; if (keys ! null) { for (String key : keys) { String value redisTemplate.opsForValue().get(key); if (value ! null) { total Long.parseLong(value); } } } return total; } }分布式锁4.1 基础分布式锁public class RedisDistributedLock { Autowired private RedisTemplateString, String redisTemplate; private static final String LOCK_PREFIX lock:; private static final long DEFAULT_EXPIRE_TIME 30000; // 30秒 /** * 获取锁 */ public boolean tryLock(String resource, String lockValue) { return tryLock(resource, lockValue, DEFAULT_EXPIRE_TIME, TimeUnit.MILLISECONDS); } public boolean tryLock(String resource, String lockValue, long expireTime, TimeUnit unit) { String key LOCK_PREFIX resource; long expireMs unit.toMillis(expireTime); Boolean result redisTemplate.opsForValue() .setIfAbsent(key, lockValue, expireTime, unit); return Boolean.TRUE.equals(result); } /** * 释放锁 */ public boolean releaseLock(String resource, String lockValue) { String key LOCK_PREFIX resource; String currentValue redisTemplate.opsForValue().get(key); if (lockValue.equals(currentValue)) { redisTemplate.delete(key); return true; } return false; } /** * 加锁并执行操作 */ public T T executeWithLock(String resource, SupplierT operation) { String lockValue UUID.randomUUID().toString(); try { while (!tryLock(resource, lockValue)) { Thread.sleep(100); } return operation.get(); } finally { releaseLock(resource, lockValue); } } }4.2 可重入分布式锁public class RedisReentrantLock { Autowired private RedisTemplateString, String redisTemplate; private ThreadLocalString lockValueHolder new ThreadLocal(); private ThreadLocalInteger lockCountHolder ThreadLocal.withInitial(() - 0); public boolean tryLock(String resource) { return tryLock(resource, 30000, TimeUnit.MILLISECONDS); } public boolean tryLock(String resource, long timeout, TimeUnit unit) { String lockValue lockValueHolder.get(); if (lockValue null) { lockValue Thread.currentThread().getId() : UUID.randomUUID().toString(); lockValueHolder.set(lockValue); } String key lock: resource; long expireMs unit.toMillis(timeout); Boolean result redisTemplate.opsForValue() .setIfAbsent(key, lockValue, expireMs, unit); if (Boolean.TRUE.equals(result)) { lockCountHolder.set(lockCountHolder.get() 1); return true; } return false; } public void unlock(String resource) { int count lockCountHolder.get(); if (count 1) { lockCountHolder.set(count - 1); return; } lockCountHolder.remove(); lockValueHolder.remove(); String key lock: resource; redisTemplate.delete(key); } }消息队列5.1 延迟队列import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.UUID; import java.util.function.Consumer; public class RedisDelayQueue { Autowired private RedisTemplateString, String redisTemplate; private static final String DELAY_QUEUE delay:queue:; private static final String READY_QUEUE delay:ready:; /** * 添加延迟任务 */ public String addDelayTask(String queue, String message, long delayMs) { String taskId UUID.randomUUID().toString(); long executeTime System.currentTimeMillis() delayMs; String scoreKey String.valueOf(executeTime); String value taskId : message; redisTemplate.opsForZSet().add(DELAY_QUEUE queue, value, executeTime); return taskId; } /** * 消费延迟任务 */ public void consumeDelayTasks(String queue, ConsumerString handler, int batchSize) { long now System.currentTimeMillis(); SetString tasks redisTemplate.opsForZSet() .rangeByScore(DELAY_QUEUE queue, 0, now, 0, batchSize); for (String task : tasks) { // 原子性删除 Long removed redisTemplate.opsForZSet() .remove(DELAY_QUEUE queue, task); if (removed 0) { String[] parts task.split(:, 2); String message parts.length 1 ? parts[1] : ; handler.accept(message); } } } /** * 取消延迟任务 */ public boolean cancelDelayTask(String queue, String taskId) { SetString tasks redisTemplate.opsForZSet() .rangeByScore(DELAY_QUEUE queue, 0, Double.MAX_VALUE); for (String task : tasks) { if (task.startsWith(taskId :)) { redisTemplate.opsForZSet() .remove(DELAY_QUEUE queue, task); return true; } } return false; } }5.2 优先级队列public class RedisPriorityQueue { Autowired private RedisTemplateString, String redisTemplate; private static final String QUEUE_PREFIX priority:queue:; /** * 入队按优先级 */ public void enqueue(String queue, String element, int priority) { String key QUEUE_PREFIX queue; // 优先级转换为排序分数优先级越高分数越小 double score Integer.MAX_VALUE - priority; redisTemplate.opsForZSet().add(key, element, score); } /** * 出队最高优先级 */ public String dequeue(String queue) { String key QUEUE_PREFIX queue; // 获取并移除最高优先级元素 SetString result redisTemplate.opsForZSet() .rangeByRank(key, 0, 0); if (!result.isEmpty()) { String element result.iterator().next(); redisTemplate.opsForZSet().remove(key, element); return element; } return null; } /** * 阻塞出队 */ public String blockingDequeue(String queue, long timeout, TimeUnit unit) throws InterruptedException { long startTime System.currentTimeMillis(); long timeoutMs unit.toMillis(timeout); while (System.currentTimeMillis() - startTime timeoutMs) { String element dequeue(queue); if (element ! null) { return element; } Thread.sleep(100); } return null; } /** * 查看队首元素 */ public String peek(String queue) { String key QUEUE_PREFIX queue; SetString result redisTemplate.opsForZSet() .rangeByRank(key, 0, 0); return result.isEmpty() ? null : result.iterator().next(); } /** * 获取队列大小 */ public long size(String queue) { String key QUEUE_PREFIX queue; Long size redisTemplate.opsForZSet().size(key); return size ! null ? size : 0; } }排行榜应用6.1 综合排行榜public class RedisLeaderboard { Autowired private RedisTemplateString, String redisTemplate; private static final String LEADERBOARD_PREFIX leaderboard:; /** * 更新用户分数 */ public void updateScore(String leaderboard, String userId, double score) { String key LEADERBOARD_PREFIX leaderboard; redisTemplate.opsForZSet().add(key, userId, score); } /** * 获取用户排名从高到低0开始 */ public Long getUserRank(String leaderboard, String userId) { String key LEADERBOARD_PREFIX leaderboard; return redisTemplate.opsForZSet().reverseRank(key, userId); } /** * 获取用户分数 */ public Double getUserScore(String leaderboard, String userId) { String key LEADERBOARD_PREFIX leaderboard; return redisTemplate.opsForZSet().score(key, userId); } /** * 获取Top N */ public ListLeaderboardEntry getTopN(String leaderboard, int n) { String key LEADERBOARD_PREFIX leaderboard; SetZSetOperations.TypedTupleString topN redisTemplate.opsForZSet().reverseRangeWithScores(key, 0, n - 1); ListLeaderboardEntry entries new ArrayList(); int rank 1; for (ZSetOperations.TypedTupleString entry : topN) { entries.add(new LeaderboardEntry( rank, entry.getValue(), entry.getScore() )); } return entries; } /** * 获取用户周围的排名 */ public ListLeaderboardEntry getUserNeighbors(String leaderboard, String userId, int range) { String key LEADERBOARD_PREFIX leaderboard; Long userRank redisTemplate.opsForZSet().reverseRank(key, userId); if (userRank null) { return Collections.emptyList(); } long start Math.max(0, userRank - range); long end userRank range; SetZSetOperations.TypedTupleString neighbors redisTemplate.opsForZSet().reverseRangeWithScores(key, start, end); ListLeaderboardEntry entries new ArrayList(); int rank (int) start 1; for (ZSetOperations.TypedTupleString entry : neighbors) { entries.add(new LeaderboardEntry( rank, entry.getValue(), entry.getScore() )); } return entries; } /** * 增加分数 */ public void incrementScore(String leaderboard, String userId, double delta) { String key LEADERBOARD_PREFIX leaderboard; redisTemplate.opsForZSet().incrementScore(key, userId, delta); } /** * 获取指定分数段的排名 */ public ListLeaderboardEntry getByScoreRange(String leaderboard, double minScore, double maxScore, int limit) { String key LEADERBOARD_PREFIX leaderboard; SetZSetOperations.TypedTupleString entries redisTemplate.opsForZSet() .reverseRangeByScoreWithScores(key, minScore, maxScore, 0, limit); return convertToEntries(entries); } private ListLeaderboardEntry convertToEntries( SetZSetOperations.TypedTupleString tuples) { ListLeaderboardEntry entries new ArrayList(); int rank 1; for (ZSetOperations.TypedTupleString tuple : tuples) { entries.add(new LeaderboardEntry( rank, tuple.getValue(), tuple.getScore() )); } return entries; } public static class LeaderboardEntry { private int rank; private String userId; private double score; public LeaderboardEntry(int rank, String userId, double score) { this.rank rank; this.userId userId; this.score score; } public int getRank() { return rank; } public String getUserId() { return userId; } public double getScore() { return score; } } }实时分析7.1 滑动窗口统计public class SlidingWindowStatistics { Autowired private RedisTemplateString, String redisTemplate; /** * 滑动窗口计数 */ public void recordEvent(String eventType, String eventId) { String key sliding: eventType : getCurrentMinute(); redisTemplate.opsForSet().add(key, eventId); } /** * 获取滑动窗口内的事件数 */ public long getEventCount(String eventType, int windowMinutes) { long currentMinute getCurrentMinute(); long total 0; for (int i 0; i windowMinutes; i) { String key sliding: eventType : (currentMinute - i); Long size redisTemplate.opsForSet().size(key); total size ! null ? size : 0; } return total; } /** * 滑动窗口限流 */ public boolean isAllowed(String userId, int maxRequests, int windowMinutes) { String key ratelimit: userId : getCurrentMinute(); Long count redisTemplate.opsForValue().increment(key); if (count 1) { redisTemplate.expire(key, windowMinutes * 60, TimeUnit.SECONDS); } return count maxRequests; } private long getCurrentMinute() { return System.currentTimeMillis() / 60000; } }7.2 实时聚合统计public class RealtimeAggregation { Autowired private RedisTemplateString, String redisTemplate; /** * 记录实时指标 */ public void recordMetric(String metricName, String dimension, double value) { String countKey metric: metricName : dimension :count; String sumKey metric: metricName : dimension :sum; String minKey metric: metricName : dimension :min; String maxKey metric: metricName : dimension :max; redisTemplate.opsForValue().increment(countKey); redisTemplate.opsForValue().increment(sumKey, value); // 更新最小值 redisTemplate.opsForZSet().add(minKey, current, value); // 更新最大值 redisTemplate.opsForZSet().add(maxKey, current, value); // 设置过期时间 String today LocalDate.now().format(DateTimeFormatter.BASIC_ISO_DATE); redisTemplate.expire(countKey, 2, TimeUnit.DAYS); redisTemplate.expire(sumKey, 2, TimeUnit.DAYS); redisTemplate.expire(minKey, 2, TimeUnit.DAYS); redisTemplate.expire(maxKey, 2, TimeUnit.DAYS); } /** * 获取实时统计 */ public MapString, Double getMetricStats(String metricName, String dimension) { MapString, Double stats new HashMap(); String countKey metric: metricName : dimension :count; String sumKey metric: metricName : dimension :sum; String countStr redisTemplate.opsForValue().get(countKey); String sumStr redisTemplate.opsForValue().get(sumKey); long count countStr ! null ? Long.parseLong(countStr) : 0; double sum sumStr ! null ? Double.parseDouble(sumStr) : 0; stats.put(count, (double) count); stats.put(sum, sum); stats.put(avg, count 0 ? sum / count : 0); return stats; } }总结Redis凭借其丰富的数据结构和高性能特性在互联网应用中有着广泛的应用场景。本文详细介绍了Redis在缓存、会话存储、计数器、分布式锁、消息队列、排行榜、实时分析等场景的具体应用。合理使用Redis能够显著提升系统性能和用户体验同时也需要注意数据一致性和持久化等问题。