一、分布式锁
秒杀高并发排队神器,
当年做电商秒杀,数据库行锁直接被打到 奄奄一息。
Redis 一出马,线程乖乖排队,老板再也不用担心超卖。
复制
// Maven 依赖
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>3.23.4</version>
</dependency>
Config config = new Config();
config.useSingleServer().setAddress("redis://127.0.0.1:6379");
RedissonClient redisson = Redisson.create(config);
RLock lock = redisson.getLock("stock:1001");
try {
// **30 秒内抢锁,锁 30 秒后自动释放**
if (lock.tryLock(30, 30, TimeUnit.SECONDS)) {
updateStockInDB(); // 真正的减库存逻辑
}
} finally {
if (lock.isHeldByCurrentThread()) {
lock.unlock(); // **一定记得手动释放**
}
}1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.
注解
1. tryLock 带时间参数,防止死锁。
2. finally 释放锁,避免“占着茅坑不拉屎”。
3. 集群场景用 RedLock,主节点挂了也能继续嗨。
二、计数器:2 万 QPS 的救火队长
直播在线人数用数据库 UPDATE?
直接 200 QPS 就跪。
Redis 的 INCR 让在线人数 像坐火箭一样飙升。
复制
Jedis jedis = new Jedis("redis://127.0.0.1:6379");
String key = "rate_limit:user:" + userId + ":minute";
long count = jedis.incr(key);
if (count == 1) {
jedis.expire(key, 60); // **首次创建,设 60 秒过期**
}
if (count > 100) {
throw new RuntimeException("手速太快,歇会儿!");
}1.2.3.4.5.6.7.8.9.
注解
1. incr 原子自增,天然抗并发。
2. expire 只在第一次设置,避免每次请求都刷新 TTL。
3. 100 次/分钟阈值可配置,灵活限流。
三、排行榜:ZSET 的凡尔赛舞台
年度博主排行?数据库跑 3 小时,ZSET 5 分钟搞定。
关键是还能 实时更新!。
复制
// 点赞一次,分数 +1
redisTemplate.opsForZSet()
.incrementScore("blog:like:rank", "user:1001", 1);
// 取前 10
Set<ZSetOperations.TypedTuple<String>> top10 =
redisTemplate.opsForZSet()
.reverseRangeWithScores("blog:like:rank", 0, 9);
// 查个人排名
Long rank = redisTemplate.opsForZSet()
.reverseRank("blog:like:rank", "user:1001");1.2.3.4.5.6.7.8.9.10.11.12.
注解
1. incrementScore 原子操作,并发点赞不丢分。
2. reverseRangeWithScores 一次取出成员和分数,减少网络往返。
3. reverseRank 查排行 O(log n),再多人也不怕。
四、轻量消息队列:异步快递员
订单高峰 10 倍流量?
把订单先丢 Redis List,后台慢慢消费,爆仓不存在的。
复制
// 生产者
jedis.lpush("order_queue", JSON.toJSONString(order));
// 消费者
while (true) {
List<String> msg = jedis.brpop(0, "order_queue");
if (msg != null) {
try {
processOrder(msg.get(1));
} catch (Exception e) {
// 失败丢到重试队列
jedis.lpush("order_retry_queue", msg.get(1));
}
}
}1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.
注解
1. brpop 阻塞读取,CPU 不空转。
2. 失败消息进入 retry 队列,可配合延时策略。
3. List 队列简单可靠,但 没有 ACK,需自己实现重试。
五、会话共享:分布式登录管家
用户在 A 机器登录,跳到 B 机器就掉线?
用 Redis 做 统一 Session 仓库,妈妈再也不用担心我踢用户下线。
复制
# application.yml
spring:
session:
store-type: redis
timeout: 30m
redis:
host: 127.0.0.1
port: 63791.2.3.4.5.6.7.8.
注解
1. spring-session-data-redis 一行配置搞定。
2. SessionID 随机的 UUID + 签名,防伪造。
3. 每次登录重新生成 SessionID,旧 Session 秒失效。
六、地理位置:附近门店秒查
“附近 5 公里有啥好吃的?”
Redis GEO 一出手,5 倍速出结果。
复制
// 添加门店坐标
redisTemplate.opsForGeo()
.add("shop:locations",
new Point(116.4074, 39.9042), "shop:1001");
// 查 5 公里内,由近到远
GeoResults<GeoLocation<String>> results =
redisTemplate.opsForGeo()
.radius("shop:locations",
new Circle(new Point(116.4074, 39.9042),
Metrics.KILOMETERS.toMeters(5)),
GeoRadiusCommandArgs.newGeoRadiusArgs()
.includeDistance()
.sortAscending());
results.getContent().forEach(r ->
System.out.println(r.getContent().getName()
+ " 离你 " + r.getDistance().getValue() + " 米"));1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.
注解
1. GEOADD 一次可插多条,批量效率高。
2. GEORADIUS 默认 O(N),但 Redis 用 geohash + 跳表,N<10W 稳稳的。
3. 距离单位支持 m/km/ft/mi,国际化项目无压力。
七、野路子合集:老码农私货
7.1 滑动窗口限流
复制
String key = "rate_limit:user:" + userId;
long now = System.currentTimeMillis();
// 清理 60 秒前记录
redisTemplate.opsForZSet()
.removeRangeByScore(key, 0, now - 60000);
// 记录当前时间戳
redisTemplate.opsForZSet().add(key, String.valueOf(now), now);
// 统计窗口内请求数
Long cnt = redisTemplate.opsForZSet().zCard(key);
if (cnt > 50) throw new RuntimeException("刷太快,小黑屋见!");1.2.3.4.5.6.7.8.9.10.
注解
1. ZSET 按时间排序,天然滑动窗口。
2. removeRangeByScore 批量清理,O(log n)。
3. zCard 计数,内存占用极低。
7.2 乐观锁抢购
复制
jedis.watch("stock:1001");
int stock = Integer.parseInt(jedis.get("stock:1001"));
if (stock > 0) {
Transaction tx = jedis.multi();
tx.decr("stock:1001");
List<Object> res = tx.exec();
if (res == null) {
// **被其他客户端改了,重试**
}
}1.2.3.4.5.6.7.8.9.10.
注解
1. watch + multi + exec 保证 原子减库存。
2. exec 返回 null 即版本冲突,自旋重试即可。
3. 适合 秒杀库存少、冲突高 的场景。
至此分享完毕,希望以上内容对你有所帮助!