
先上链接:腾讯云 Redis
缓存技术已成为构建高性能、低延时系统不可或缺的技术。Redis 作为一个高性能的内存数据库,被广泛应用于缓存、会话管理、限流等场景。在分布式架构中,缓存可以显著提高系统的吞吐量,降低数据库的压力。腾讯云 Redis 作为托管的 Redis 服务,为开发者提供了安全、稳定、可扩展的解决方案,使我们无需关心底层的管理运维,可以专注于业务开发。

本文将结合 Spring Boot 和腾讯云 Redis,带大家从零开始构建一个高性能的缓存系统,并通过 Bootstrap UI 搭建一个简洁的前端界面,以方便在实际项目中测试和验证缓存功能的效果。
要创建一个 Spring Boot 项目,首先可以使用 Spring Initializr 快速生成项目模板。可以选择以下主要依赖:
Spring Web:用于创建 REST API。Spring Data Redis:提供与 Redis 交互的功能。Spring Boot Starter Thymeleaf:用于页面渲染(如果需要的话)。选择好依赖后,点击生成项目,将其下载并导入到 IDE 中。确保项目能正常运行。
application.yml 文件中。spring:
redis:
host: <YOUR_TENCENT_CLOUD_REDIS_HOST>
port: <PORT>
password: <PASSWORD>
timeout: 5000ms
lettuce:
pool:
max-active: 10
max-idle: 5
min-idle: 1通过以上配置,Spring Boot 就能够连接到腾讯云 Redis 服务,并进行数据的缓存与存取。
缓存系统的核心是如何高效地读写数据。在这个例子中,我们将用户信息缓存到 Redis 中,以提高查询性能。我们将使用 RedisTemplate 来操作缓存。
首先,我们创建一个简单的用户实体类,其中包含用户 ID、名称和邮箱等基本信息:
package com.example.demo.entity;
import lombok.Data;
import java.io.Serializable;
@Data
public class User implements Serializable {
private Long id;
private String name;
private String email;
}我们通过 RedisTemplate 来实现用户信息的缓存管理。以下是一个简单的 Redis 缓存服务,包含了增、删、查、改操作,我们创建了 saveUser、getUser、getAllUsers 和 deleteUser 四个常见的操作方法。这些方法允许我们对 Redis 中的用户数据进行增删查改。
package com.example.demo.service;
import com.example.demo.entity.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import java.util.Map;
@Service
public class UserService {
@Autowired
private RedisTemplate<String, Object> redisTemplate; // 自动注入 RedisTemplate
private static final String USER_CACHE_KEY = "USER";
// 保存用户信息到缓存
public void saveUser(User user) {
redisTemplate.opsForHash().put(USER_CACHE_KEY, user.getId().toString(), user);
}
// 从缓存中获取用户信息
public User getUser(Long id) {
return (User) redisTemplate.opsForHash().get(USER_CACHE_KEY, id.toString());
}
// 获取所有缓存的用户信息
public Map<Object, Object> getAllUsers() {
return redisTemplate.opsForHash().entries(USER_CACHE_KEY);
}
// 从缓存中删除用户信息
public void deleteUser(Long id) {
redisTemplate.opsForHash().delete(USER_CACHE_KEY, id.toString());
}
}package com.example.demo.controller;
import com.example.demo.entity.User;
import com.example.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.http.ResponseEntity;
import java.util.Map;
@Controller
public class UserController {
@Autowired
private UserService userService;
// 返回 index.html 页面
@GetMapping("/")
public String index() {
return "redis"; // 返回的是 index.html 页面
}
// 获取所有用户数据
@GetMapping("/api/users")
@ResponseBody
public Map<Object, Object> getAllUsers() {
return userService.getAllUsers();
}
// 获取单个用户数据
@GetMapping("/api/users/{id}")
@ResponseBody
public User getUser(@PathVariable Long id) {
return userService.getUser(id);
}
// 添加用户数据
@PostMapping("/api/users")
@ResponseBody
public ResponseEntity<String> saveUser(@RequestBody User user) {
try {
// 调用 service 层保存用户数据
userService.saveUser(user);
return ResponseEntity.ok("User saved successfully");
} catch (Exception e) {
// 捕获异常并返回错误信息
e.printStackTrace();
return ResponseEntity.status(500).body("Internal Server Error: " + e.getMessage());
}
}
// 删除用户数据
@DeleteMapping("/api/users/{id}")
@ResponseBody
public ResponseEntity<String> deleteUser(@PathVariable Long id) {
userService.deleteUser(id);
return ResponseEntity.ok("User deleted successfully");
}
}2.4 定义 RedisTemplate 的 Bean: 在 Spring Boot 中,你需要在配置类中手动配置一个 RedisTemplate Bean,指定连接的 Redis 库和数据类型。你可以通过以下方式来解决这个问题:
创建一个配置类来定义 RedisTemplate。
package com.example.demo.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
// 设置 key 和 value 的序列化方式
template.setKeySerializer(new StringRedisSerializer());
template.setValueSerializer(new StringRedisSerializer());
return template;
}
}为了更好地管理 Redis 中缓存的用户信息,我们使用 Bootstrap UI 来创建一个简单的用户管理页面。在这个页面中,用户可以输入自己的信息并提交保存,同时还可以查看缓存中的所有用户信息。
为了让页面更加美观,我们使用 Bootstrap 5 的 CDN 引入 UI 组件,避免了手动下载和管理静态资源。
在 index.html 中,我们加入了 Bootstrap 的 CDN:
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css" rel="stylesheet">在 src/main/resources/templates 目录下,我们创建了 redis.html 文件,通过 Bootstrap 创建了一个简洁的用户管理界面,功能包括添加用户、显示用户列表和删除用户。
这个页面实现了一个简洁的用户管理界面。用户可以通过输入框录入用户信息,并通过点击按钮将数据保存到 Redis 中。同时,页面会动态加载 Redis 中的用户信息,并展示在列表中,用户还可以删除已有的用户数据。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>用户缓存管理</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container">
<h1 class="mt-5">用户缓存管理</h1>
<div class="card mt-4">
<div class="card-header">Add User</div>
<div class="card-body">
<form id="userForm">
<div class="mb-3">
<label for="userId" class="form-label">User ID</label>
<input type="number" id="userId" class="form-control" required>
</div>
<div class="mb-3">
<label for="userName" class="form-label">Name</label>
<input type="text" id="userName" class="form-control" required>
</div>
<div class="mb-3">
<label for="userEmail" class="form-label">Email</label>
<input type="email" id="userEmail" class="form-control" required>
</div>
<button type="button" class="btn btn-primary" onclick="saveUser()">保存</button>
</form>
</div>
</div>
<!-- User List -->
<div class="card mt-4">
<div class="card-header">缓存列表</div>
<div class="card-body">
<ul id="userList" class="list-group"></ul>
</div>
</div>
</div>
<script>
async function saveUser() {
const user = {
id: document.getElementById('userId').value,
name: document.getElementById('userName').value,
email: document.getElementById('userEmail').value
};
await fetch('/api/users', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(user)
});
loadUsers();
}
async function loadUsers() {
const response = await fetch('/api/users');
const users = await response.json();
const userList = document.getElementById('userList');
userList.innerHTML = '';
Object.keys(users).forEach(key => {
const user = users[key];
const listItem = document.createElement('li');
listItem.classList.add('list-group-item', 'd-flex', 'justify-content-between', 'align-items-center');
listItem.textContent = `${user.name} (${user.email})`;
listItem.appendChild(createDeleteButton(user.id));
userList.appendChild(listItem);
});
}
function createDeleteButton(id) {
const button = document.createElement('button');
button.classList.add('btn', 'btn-danger', 'btn-sm');
button.textContent = 'Delete';
button.onclick = () => deleteUser(id);
return button;
}
async function deleteUser(id) {
await fetch(`/api/users/${id}`, { method: 'DELETE' });
loadUsers();
}
document.addEventListener('DOMContentLoaded', loadUsers);
</script>
</body>
</html>
Redis 是一个功能强大的内存数据库,除了作为缓存使用之外,还可以在多个场景中发挥作用,包括分布式锁、消息队列、发布/订阅系统等。通过合理使用 Redis 的数据结构和特性,可以极大地提升系统的性能和可靠性。
在分布式系统中,多个进程或服务器可能会同时访问共享资源,导致数据不一致或并发问题。为了保证数据的一致性和防止并发冲突,常常使用 分布式锁 来保证同一时间内只有一个进程可以操作共享资源。Redis 提供了一个简单的方式来实现分布式锁,主要使用 SETNX 命令(SET if Not eXists)来确保只有一个进程能够获得锁。
SETNX 命令来尝试设置一个键值对,如果键不存在,则设置成功并返回 1(表示获得锁)。import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.connection.RedisStringCommands;
import java.util.concurrent.TimeUnit;
@Service
public class RedisLockService {
@Autowired
private RedisTemplate<String, String> redisTemplate;
/**
* 尝试获取分布式锁
* @param lockKey 锁的标识
* @param requestId 请求标识,防止死锁
* @param expireTime 锁的过期时间,防止因某些原因未释放锁导致死锁
* @return 是否成功获得锁
*/
public boolean acquireLock(String lockKey, String requestId, long expireTime) {
return redisTemplate.execute((RedisCallback<Boolean>) connection ->
connection.set(lockKey.getBytes(), requestId.getBytes(),
Expiration.from(expireTime, TimeUnit.MILLISECONDS),
RedisStringCommands.SetOption.SET_IF_ABSENT));
}
/**
* 释放分布式锁
* @param lockKey 锁的标识
* @param requestId 请求标识
* @return 是否成功释放锁
*/
public boolean releaseLock(String lockKey, String requestId) {
// 只允许锁的拥有者释放锁
String currentValue = (String) redisTemplate.opsForValue().get(lockKey);
if (currentValue != null && currentValue.equals(requestId)) {
return redisTemplate.delete(lockKey); // 删除锁
}
return false; // 锁不存在或不是当前请求持有
}
}Redis 提供了丰富的 List 数据结构,可以用来实现消息队列。Redis 的 LPUSH 和 RPOP 命令是实现队列的基本操作:通过这种方式,可以实现一个简单的消息队列,适用于异步处理、任务队列等场景。
LPUSH:将一个元素插入到列表的左侧。RPOP:将一个元素从列表的右侧弹出。import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
@Service
public class RedisQueueService {
@Autowired
private RedisTemplate<String, String> redisTemplate;
/**
* 向队列中推送消息
* @param queueName 队列名称
* @param message 消息内容
*/
public void pushMessage(String queueName, String message) {
redisTemplate.opsForList().leftPush(queueName, message); // 将消息推入队列的左侧
}
/**
* 从队列中弹出消息
* @param queueName 队列名称
* @return 消息内容
*/
public String popMessage(String queueName) {
return (String) redisTemplate.opsForList().rightPop(queueName); // 从队列的右侧弹出消息
}
}BLPOP 和 BRPOP 命令,可以使队列操作阻塞,直到有消息到达队列。// 阻塞队列示例
public String popMessageBlocking(String queueName) {
return (String) redisTemplate.opsForList().rightPop(queueName, 0, TimeUnit.SECONDS); // 阻塞直到队列有消息
}Redis 还提供了发布/订阅(Pub/Sub)模式,用于消息的广播。发布者可以将消息发布到一个频道(Channel),而多个订阅者(Subscriber)可以订阅该频道,接收消息。此模式适用于即时消息通知、系统通知等场景。
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
@Service
public class RedisPubSubService {
@Autowired
private RedisTemplate<String, String> redisTemplate;
/**
* 发布消息到频道
* @param channel 频道名称
* @param message 消息内容
*/
public void publishMessage(String channel, String message) {
redisTemplate.convertAndSend(channel, message); // 发布消息
}
}订阅者可以通过实现 MessageListener 接口来订阅某个频道的消息:订阅过程通常在启动时通过 Redis 配置进行设置。
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.connection.MessageListener;
import org.springframework.stereotype.Service;
@Service
public class RedisMessageListener implements MessageListener {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Override
public void onMessage(Message message, byte[] pattern) {
String channel = new String(message.getChannel());
String messageBody = new String(message.getBody());
System.out.println("Received message from channel " + channel + ": " + messageBody);
}
}在实际应用中,Redis 缓存系统的性能优化是非常重要的。合理的缓存策略能够有效地提升系统的响应速度,减轻数据库的压力,改善用户体验。
缓存预热(Cache Warming)是指在系统启动时,或者系统空闲时,预先将一些常用的数据加载到缓存中。这样可以减少缓存未命中时对数据库的访问,提升系统响应速度。
缓存预热的好处:
实现方式:
假设我们有一个常用的商品数据,缓存预热可以在系统启动时自动加载这些商品数据:我们通过 @PostConstruct 注解让 preheatCache 方法在应用启动时执行,提前将常用的商品数据加载到 Redis 缓存中。这样,当用户访问这些商品时,可以直接从缓存中获取,避免了数据库的压力。
@Service
public class CacheWarmUpService {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
@Autowired
private ProductService productService;
private static final String CACHE_KEY = "product_data";
@PostConstruct
public void preheatCache() {
// 从数据库获取常用商品数据
List<Product> products = productService.getPopularProducts();
// 将数据加载到 Redis 缓存中
redisTemplate.opsForValue().set(CACHE_KEY, products, 1, TimeUnit.HOURS); // 缓存 1 小时
}
}缓存淘汰策略(Cache Eviction Strategy)用于决定在 Redis 缓存空间不足时,如何选择需要删除的数据。Redis 提供了多种缓存淘汰策略,可以根据具体的应用场景选择最合适的策略。
如何配置 Redis 缓存淘汰策略:
Redis 的缓存淘汰策略可以通过 redis.conf 文件或运行时命令进行配置。例如:这表示当 Redis 内存达到 2GB 时,使用 LRU 策略淘汰数据。
# 在 redis.conf 文件中设置 LRU 淘汰策略
maxmemory 2gb
maxmemory-policy allkeys-lru假设我们需要设置 Redis 使用 LRU 策略来淘汰缓存数据,在 application.properties 或 application.yml 配置文件中设置:配置表示当 Redis 内存使用超过 1GB 时,Redis 会按照 LRU 策略淘汰缓存。
# 设置 Redis 使用 LRU 策略淘汰数据
spring.redis.lru-eviction-policy=allkeys-lru
spring.redis.max-heap-size=1GB---使用腾讯云Redis的好处,就是可以以此来减轻腾讯云CVM(云服务器)服务器的功能压力,

Redis 作为高性能的缓存系统,可以将一些热点数据(例如用户信息、商品详情、搜索结果等)存储在内存中,避免每次请求都访问数据库或计算复杂逻辑。这样可以有效减少CVM服务器的计算压力,并提高响应速度。
Redis 提供了高效的键值存储,能够用来存储用户会话数据(例如登录状态、购物车内容等)。使用 Redis 来管理会话可以减轻CVM在用户请求中处理会话数据的压力,尤其是对于高并发的场景,Redis 能有效提升性能。
使用 Redis 提供的队列功能,可以将异步任务(例如邮件发送、数据处理、第三方接口请求等)放入队列中,CVM 服务器可以从队列中取出任务并异步处理,而无需同步处理每一个请求。这样可以减少CVM的即时负载。
Redis 可以帮助实现请求限流、访问频率控制等机制,防止某些高并发请求直接压垮服务器资源。例如,可以利用 Redis 的原子操作实现分布式限流计数器,防止短时间内过多请求集中到CVM服务器上,从而避免出现雪崩效应。
Redis 提供了非常高效的实时数据处理能力,能够实时统计数据(如用户访问次数、页面点击量等)。这种实时处理能力减轻了CVM对数据库的压力,因为不需要每次都进行计算和查询。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。