开篇:Redis的隐藏技能树
"又双叒叕是缓存击穿?" "Redis不就是个缓存吗?" "为啥这个功能还要用Redis实现?"
如果你的团队里还有人这么想,那这篇文章就是为他们准备的!Redis不仅仅是一个缓存工具,它简直就是一把瑞士军刀,能解决你想象不到的各种问题。
今天就带你解锁Redis的16种神仙用法,让你的同事看完直呼:"牛啊,原来Redis还能这么玩!"
本文将通过16个实战场景,配合完整可用的代码示例,带你全面解锁Redis的神级用法。
从分布式锁到实时排行榜,从用户关系网络到高性能计数器,每一个场景都经过生产环境验证,代码可以直接复制到项目中使用。
看完这篇文章,你将获得:
- 16个Redis高级应用场景的完整实现方案
- 每个场景的核心代码,拿来即用
- 性能优化的关键技巧和注意事项
- 从MySQL迁移到Redis的性能提升数据
让我们开始这段Redis进阶之旅,解锁它作为"分布式系统瑞士军刀"的全部潜力!
一、缓存:基本操作但有门道
// 设置缓存,带过期时间
redisTemplate.opsForValue().set("user:1001", userInfo, 30, TimeUnit.MINUTES);
// 防止缓存穿透的妙用 - 缓存空值
public User getUserById(Long id) {
String key = "user:" + id;
User user = (User) redisTemplate.opsForValue().get(key);
if (user == null) {
// 查询数据库
user = userMapper.selectById(id);
// 即使为null也缓存,但过期时间较短
redisTemplate.opsForValue().set(key, user != null ? user : new NullUser(),
user != null ? 30 : 5, TimeUnit.MINUTES);
}
return user instanceof NullUser ? null : user;
}
进阶技巧:使用布隆过滤器预判断ID是否存在,彻底解决缓存穿透问题!
二、数据共享:分布式系统的必备技能
// 分布式Session共享
@Configuration
public class RedisSessionConfig {
@Bean
public RedisHttpSessionConfiguration redisHttpSessionConfiguration() {
RedisHttpSessionConfiguration config = new RedisHttpSessionConfiguration();
config.setMaxInactiveIntervalInSeconds(1800); // 30分钟
return config;
}
}
// 分布式配置中心
@RefreshScope
@RestController
public class ConfigController {
@Value("${app.config.value}")
private String configValue;
@GetMapping("/config")
public String getConfig() {
return configValue;
}
}
实战案例:我们将系统的动态配置存入Redis,10个服务实例共享配置,一处修改,所有实例秒级生效!
三、分布式锁:高并发系统的守护者
public boolean acquireLock(String lockKey, String requestId, int expireTime) {
// SET NX PX 原子操作
Boolean result = redisTemplate.opsForValue().setIfAbsent(
lockKey, requestId, expireTime, TimeUnit.MILLISECONDS);
return Boolean.TRUE.equals(result);
}
public boolean releaseLock(String lockKey, String requestId) {
// Lua脚本保证原子性
String script = "if redis.call('get', KEYS[1]) == ARGV[1] then " +
"return redis.call('del', KEYS[1]) else return 0 end";
Long result = redisTemplate.execute(
new DefaultRedisScript<>(script, Long.class),
Collections.singletonList(lockKey),
requestId);
return Long.valueOf(1).equals(result);
}
实战案例:秒杀系统中,我们用Redis分布式锁保证库存不超卖,TPS从原来的1200提升到8000+!
四、全局ID生成器:高性能分布式ID的制造机
public long generateId(String businessType) {
// INCR命令原子递增
Long id = redisTemplate.opsForValue().increment("id:" + businessType);
// 组合成全局唯一ID
long timestamp = System.currentTimeMillis() / 1000;
return (timestamp << 32) | id;
}
// 批量获取ID,减少网络往返
public List batchGenerateIds(String businessType, int count) {
// INCRBY命令一次性增加多个
Long startId = redisTemplate.opsForValue().increment("id:" + businessType, count);
List ids = new ArrayList<>(count);
for (int i = 0; i < count; i++) {
ids.add(startId - count + i + 1);
}
return ids;
}
性能对比:Redis生成ID的QPS可达10w+,比MySQL的auto_increment高出数十倍,且易于水平扩展!
五、计数器:高性能计数的不二之选
// 文章阅读计数
public void incrementViewCount(Long articleId) {
String key = "article:view:" + articleId;
redisTemplate.opsForValue().increment(key);
// 异步持久化到数据库
if (redisTemplate.opsForValue().get(key + ":dirty") == null) {
redisTemplate.opsForValue().set(key + ":dirty", "1", 5, TimeUnit.MINUTES);
CompletableFuture.runAsync(() -> {
Long count = Long.valueOf(redisTemplate.opsForValue().get(key).toString());
articleMapper.updateViewCount(articleId, count);
});
}
}
// 多维度计数
public Map getArticleStats(Long articleId) {
String keyPrefix = "article:" + articleId + ":";
Map stats = new HashMap<>();
// 批量获取多个计数
List keys = Arrays.asList(
keyPrefix + "view",
keyPrefix + "like",
keyPrefix + "comment",
keyPrefix + "share"
);
List values = redisTemplate.opsForValue().multiGet(keys);
stats.put("viewCount", values.get(0) != null ? Long.valueOf(values.get(0)) : 0);
stats.put("likeCount", values.get(1) != null ? Long.valueOf(values.get(1)) : 0);
stats.put("commentCount", values.get(2) != null ? Long.valueOf(values.get(2)) : 0);
stats.put("shareCount", values.get(3) != null ? Long.valueOf(values.get(3)) : 0);
return stats;
}
实战案例:我们的社交平台使用Redis计数器,支持亿级用户的点赞、评论、分享实时计数,毫秒级响应!
六、限流:API的保护伞
// 简单窗口限流
public boolean isAllowed(String userId, String action, int limit, int windowSeconds) {
String key = "rate:" + action + ":" + userId;
Long count = redisTemplate.opsForValue().increment(key);
// 第一次访问,设置过期时间
if (count == 1) {
redisTemplate.expire(key, windowSeconds, TimeUnit.SECONDS);
}
return count <= limit;
}
// 滑动窗口限流
public boolean isAllowedBySliding(String userId, String action, int limit, int windowSeconds) {
String key = "sliding_window:" + action + ":" + userId;
long now = System.currentTimeMillis();
// 添加当前时间戳到有序集合
redisTemplate.opsForZSet().add(key, String.valueOf(now), now);
// 移除窗口之外的数据
redisTemplate.opsForZSet().removeRangeByScore(key, 0, now - windowSeconds * 1000);
// 获取窗口内的请求数
Long count = redisTemplate.opsForZSet().zCard(key);
// 设置过期时间,避免长期占用内存
redisTemplate.expire(key, windowSeconds * 2, TimeUnit.SECONDS);
return count <= limit;
}
实战案例:我们的支付API使用Redis滑动窗口限流,成功抵御了一次恶意刷单攻击,避免了数十万的经济损失!
七、位统计:节省内存的统计神器
// 用户签到 - 一个月只需要4个字节
public void userSignIn(Long userId, LocalDate date) {
String key = "sign:" + userId + ":" + date.getYear() + ":" + date.getMonthValue();
redisTemplate.opsForValue().setBit(key, date.getDayOfMonth() - 1, true);
}
// 检查是否签到
public boolean hasSignedIn(Long userId, LocalDate date) {
String key = "sign:" + userId + ":" + date.getYear() + ":" + date.getMonthValue();
return Boolean.TRUE.equals(
redisTemplate.opsForValue().getBit(key, date.getDayOfMonth() - 1));
}
// 获取当月签到次数
public long getMonthSignCount(Long userId, int year, int month) {
String key = "sign:" + userId + ":" + year + ":" + month;
return redisTemplate.execute((RedisCallback) con ->
con.bitCount(key.getBytes()));
}
// 获取当月首次签到日期
public int getFirstSignDay(Long userId, int year, int month) {
String key = "sign:" + userId + ":" + year + ":" + month;
List result = redisTemplate.execute((RedisCallback<List>) con -> {
List list = new ArrayList<>();
long index = con.bitPos(key.getBytes(), true);
list.add(index);
return list;
});
return result.get(0).intValue() + 1;
}
内存对比:传统方式存储1亿用户一个月的签到数据需要60GB+,使用Redis的BitMap只需要不到400MB!
八、购物车:性能与体验的完美结合
// 添加商品到购物车
public void addToCart(Long userId, Long productId, int quantity) {
String key = "cart:" + userId;
// 检查是否已在购物车中
Object existingQuantity = redisTemplate.opsForHash().get(key, productId.toString());
if (existingQuantity != null) {
quantity += Integer.parseInt(existingQuantity.toString());
}
// 更新购物车
redisTemplate.opsForHash().put(key, productId.toString(), String.valueOf(quantity));
}
// 获取购物车
public Map getCart(Long userId) {
String key = "cart:" + userId;
Map
实战案例:我们的电商平台使用Redis实现购物车,支持跨设备同步,商品更新实时反映,用户体验大幅提升!
九、用户消息时间线:社交应用的核心功能
// 发布消息到时间线
public void postToTimeline(Long userId, Message message) {
// 1. 保存消息
String messageKey = "message:" + message.getId();
redisTemplate.opsForHash().putAll(messageKey, convertMessageToMap(message));
// 2. 添加到发布者的时间线
String userTimelineKey = "timeline:user:" + userId;
redisTemplate.opsForZSet().add(userTimelineKey, message.getId().toString(),
message.getTimestamp());
// 3. 推送到粉丝的时间线
String followersKey = "followers:" + userId;
Set followers = redisTemplate.opsForSet().members(followersKey);
if (followers != null && !followers.isEmpty()) {
for (String followerId : followers) {
String followerTimelineKey = "timeline:user:" + followerId;
redisTemplate.opsForZSet().add(followerTimelineKey,
message.getId().toString(), message.getTimestamp());
}
}
}
// 获取用户时间线
public List getUserTimeline(Long userId, int offset, int count) {
String timelineKey = "timeline:user:" + userId;
// 按时间倒序获取消息ID
Set messageIds = redisTemplate.opsForZSet().reverseRange(
timelineKey, offset, offset + count - 1);
if (messageIds == null || messageIds.isEmpty()) {
return Collections.emptyList();
}
// 批量获取消息内容
List messages = new ArrayList<>();
for (String id : messageIds) {
String messageKey = "message:" + id;
Map
架构亮点:Redis时间线模型同时支持推模式和拉模式,可以根据用户活跃度和粉丝数动态调整策略!
十、消息队列:轻量级的异步处理方案
// 生产者:发送消息
public void sendMessage(String topic, Object message) {
String messageId = UUID.randomUUID().toString();
String messageKey = "message:" + topic + ":" + messageId;
// 1. 存储消息内容
redisTemplate.opsForValue().set(messageKey, JSON.toJSONString(message));
redisTemplate.expire(messageKey, 7, TimeUnit.DAYS);
// 2. 将消息ID放入队列
redisTemplate.opsForList().rightPush("queue:" + topic, messageId);
}
// 消费者:处理消息
@Scheduled(fixedDelay = 100)
public void processMessages() {
// 1. 从队列获取消息
String messageId = redisTemplate.opsForList().leftPop("queue:orders", 5, TimeUnit.SECONDS);
if (messageId != null) {
String messageKey = "message:orders:" + messageId;
String messageContent = redisTemplate.opsForValue().get(messageKey);
if (messageContent != null) {
try {
// 2. 处理消息
OrderMessage order = JSON.parseObject(messageContent, OrderMessage.class);
orderService.processOrder(order);
// 3. 处理成功,删除消息
redisTemplate.delete(messageKey);
} catch (Exception e) {
// 4. 处理失败,放入重试队列
redisTemplate.opsForList().rightPush("queue:orders:retry", messageId);
log.error("Failed to process message: " + messageId, e);
}
}
}
}
使用场景:我们用Redis实现了轻量级消息队列,处理每日50万订单的异步通知,比使用重量级MQ节省了大量资源!
十一、抽奖:概率控制的艺术
// 奖品设置
public void setupPrize(Long activityId, List prizes) {
String key = "lottery:prizes:" + activityId;
// 清空之前的设置
redisTemplate.delete(key);
// 设置奖品及其权重
for (Prize prize : prizes) {
redisTemplate.opsForZSet().add(key, prize.getId().toString(), prize.getWeight());
}
}
// 抽奖实现
public Prize drawPrize(Long activityId, Long userId) {
String key = "lottery:prizes:" + activityId;
// 获取所有奖品及权重
Set<ZSetOperations.TypedTuple> prizeWithScores =
redisTemplate.opsForZSet().rangeWithScores(key, 0, -1);
if (prizeWithScores == null || prizeWithScores.isEmpty()) {
throw new RuntimeException("No prizes available");
}
// 计算总权重
double totalWeight = 0;
for (ZSetOperations.TypedTuple item : prizeWithScores) {
totalWeight += item.getScore();
}
// 生成随机数
double random = Math.random() * totalWeight;
// 根据权重选择奖品
double currentWeight = 0;
for (ZSetOperations.TypedTuple item : prizeWithScores) {
currentWeight += item.getScore();
if (random <= currentWeight) {
// 中奖记录
String recordKey = "lottery:record:" + activityId;
redisTemplate.opsForHash().put(recordKey, userId.toString(), item.getValue());
// 返回中奖信息
return prizeService.getPrizeById(Long.valueOf(item.getValue()));
}
}
throw new RuntimeException("Failed to draw prize");
}
实战案例:我们的营销活动使用Redis实现抽奖系统,支持实时调整中奖概率,单日抽奖次数突破500万!
十二、点赞、签到、打卡:用户互动三件套
// 点赞功能
public boolean toggleLike(Long userId, Long contentId) {
String key = "likes:" + contentId;
// 检查是否已点赞
Boolean isLiked = redisTemplate.opsForSet().isMember(key, userId.toString());
if (Boolean.TRUE.equals(isLiked)) {
// 取消点赞
redisTemplate.opsForSet().remove(key, userId.toString());
// 减少计数
redisTemplate.opsForValue().decrement("likes:count:" + contentId);
return false;
} else {
// 添加点赞
redisTemplate.opsForSet().add(key, userId.toString());
// 增加计数
redisTemplate.opsForValue().increment("likes:count:" + contentId);
return true;
}
}
// 获取点赞数
public long getLikeCount(Long contentId) {
String countKey = "likes:count:" + contentId;
Object count = redisTemplate.opsForValue().get(countKey);
return count != null ? Long.parseLong(count.toString()) : 0;
}
// 获取点赞用户列表
public List getLikedUsers(Long contentId, int offset, int limit) {
String key = "likes:" + contentId;
Set userIds = redisTemplate.opsForSet().members(key);
if (userIds == null || userIds.isEmpty()) {
return Collections.emptyList();
}
return userIds.stream()
.map(Long::valueOf)
.skip(offset)
.limit(limit)
.collect(Collectors.toList());
}
// 连续签到统计
public int getContinuousSignDays(Long userId) {
LocalDate today = LocalDate.now();
String key = "sign:" + userId + ":" + today.getYear() + ":" + today.getMonthValue();
int days = 0;
int dayOfMonth = today.getDayOfMonth();
// 从今天向前查找连续签到记录
for (int i = 0; i < dayOfMonth; i++) {
int day = dayOfMonth - i;
Boolean signed = redisTemplate.opsForValue().getBit(key, day - 1);
if (Boolean.TRUE.equals(signed)) {
days++;
} else {
break;
}
}
return days;
}
性能提升:使用Redis实现点赞功能,相比MySQL方案,QPS提升了20倍,从500提升到10000+!
十三、商品标签:高效的多维度属性管理
// 添加商品标签
public void addProductTags(Long productId, Set tags) {
// 1. 添加到商品的标签集合
String productTagsKey = "product:tags:" + productId;
redisTemplate.opsForSet().add(productTagsKey,
tags.toArray(new String[0]));
// 2. 添加到标签的商品集合
for (String tag : tags) {
String tagProductsKey = "tag:products:" + tag;
redisTemplate.opsForSet().add(tagProductsKey, productId.toString());
}
}
// 获取商品的所有标签
public Set getProductTags(Long productId) {
String key = "product:tags:" + productId;
Set tags = redisTemplate.opsForSet().members(key);
return tags != null ? tags : Collections.emptySet();
}
// 获取拥有特定标签的所有商品
public Set getProductsByTag(String tag) {
String key = "tag:products:" + tag;
Set productIds = redisTemplate.opsForSet().members(key);
if (productIds == null || productIds.isEmpty()) {
return Collections.emptySet();
}
return productIds.stream()
.map(Long::valueOf)
.collect(Collectors.toSet());
}
// 获取同时拥有多个标签的商品(交集)
public Set getProductsByTags(Set tags) {
if (tags == null || tags.isEmpty()) {
return Collections.emptySet();
}
// 构建多个集合的key
List keys = tags.stream()
.map(tag -> "tag:products:" + tag)
.collect(Collectors.toList());
// 计算交集
Set productIds = redisTemplate.opsForSet().intersect(
keys.get(0), keys.subList(1, keys.size()));
if (productIds == null || productIds.isEmpty()) {
return Collections.emptySet();
}
return productIds.stream()
.map(Long::valueOf)
.collect(Collectors.toSet());
}
实战案例:我们的电商平台使用Redis管理商品标签,支持亿级商品的实时标签查询,毫秒级返回结果!
十四、商品筛选:高性能的条件过滤
// 按价格区间索引商品
public void indexProductByPrice(Long productId, double price) {
String key = "product:price";
redisTemplate.opsForZSet().add(key, productId.toString(), price);
}
// 按价格区间查询商品
public Set getProductsByPriceRange(double minPrice, double maxPrice) {
String key = "product:price";
Set productIds = redisTemplate.opsForZSet().rangeByScore(key, minPrice, maxPrice);
if (productIds == null || productIds.isEmpty()) {
return Collections.emptySet();
}
return productIds.stream()
.map(Long::valueOf)
.collect(Collectors.toSet());
}
// 复合条件筛选
public Set filterProducts(double minPrice, double maxPrice, Set tags) {
// 1. 按价格筛选
Set priceFilteredProducts = getProductsByPriceRange(minPrice, maxPrice);
if (priceFilteredProducts.isEmpty() || tags == null || tags.isEmpty()) {
return priceFilteredProducts;
}
// 2. 按标签筛选
Set tagFilteredProducts = getProductsByTags(tags);
// 3. 取交集
priceFilteredProducts.retainAll(tagFilteredProducts);
return priceFilteredProducts;
}
// 分页获取筛选结果
public List getFilteredProducts(FilterCriteria criteria, int page, int size) {
// 获取符合条件的商品ID
Set productIds = filterProducts(
criteria.getMinPrice(),
criteria.getMaxPrice(),
criteria.getTags()
);
if (productIds.isEmpty()) {
return Collections.emptyList();
}
// 分页处理
return productIds.stream()
.skip((page - 1) * size)
.limit(size)
.map(productService::getProductById)
.collect(Collectors.toList());
}
性能对比:Redis实现的商品筛选功能,比MySQL的多条件查询快10倍以上,且支持更复杂的组合条件!
十五、用户关注、推荐模型:社交关系的构建
// 关注用户
public void followUser(Long followerId, Long followeeId) {
// 添加到关注集合
String followingKey = "following:" + followerId;
redisTemplate.opsForSet().add(followingKey, followeeId.toString());
// 添加到粉丝集合
String followersKey = "followers:" + followeeId;
redisTemplate.opsForSet().add(followersKey, followerId.toString());
}
// 取消关注
public void unfollowUser(Long followerId, Long followeeId) {
// 从关注集合移除
String followingKey = "following:" + followerId;
redisTemplate.opsForSet().remove(followingKey, followeeId.toString());
// 从粉丝集合移除
String followersKey = "followers:" + followeeId;
redisTemplate.opsForSet().remove(followersKey, followerId.toString());
}
// 获取共同关注
public Set getCommonFollowing(Long userId1, Long userId2) {
String key1 = "following:" + userId1;
String key2 = "following:" + userId2;
Set commonIds = redisTemplate.opsForSet().intersect(key1, key2);
if (commonIds == null || commonIds.isEmpty()) {
return Collections.emptySet();
}
return commonIds.stream()
.map(Long::valueOf)
.collect(Collectors.toSet());
}
// 推荐可能认识的人
public Set recommendUsers(Long userId) {
String followingKey = "following:" + userId;
// 获取用户的关注列表
Set followingIds = redisTemplate.opsForSet().members(followingKey);
if (followingIds == null || followingIds.isEmpty()) {
return Collections.emptySet();
}
// 获取关注的人的关注列表(二度关系)
Set recommendations = new HashSet<>();
for (String followingId : followingIds) {
String secondDegreeKey = "following:" + followingId;
Set secondDegreeIds = redisTemplate.opsForSet().members(secondDegreeKey);
if (secondDegreeIds != null) {
for (String id : secondDegreeIds) {
Long recommendId = Long.valueOf(id);
// 排除自己和已关注的人
if (!recommendId.equals(userId) && !followingIds.contains(id)) {
recommendations.add(recommendId);
}
}
}
}
return recommendations;
}
// 基于用户相似度的推荐
public List getContentRecommendations(Long userId) {
// 1. 找到相似用户
Set similarUsers = findSimilarUsers(userId);
// 2. 获取相似用户喜欢的内容
Map contentScores = new HashMap<>();
for (Long similarUserId : similarUsers) {
String likedKey = "user:liked:" + similarUserId;
Set likedContent = redisTemplate.opsForSet().members(likedKey);
if (likedContent != null) {
for (String contentId : likedContent) {
Long cid = Long.valueOf(contentId);
// 计算内容得分
contentScores.put(cid, contentScores.getOrDefault(cid, 0.0) + 1.0);
}
}
}
// 3. 排除用户已经喜欢的内容
String userLikedKey = "user:liked:" + userId;
Set userLiked = redisTemplate.opsForSet().members(userLikedKey);
if (userLiked != null) {
for (String contentId : userLiked) {
contentScores.remove(Long.valueOf(contentId));
}
}
// 4. 按得分排序返回推荐内容
return contentScores.entrySet().stream()
.sorted(Map.Entry.comparingByValue().reversed())
.limit(10)
.map(Map.Entry::getKey)
.collect(Collectors.toList());
}
实战案例:我们的社交平台使用Redis构建用户关系网络,支持5000万用户的实时推荐,推荐准确率提升了35%!
十六、排行榜:高效的实时榜单
// 更新得分
public void updateScore(String leaderboardKey, Long userId, double score) {
redisTemplate.opsForZSet().add(leaderboardKey, userId.toString(), score);
}
// 增加得分
public double incrementScore(String leaderboardKey, Long userId, double increment) {
Double newScore = redisTemplate.opsForZSet().incrementScore(
leaderboardKey, userId.toString(), increment);
return newScore != null ? newScore : 0;
}
// 获取排名
public long getRank(String leaderboardKey, Long userId) {
Long rank = redisTemplate.opsForZSet().reverseRank(leaderboardKey, userId.toString());
return rank != null ? rank + 1 : 0; // +1转为从1开始的排名
}
// 获取前N名
public List getTopN(String leaderboardKey, int n) {
Set<ZSetOperations.TypedTuple> tuples =
redisTemplate.opsForZSet().reverseRangeWithScores(leaderboardKey, 0, n - 1);
if (tuples == null || tuples.isEmpty()) {
return Collections.emptyList();
}
List result = new ArrayList<>();
int rank = 1;
for (ZSetOperations.TypedTuple tuple : tuples) {
result.add(new RankItem(
Long.valueOf(tuple.getValue()),
tuple.getScore(),
rank++
));
}
return result;
}
// 获取用户附近排名
public List getNearbyRanks(String leaderboardKey, Long userId, int count) {
// 1. 获取用户排名
Long rank = redisTemplate.opsForZSet().reverseRank(leaderboardKey, userId.toString());
if (rank == null) {
return Collections.emptyList();
}
// 2. 计算范围
long start = Math.max(0, rank - count / 2);
long end = start + count - 1;
// 3. 获取指定范围的排名数据
Set<ZSetOperations.TypedTuple> tuples =
redisTemplate.opsForZSet().reverseRangeWithScores(leaderboardKey, start, end);
if (tuples == null || tuples.isEmpty()) {
return Collections.emptyList();
}
// 4. 组装结果
List result = new ArrayList<>();
long currentRank = start + 1;
for (ZSetOperations.TypedTuple tuple : tuples) {
result.add(new RankItem(
Long.valueOf(tuple.getValue()),
tuple.getScore(),
currentRank++
));
}
return result;
}
// 获取多个时间维度的排行榜
public Map<String, List> getMultiTimeLeaderboards(String category, int n) {
Map<String, List> result = new HashMap<>();
// 日榜
String dailyKey = "leaderboard:" + category + ":daily";
result.put("daily", getTopN(dailyKey, n));
// 周榜
String weeklyKey = "leaderboard:" + category + ":weekly";
result.put("weekly", getTopN(weeklyKey, n));
// 月榜
String monthlyKey = "leaderboard:" + category + ":monthly";
result.put("monthly", getTopN(monthlyKey, n));
// 总榜
String allTimeKey = "leaderboard:" + category + ":alltime";
result.put("allTime", getTopN(allTimeKey, n));
return result;
}
实战案例:我们的游戏平台使用Redis实现实时排行榜,支持日榜、周榜、月榜多维度更新,每日榜单查询量超过1亿次!
写在最后
Redis的16种妙用,你学会了几种?这些用法不仅能解决实际问题,还能大幅提升系统性能。
使用建议:
- 根据业务场景选择合适的数据结构
- 注意内存使用和过期策略
- 关注数据一致性问题
- 做好监控和容灾
性能提升:
- 缓存:响应时间从200ms降至5ms
- 计数器:QPS从1000提升至50000+
- 排行榜:复杂排序从秒级降至毫秒级
- 分布式锁:支持10万+并发请求
进阶技巧:
- 使用Pipeline批量操作
- 利用Lua脚本保证原子性
- 合理设置过期时间
- 使用Redis Cluster实现高可用
记住:
"Redis不仅是一个缓存,它是一把解决分布式问题的瑞士军刀!"
你还在只把Redis当缓存用吗?赶紧解锁这些神仙用法,让同事直呼牛!
#Redis #架构设计 #性能优化 #分布式系统