Redis 在 Spring 项目中的使用及操作方法
<div id="navCategory"><h5 class="catalogue">目录</h5><ul class="first_class_ul"><li><a href="#_label0">一、Redis 在 Spring 项目中的常见使用场景</a></li><li><a href="#_label1">二、环境准备</a></li><li><a href="#_label2">三、RedisTemplate 的作用</a></li><li><a href="#_label3">四、应用场景实战</a></li><ul class="second_class_ul"><li><a href="#_lab2_3_0">4.1 缓存(Cache)</a></li><li><a href="#_lab2_3_1">4.2 分布式 Session 管理</a></li><li><a href="#_lab2_3_2">4.3 分布式锁(Distributed Lock)</a></li><li><a href="#_lab2_3_3">4.4 消息队列(Message Queue)</a></li><li><a href="#_lab2_3_4">4.5 排行榜 / 计数系统</a></li><li><a href="#_lab2_3_5">4.6 限流(Rate Limiting)</a></li><li><a href="#_lab2_3_6">4.7 延时任务 / 定时任务</a></li><li><a href="#_lab2_3_7">4.8 热点数据保护</a></li><li><a href="#_lab2_3_8">4.9 地理位置(Geo)</a></li><li><a href="#_lab2_3_9">4.10 数据共享 / 配置中心缓存</a></li></ul></ul></div><p class="maodian"><a name="_label0"></a></p><h2>一、Redis 在 Spring 项目中的常见使用场景</h2><p>在企业开发中,Redis 不只是一个缓存工具,而是一个<strong>高性能分布式中间件</strong>。<br />它既能加速数据访问,也能解决很多分布式问题。</p>
<table><thead><tr><th>场景类别</th><th>场景说明</th><th>使用目的</th></tr></thead><tbody><tr><td><strong>1. 缓存(Cache)</strong></td><td>将数据库查询结果或计算结果暂存到 Redis</td><td>提高访问速度、减轻数据库压力</td></tr><tr><td><strong>2. 分布式 Session 管理</strong></td><td>在多台服务器间共享登录状态</td><td>解决 Session 不一致问题</td></tr><tr><td><strong>3. 分布式锁(Distributed Lock)</strong></td><td>控制分布式环境下的资源竞争</td><td>保证接口幂等性、避免超卖</td></tr><tr><td><strong>4. 消息队列(Message Queue)</strong></td><td>使用 Redis 的 List 或 Stream 实现简单消息队列</td><td>异步处理任务、削峰填谷</td></tr><tr><td><strong>5. 排行榜 / 计数系统</strong></td><td>使用 ZSet、Incr 等结构实现排行榜、点赞、热度统计</td><td>实时性强、性能高</td></tr><tr><td><strong>6. 限流(Rate Limiting)</strong></td><td>基于 Redis 的计数器算法实现请求限流</td><td>防止接口被恶意频繁调用</td></tr><tr><td><strong>7. 数据共享 / 配置中心缓存</strong></td><td>缓存配置、公共数据字典、系统参数</td><td>提高系统访问效率</td></tr><tr><td><strong>8. 地理位置功能(Geo)</strong></td><td>使用 Redis 的 Geo 类型</td><td>实现附近的人 / 店铺功能</td></tr><tr><td><strong>9. 延时任务 / 定时任务</strong></td><td>利用 ZSet 的分数排序实现延迟调度</td><td>替代消息队列中的延迟功能</td></tr><tr><td><strong>10. 热点数据保护</strong></td><td>对热点 Key 设置过期策略或锁</td><td>避免缓存击穿、穿透、雪崩问题</td></tr></tbody></table>
<p class="maodian"><a name="_label1"></a></p><h2>二、环境准备</h2>
<p>在开始编码前,我们需要在 Spring Boot 项目中引入 Redis 依赖。</p>
<p><strong>Maven 依赖:</strong></p>
<div class="jb51code"><pre class="brush:plain;"><dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency></pre></div>
<p><strong>YAML 配置:</strong></p>
<div class="jb51code"><pre class="brush:yaml;">spring:
data:
redis:
host: localhost
port: 6379
password:
database: 0
timeout: 2000ms</pre></div>
<p>这就完成了基础配置,Spring Boot 会自动帮我们创建 <code>RedisTemplate</code> 对象。</p>
<p class="maodian"><a name="_label2"></a></p><h2>三、RedisTemplate 的作用</h2>
<p>在 Spring 中,<code>RedisTemplate</code> 是操作 Redis 的核心对象,<br />相当于 Redis 的 JDBC 模板。所有读写都靠它完成。</p>
<table><thead><tr><th>方法</th><th>Redis 类型</th><th>常见业务场景</th><th>示例</th></tr></thead><tbody><tr><td><code>opsForValue()</code></td><td>String</td><td>缓存对象、验证码、Token</td><td><code>set("user:1001:name", "Tom")</code></td></tr><tr><td><code>opsForHash()</code></td><td>Hash</td><td>存储对象属性,如用户、商品</td><td><code>put("user:1001", "age", "25")</code></td></tr><tr><td><code>opsForList()</code></td><td>List</td><td>评论列表、任务队列</td><td><code>leftPush("comment:101", "很好!")</code></td></tr><tr><td><code>opsForSet()</code></td><td>Set</td><td>点赞去重、好友推荐</td><td><code>add("like:post:100", "user1")</code></td></tr><tr><td><code>opsForZSet()</code></td><td>ZSet</td><td>排行榜、积分榜</td><td><code>add("rank:score", "Tom", 100)</code></td></tr></tbody></table>
<p><strong>一句话理解:</strong></p>
<blockquote><p>RedisTemplate 是万能 钥匙,不管你想存什么类型的数据,它都能帮你搞定。</p></blockquote>
<p class="maodian"><a name="_label3"></a></p><h2>四、应用场景实战</h2>
<p class="maodian"><a name="_lab2_3_0"></a></p><h3>4.1 缓存(Cache)</h3>
<table><thead><tr><th>分类</th><th>场景说明</th><th>使用目的</th><th>Redis 类型</th><th>示例</th></tr></thead><tbody><tr><td>缓存数据库查询结果</td><td>缓存商品详情、用户信息</td><td>提高访问速度</td><td>String / Hash</td><td>user:1001 → {…}</td></tr><tr><td>缓存热点数据</td><td>首页推荐、排行榜</td><td>提升并发性能</td><td>String / ZSet</td><td>rank:hot → </td></tr><tr><td>缓存计算结果</td><td>缓存统计分析结果</td><td>降低重复计算</td><td>String</td><td>report:2025-11 → value</td></tr><tr><td>本地 + 分布式缓存</td><td>Spring Cache + Redis</td><td>提高系统扩展性</td><td>Hash</td><td><code>@Cacheable(value="user")</code></td></tr></tbody></table>
<p><strong>业务背景</strong></p>
<p>在高并发项目中(比如商城、题库、短视频平台),数据库访问往往成为性能瓶颈。<br />而 Redis 的读写性能是数据库的上千倍,因此我们常常将热点数据缓存起来,<br />以“读缓存 → 缓存失效 → 回源数据库”的模式运行。</p>
<p><strong>示例:缓存用户详情数据</strong></p>
<div class="jb51code"><pre class="brush:java;">@Service
public class UserService {
@Resource
private RedisTemplate<String, Object> redisTemplate;
@Resource
private UserMapper userMapper;
public User getUserById(Long id) {
String key = "user:" + id;
// Step 1: 尝试从缓存中读取
User user = (User) redisTemplate.opsForValue().get(key);
if (user != null) {
System.out.println("【命中缓存】userId = " + id);
return user;
}
// Step 2: 缓存未命中 → 查询数据库
user = userMapper.selectById(id);
if (user == null) {
return null;
}
// Step 3: 写入缓存,设置过期时间 10 分钟
redisTemplate.opsForValue().set(key, user, 10, TimeUnit.MINUTES);
System.out.println("【写入缓存】userId = " + id);
return user;
}
}</pre></div>
<p><strong>亮点:</strong></p>
<ul><li>每次查询会优先走 Redis;</li><li>避免同一数据被频繁访问数据库;</li><li>可控制缓存时间,防止脏数据积累。</li></ul>
<p class="maodian"><a name="_lab2_3_1"></a></p><h3>4.2 分布式 Session 管理</h3>
<table><thead><tr><th>分类</th><th>场景说明</th><th>使用目的</th><th>Redis 类型</th><th>示例</th></tr></thead><tbody><tr><td>分布式 Session 管理</td><td>多台服务器共享登录状态</td><td>解决 Session 不一致</td><td>String / Hash</td><td>登录共享、SSO、Token 验证</td></tr></tbody></table>
<p><strong>业务背景</strong></p>
<p>假设一个网站部署在三台服务器上:</p>
<ul><li>用户第一次请求被分配到 A 服务器并登录;</li><li>第二次请求被负载均衡到 B;</li><li>B 并不知道这个用户的登录状态。</li></ul>
<blockquote><p>这就是典型的 “Session 不一致” 问题。</p></blockquote>
<p><strong>方案一:使用 Spring Session(推荐)</strong></p>
<p><strong>依赖:</strong></p>
<div class="jb51code"><pre class="brush:plain;"><dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency></pre></div>
<p><strong>配置:</strong></p>
<div class="jb51code"><pre class="brush:plain;">spring:
session:
store-type: redis
redis:
host: localhost
port: 6379</pre></div>
<p><strong>实现效果:</strong></p>
<ul><li>自动拦截所有 <code>HttpSession</code>;</li><li>自动序列化到 Redis;</li><li>多台服务器访问同一 Redis,即可共享登录状态。</li></ul>
<p><strong>方案二:自定义 Token(前后端分离项目常用)</strong></p>
<p><strong>登录接口:</strong></p>
<div class="jb51code"><pre class="brush:java;">@PostMapping("/login")
public ResponseEntity<?> login(@RequestBody LoginRequest request) {
User user = userMapper.findByUsername(request.getUsername());
if (user == null || !user.getPassword().equals(request.getPassword())) {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("用户名或密码错误");
}
// 生成 token
String token = UUID.randomUUID().toString();
redisTemplate.opsForValue().set("login:token:" + token, user, 30, TimeUnit.MINUTES);
return ResponseEntity.ok(Map.of("token", token));
}</pre></div>
<p><strong>请求拦截器:</strong></p>
<div class="jb51code"><pre class="brush:java;">@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
String token = request.getHeader("Authorization");
if (token == null) return false;
User user = (User) redisTemplate.opsForValue().get("login:token:" + token);
if (user == null) {
response.setStatus(401);
return false;
}
request.setAttribute("user", user);
return true;
}</pre></div>
<p><strong>效果:</strong></p>
<ul><li>Token 与用户信息缓存在 Redis;</li><li>任意节点可通过 token 验证身份;</li><li>登录状态共享、可过期控制。</li></ul>
<p class="maodian"><a name="_lab2_3_2"></a></p><h3>4.3 分布式锁(Distributed Lock)</h3>
<table><thead><tr><th>分类</th><th>场景说明</th><th>使用目的</th><th>Redis 类型</th><th>示例</th></tr></thead><tbody><tr><td>分布式锁</td><td>控制资源竞争</td><td>保证幂等、防止超卖</td><td>String</td><td>秒杀、库存控制</td></tr></tbody></table>
<p><strong>业务背景</strong></p>
<p>电商场景中,秒杀活动高并发下会导致:</p>
<ul><li>多人同时下单同一商品;</li><li>超卖、库存负数。</li></ul>
<p>此时可以用 Redis 分布式锁,确保一个商品同一时刻只能被一个线程修改。</p>
<p><strong>代码实现:</strong></p>
<div class="jb51code"><pre class="brush:java;">@Service
public class OrderService {
@Resource
private RedisTemplate<String, Object> redisTemplate;
public void placeOrder(Long productId) {
String lockKey = "lock:product:" + productId;
String clientId = UUID.randomUUID().toString();
try {
Boolean locked = redisTemplate.opsForValue()
.setIfAbsent(lockKey, clientId, 10, TimeUnit.SECONDS);
if (Boolean.FALSE.equals(locked)) {
throw new RuntimeException("系统繁忙,请稍后再试");
}
// 模拟扣库存逻辑
Integer stock = getStock(productId);
if (stock > 0) {
updateStock(productId, stock - 1);
System.out.println("下单成功,库存剩余:" + (stock - 1));
} else {
System.out.println("库存不足");
}
} finally {
// 释放锁(防止误删)
String value = (String) redisTemplate.opsForValue().get(lockKey);
if (clientId.equals(value)) {
redisTemplate.delete(lockKey);
}
}
}
private Integer getStock(Long id) { return 5; } // 模拟
private void updateStock(Long id, Integer newStock) {}
}</pre></div>
<p><strong>要点说明:</strong></p>
<ul><li><code>setIfAbsent()</code> = Redis 实现的原子加锁;</li><li>过期时间避免死锁;</li><li>校验 <code>clientId</code> 防止误删他人锁。</li></ul>
<p class="maodian"><a name="_lab2_3_3"></a></p><h3>4.4 消息队列(Message Queue)</h3>
<table><thead><tr><th>分类</th><th>场景说明</th><th>使用目的</th><th>Redis 类型</th><th>示例</th></tr></thead><tbody><tr><td>消息队列</td><td>使用 List / Stream 实现异步任务</td><td>异步处理任务、削峰填谷</td><td>List / Stream</td><td>下单通知、邮件发送</td></tr></tbody></table>
<p><strong>业务背景</strong></p>
<p>假设用户下单成功后,需要:</p>
<ul><li>发送邮件;</li><li>推送短信;</li><li>更新统计数据。</li></ul>
<p>这些都可以异步执行,不应阻塞主线程。</p>
<p><strong>方案一:基于 List 的简单队列</strong></p>
<div class="jb51code"><pre class="brush:java;">// 生产者:发送任务
public void sendMailTask(String mailJson) {
redisTemplate.opsForList().leftPush("queue:mail", mailJson);
}
// 消费者:异步线程处理任务
@Scheduled(fixedDelay = 2000)
public void consumeMailTask() {
String task = (String) redisTemplate.opsForList().rightPop("queue:mail");
if (task != null) {
System.out.println("发送邮件任务:" + task);
// 执行邮件发送逻辑
}
}</pre></div>
<p><strong>方案二:使用 Stream(支持消费组)</strong></p>
<div class="jb51code"><pre class="brush:sql;">XADD queue:order * orderId 1001 userId 2002
XGROUP CREATE queue:order group1 0 MKSTREAM</pre></div>
<p><strong>消费者代码:</strong></p>
<div class="jb51code"><pre class="brush:java;">@Scheduled(fixedDelay = 3000)
public void consumeOrder() {
List<MapRecord<String, Object, Object>> messages = redisTemplate.opsForStream()
.read(Consumer.from("group1", "consumerA"),
StreamReadOptions.empty().count(1),
StreamOffset.create("queue:order", ReadOffset.lastConsumed()));
if (messages != null) {
for (MapRecord<String, Object, Object> msg : messages) {
System.out.println("消费订单消息:" + msg.getValue());
redisTemplate.opsForStream().acknowledge("queue:order", "group1", msg.getId());
}
}
}</pre></div>
<p><strong>优势:</strong></p>
<ul><li>支持多消费者组;</li><li>消息可持久化;</li><li>可追溯未消费记录。</li></ul>
<p class="maodian"><a name="_lab2_3_4"></a></p><h3>4.5 排行榜 / 计数系统</h3>
<table><thead><tr><th>分类</th><th>场景说明</th><th>使用目的</th><th>Redis 类型</th><th>示例</th></tr></thead><tbody><tr><td>排行榜 / 计数</td><td>实现积分榜、热度榜、点赞统计</td><td>实时计算 + 高性能排序</td><td>ZSet / String</td><td>热门文章榜、游戏积分榜</td></tr></tbody></table>
<p><strong>业务背景</strong></p>
<p>在很多应用中(例如:<strong>短视频热榜、游戏积分榜、帖子点赞排行</strong>),我们都需要根据“分数”动态排序。<br />数据库的排序操作成本高,而 Redis 的 <code>ZSet</code> 类型天然支持「按分数排序」,<br />非常适合做排行榜类功能。</p>
<p><strong>代码示例:用户积分排行榜</strong></p>
<div class="jb51code"><pre class="brush:java;">@Service
public class RankService {
@Resource
private RedisTemplate<String, Object> redisTemplate;
private static final String RANK_KEY = "rank:user:score";
// 增加用户积分
public void addScore(String userId, double score) {
redisTemplate.opsForZSet().incrementScore(RANK_KEY, userId, score);
}
// 获取前 N 名用户
public Set<String> getTopUsers(int limit) {
return redisTemplate.opsForZSet().reverseRange(RANK_KEY, 0, limit - 1);
}
// 查询某个用户的排名
public Long getRank(String userId) {
return redisTemplate.opsForZSet().reverseRank(RANK_KEY, userId);
}
// 查询某个用户的分数
public Double getUserScore(String userId) {
return redisTemplate.opsForZSet().score(RANK_KEY, userId);
}
}</pre></div>
<p><strong>使用效果:</strong></p>
<div class="jb51code"><pre class="brush:java;">rankService.addScore("Tom", 10);
rankService.addScore("Jerry", 20);
rankService.addScore("Alice", 15);
System.out.println(rankService.getTopUsers(3)); // </pre></div>
<p><strong>扩展应用</strong></p>
<ul><li>文章热度排行榜(根据阅读量 / 点赞数累计)</li><li>商品销量榜单</li><li>实时在线活跃用户榜</li><li>视频播放量榜单</li></ul>
<p class="maodian"><a name="_lab2_3_5"></a></p><h3>4.6 限流(Rate Limiting)</h3>
<table><thead><tr><th>分类</th><th>场景说明</th><th>使用目的</th><th>Redis 类型</th><th>示例</th></tr></thead><tbody><tr><td>接口限流</td><td>限制单位时间内访问次数</td><td>防止接口被刷、控制 QPS</td><td>String</td><td>登录防暴力 破解、API 限速</td></tr></tbody></table>
<p><strong>业务背景</strong></p>
<p>在接口开放或秒杀活动中,往往会出现某些接口被频繁请求,<br />轻则浪费资源,重则打垮系统。</p>
<p>此时我们可以利用 Redis 做“计数限流”:</p>
<blockquote><p>以 IP / 用户 ID 为维度,统计在某个时间窗口内的访问次数。</p></blockquote>
<p><strong>代码示例:基于固定窗口的限流实现</strong></p>
<div class="jb51code"><pre class="brush:java;">@Service
public class RateLimitService {
@Resource
private RedisTemplate<String, Object> redisTemplate;
// 每分钟最多请求 60 次
private static final int LIMIT_COUNT = 60;
private static final int EXPIRE_TIME = 60;
public void checkRateLimit(String ip) {
String key = "limit:ip:" + ip;
Long count = redisTemplate.opsForValue().increment(key);
if (count == 1) {
redisTemplate.expire(key, EXPIRE_TIME, TimeUnit.SECONDS);
}
if (count > LIMIT_COUNT) {
throw new RuntimeException("请求过于频繁,请稍后再试!");
}
}
}</pre></div>
<p><strong>示例使用:</strong></p>
<div class="jb51code"><pre class="brush:sql;">@GetMapping("/api/test")
public String test(HttpServletRequest request) {
String ip = request.getRemoteAddr();
rateLimitService.checkRateLimit(ip);
return "正常访问成功";
}
</pre></div>
<p><strong>升级方案:滑动窗口限流</strong></p>
<p>使用 Redis 的 <code>ZSet</code> 来记录时间戳,实现更精确的滑动窗口限流:</p>
<div class="jb51code"><pre class="brush:java;">public boolean allowRequest(String key, int limit, int seconds) {
long now = System.currentTimeMillis();
long windowStart = now - seconds * 1000L;
redisTemplate.opsForZSet().removeRangeByScore(key, 0, windowStart);
redisTemplate.opsForZSet().add(key, String.valueOf(now), now);
long count = redisTemplate.opsForZSet().zCard(key);
redisTemplate.expire(key, seconds, TimeUnit.SECONDS);
return count <= limit;
}</pre></div>
<p class="maodian"><a name="_lab2_3_6"></a></p><h3>4.7 延时任务 / 定时任务</h3>
<table><thead><tr><th>分类</th><th>场景说明</th><th>使用目的</th><th>Redis 类型</th><th>示例</th></tr></thead><tbody><tr><td>延时任务 / 定时任务</td><td>基于 ZSet 时间戳实现延迟执行</td><td>实现订单超时取消、消息延迟发送</td><td>ZSet</td><td>延迟队列、定时提醒</td></tr></tbody></table>
<p><strong>业务背景</strong></p>
<p>在很多业务中存在“延时触发”的逻辑,例如:</p>
<ul><li>订单 30 分钟未支付自动取消;</li><li>延迟发送消息;</li><li>提前 10 分钟推送会议提醒。</li></ul>
<p>使用 Redis 的 <strong>ZSet</strong> 可以轻松实现。</p>
<p><strong>代码示例:订单超时取消任务</strong></p>
<div class="jb51code"><pre class="brush:java;">@Service
public class DelayTaskService {
@Resource
private RedisTemplate<String, Object> redisTemplate;
private static final String DELAY_KEY = "delay:order";
// 添加延时任务
public void addDelayTask(Long orderId, long delayMs) {
long executeTime = System.currentTimeMillis() + delayMs;
redisTemplate.opsForZSet().add(DELAY_KEY, orderId, executeTime);
System.out.println("添加延迟任务: orderId=" + orderId + ", 执行时间=" + executeTime);
}
// 定时扫描执行任务
@Scheduled(fixedDelay = 5000)
public void executeTasks() {
long now = System.currentTimeMillis();
Set<Object> tasks = redisTemplate.opsForZSet().rangeByScore(DELAY_KEY, 0, now);
if (tasks != null) {
for (Object task : tasks) {
System.out.println("执行超时任务: orderId=" + task);
// 执行业务逻辑:关闭订单
redisTemplate.opsForZSet().remove(DELAY_KEY, task);
}
}
}
}</pre></div>
<p><strong>测试示例:</strong></p>
<div class="jb51code"><pre class="brush:sql;">delayTaskService.addDelayTask(1001L, 60000); // 1分钟后取消订单
</pre></div>
<p class="maodian"><a name="_lab2_3_7"></a></p><h3>4.8 热点数据保护</h3>
<table><thead><tr><th>分类</th><th>场景说明</th><th>使用目的</th><th>Redis 类型</th><th>示例</th></tr></thead><tbody><tr><td>热点数据保护</td><td>防止缓存击穿、穿透、雪崩</td><td>保证系统稳定性</td><td>String / Hash</td><td>商品详情缓存、热点新闻</td></tr></tbody></table>
<p><strong>业务背景</strong></p>
<p>在高并发系统中常见三种缓存问题:</p>
<table><thead><tr><th>问题类型</th><th>含义</th><th>解决方案</th></tr></thead><tbody><tr><td>缓存穿透</td><td>查询不存在的 Key 导致每次都打数据库</td><td>设置空值缓存、布隆过滤器</td></tr><tr><td>缓存击穿</td><td>热点 Key 失效瞬间被大量请求打爆</td><td>加互斥锁、延迟失效</td></tr><tr><td>缓存雪崩</td><td>大量 Key 同时过期</td><td>设置随机过期时间、预热机制</td></tr></tbody></table>
<p><strong>代码示例:缓存击穿防护</strong></p>
<div class="jb51code"><pre class="brush:java;">@Service
public class ProductService {
@Resource
private RedisTemplate<String, Object> redisTemplate;
@Resource
private ProductMapper productMapper;
public Product getProduct(Long id) {
String key = "product:" + id;
// 1. 先查缓存
Product product = (Product) redisTemplate.opsForValue().get(key);
if (product != null) {
return product;
}
// 2. 缓存为空,加锁防止击穿
synchronized (this) {
product = (Product) redisTemplate.opsForValue().get(key);
if (product == null) {
product = productMapper.selectById(id);
if (product == null) {
// 防止穿透:缓存空对象
redisTemplate.opsForValue().set(key, new Product(), 2, TimeUnit.MINUTES);
} else {
// 防止雪崩:过期时间随机
int expireTime = 10 + new Random().nextInt(5);
redisTemplate.opsForValue().set(key, product, expireTime, TimeUnit.MINUTES);
}
}
}
return product;
}
}</pre></div>
<p class="maodian"><a name="_lab2_3_8"></a></p><h3>4.9 地理位置(Geo)</h3>
<table><thead><tr><th>分类</th><th>场景说明</th><th>使用目的</th><th>Redis 类型</th><th>示例</th></tr></thead><tbody><tr><td>地理位置功能</td><td>使用 Geo 存储经纬度信息</td><td>实现“附近的人 / 店铺”功能</td><td>Geo</td><td>外卖、打车、社交定位</td></tr></tbody></table>
<p><strong>示例:查找附近商铺</strong></p>
<div class="jb51code"><pre class="brush:java;">@Service
public class GeoService {
@Resource
private RedisTemplate<String, Object> redisTemplate;
private static final String GEO_KEY = "shop:geo";
// 添加商铺坐标
public void addShop(String shopName, double lon, double lat) {
redisTemplate.opsForGeo().add(GEO_KEY, new Point(lon, lat), shopName);
}
// 查找附近商铺
public void findNearby(double lon, double lat, double distanceKm) {
Circle area = new Circle(new Point(lon, lat), new Distance(distanceKm, Metrics.KILOMETERS));
GeoResults<RedisGeoCommands.GeoLocation<Object>> results =
redisTemplate.opsForGeo().radius(GEO_KEY, area);
results.forEach(r -> System.out.println("附近店铺:" + r.getContent().getName()));
}
}</pre></div>
<p class="maodian"><a name="_lab2_3_9"></a></p><h3>4.10 数据共享 / 配置中心缓存</h3>
<table><thead><tr><th>分类</th><th>场景说明</th><th>使用目的</th><th>Redis 类型</th><th>示例</th></tr></thead><tbody><tr><td>数据共享 / 配置缓存</td><td>缓存公共配置与数据字典</td><td>减少数据库压力</td><td>Hash / String</td><td>系统参数缓存</td></tr></tbody></table>
<p><strong>代码示例:系统配置缓存</strong></p>
<div class="jb51code"><pre class="brush:java;">@Service
public class ConfigService {
@Resource
private RedisTemplate<String, Object> redisTemplate;
public String getConfig(String key) {
String value = (String) redisTemplate.opsForHash().get("config:system", key);
if (value == null) {
// 假设从数据库加载配置
value = loadFromDb(key);
redisTemplate.opsForHash().put("config:system", key, value);
}
return value;
}
private String loadFromDb(String key) {
// 模拟数据库
if ("maxLoginRetry".equals(key)) return "5";
return "default";
}
}</pre></div>
頁:
[1]