在现代企业级应用开发中,spring boot、redis 和 rabbitmq 已经成为不可或缺的技术组件。它们各自在项目中扮演着重要角色,共同构建出高性能、高可用的分布式系统。本文将深入剖析这三者在实际项目中的作用,并通过代码示例和流程图展示它们的实际应用。
一、spring boot:快速开发的利器
1.1 spring boot 的核心作用
spring boot 是一个基于 spring 框架的快速开发脚手架,其主要作用体现在:
- 简化配置:通过自动配置和约定优于配置的原则,大幅减少 xml 配置
- 快速启动:内嵌 tomcat、jetty 等 web 容器,无需部署 war 包
- 生产就绪:提供健康检查、指标监控等生产级特性
- 微服务支持:完美支持 spring cloud 微服务生态
1.2 spring boot 项目结构
// 主启动类
@springbootapplication
public class application {
public static void main(string[] args) {
springapplication.run(application.class, args);
}
}
// 控制器层
@restcontroller
@requestmapping("/api/users")
public class usercontroller {
@autowired
private userservice userservice;
@getmapping("/{id}")
public responseentity<user> getuserbyid(@pathvariable long id) {
user user = userservice.getuserbyid(id);
return responseentity.ok(user);
}
@postmapping
public responseentity<user> createuser(@requestbody user user) {
user saveduser = userservice.createuser(user);
return responseentity.status(httpstatus.created).body(saveduser);
}
}
// 服务层
@service
public class userservice {
@autowired
private userrepository userrepository;
public user getuserbyid(long id) {
return userrepository.findbyid(id)
.orelsethrow(() -> new resourcenotfoundexception("user not found"));
}
public user createuser(user user) {
return userrepository.save(user);
}
}
// 数据访问层
@repository
public interface userrepository extends jparepository<user, long> {
optional<user> findbyemail(string email);
}
// 实体类
@entity
@table(name = "users")
@data
public class user {
@id
@generatedvalue(strategy = generationtype.identity)
private long id;
@column(nullable = false)
private string name;
@column(nullable = false, unique = true)
private string email;
@creationtimestamp
private localdatetime createdat;
}1.3 spring boot 自动配置原理
// 自定义 starter 示例
@configuration
@conditionalonclass(userservice.class)
@enableconfigurationproperties(userproperties.class)
public class userautoconfiguration {
@bean
@conditionalonmissingbean
public userservice userservice(userproperties properties) {
return new userservice(properties);
}
}
// 配置属性类
@configurationproperties(prefix = "app.user")
@data
public class userproperties {
private string defaultname = "default user";
private int maxattempts = 3;
}
// meta-inf/spring.factories
org.springframework.boot.autoconfigure.enableautoconfiguration=\
com.example.autoconfigure.userautoconfiguration1.4 spring boot 在项目中的架构位置
┌─────────────────┐ ┌──────────────────┐ ┌─────────────────┐
│ client │───▶│ spring boot │───▶│ database │
│ (browser/app) │ │ application │ │ (mysql/psql) │
└─────────────────┘ └──────────────────┘ └─────────────────┘
│ │ │
│ ▼ │
│ ┌─────────────────┐ │
└──────────────│ thymeleaf │─────────────┘
│ templates │
└─────────────────┘二、redis:高性能缓存与数据存储
2.1 redis 的核心作用
redis 是一个开源的内存数据结构存储,用作数据库、缓存和消息代理,其主要作用:
- 缓存加速:减少数据库访问,提升应用性能
- 会话存储:分布式会话管理
- 消息队列:通过 pub/sub 和 streams 实现消息传递
- 实时数据处理:计数器、排行榜等实时功能
2.2 redis 在 spring boot 中的集成
// redis 配置类
@configuration
@enablecaching
public class redisconfig {
@bean
public redistemplate<string, object> redistemplate(redisconnectionfactory factory) {
redistemplate<string, object> template = new redistemplate<>();
template.setconnectionfactory(factory);
// 使用 jackson2jsonredisserializer 序列化
jackson2jsonredisserializer<object> serializer =
new jackson2jsonredisserializer<>(object.class);
objectmapper mapper = new objectmapper();
mapper.setvisibility(propertyaccessor.all, jsonautodetect.visibility.any);
mapper.activatedefaulttyping(
mapper.getpolymorphictypevalidator(),
objectmapper.defaulttyping.non_final
);
serializer.setobjectmapper(mapper);
template.setkeyserializer(new stringredisserializer());
template.setvalueserializer(serializer);
template.sethashkeyserializer(new stringredisserializer());
template.sethashvalueserializer(serializer);
template.afterpropertiesset();
return template;
}
@bean
public cachemanager cachemanager(redisconnectionfactory factory) {
rediscacheconfiguration config = rediscacheconfiguration.defaultcacheconfig()
.entryttl(duration.ofminutes(10)) // 设置缓存过期时间
.disablecachingnullvalues(); // 不缓存空值
return rediscachemanager.builder(factory)
.cachedefaults(config)
.build();
}
}2.3 redis 缓存使用示例
// 缓存服务类
@service
public class productservice {
@autowired
private productrepository productrepository;
@autowired
private redistemplate<string, object> redistemplate;
private static final string product_cache_key = "product:";
private static final string product_list_cache_key = "products:all";
// 使用 spring cache 注解
@cacheable(value = "products", key = "#id")
public product getproductbyid(long id) {
return productrepository.findbyid(id)
.orelsethrow(() -> new resourcenotfoundexception("product not found"));
}
// 手动缓存操作
public list<product> getallproducts() {
// 先从缓存获取
list<product> products = (list<product>) redistemplate.opsforvalue()
.get(product_list_cache_key);
if (products != null) {
return products;
}
// 缓存未命中,查询数据库
products = productrepository.findall();
// 写入缓存,设置过期时间
redistemplate.opsforvalue().set(
product_list_cache_key,
products,
duration.ofminutes(30)
);
return products;
}
// 更新缓存
@cacheput(value = "products", key = "#product.id")
public product updateproduct(product product) {
product updated = productrepository.save(product);
// 清除列表缓存
redistemplate.delete(product_list_cache_key);
return updated;
}
// 删除缓存
@cacheevict(value = "products", key = "#id")
public void deleteproduct(long id) {
productrepository.deletebyid(id);
redistemplate.delete(product_list_cache_key);
}
// redis 分布式锁示例
public boolean purchaseproduct(long productid, integer quantity) {
string lockkey = "lock:product:" + productid;
string requestid = uuid.randomuuid().tostring();
try {
// 尝试获取分布式锁
boolean locked = redistemplate.opsforvalue().setifabsent(
lockkey, requestid, duration.ofseconds(10)
);
if (boolean.true.equals(locked)) {
// 获取锁成功,执行库存扣减
product product = getproductbyid(productid);
if (product.getstock() >= quantity) {
product.setstock(product.getstock() - quantity);
updateproduct(product);
return true;
}
return false;
} else {
// 获取锁失败,稍后重试
thread.sleep(100);
return purchaseproduct(productid, quantity);
}
} catch (exception e) {
throw new runtimeexception("purchase failed", e);
} finally {
// 释放锁
if (requestid.equals(redistemplate.opsforvalue().get(lockkey))) {
redistemplate.delete(lockkey);
}
}
}
}2.4 redis 数据结构应用场景
@service
public class redisdatastructureservice {
@autowired
private redistemplate<string, object> redistemplate;
// string 类型:缓存、计数器
public void stringoperations() {
// 缓存对象
user user = new user(1l, "john doe", "john@example.com");
redistemplate.opsforvalue().set("user:1", user);
// 计数器
redistemplate.opsforvalue().increment("page:view:home");
long views = redistemplate.opsforvalue().increment("user:1:login:count");
}
// hash 类型:存储对象属性
public void hashoperations() {
redistemplate.opsforhash().put("user:2", "name", "jane smith");
redistemplate.opsforhash().put("user:2", "email", "jane@example.com");
redistemplate.opsforhash().put("user:2", "age", "25");
string name = (string) redistemplate.opsforhash().get("user:2", "name");
}
// list 类型:消息队列、最新列表
public void listoperations() {
// 最新消息列表
redistemplate.opsforlist().leftpush("recent:news", "news 1");
redistemplate.opsforlist().leftpush("recent:news", "news 2");
redistemplate.opsforlist().trim("recent:news", 0, 9); // 保持10条最新
list<object> recentnews = redistemplate.opsforlist().range("recent:news", 0, -1);
}
// set 类型:标签、共同好友
public void setoperations() {
// 用户标签
redistemplate.opsforset().add("user:1:tags", "vip", "active", "premium");
redistemplate.opsforset().add("user:2:tags", "active", "new");
// 共同标签
set<object> commontags = redistemplate.opsforset().intersect("user:1:tags", "user:2:tags");
}
// sorted set 类型:排行榜
public void sortedsetoperations() {
// 用户积分排行榜
redistemplate.opsforzset().add("leaderboard", "user1", 1000);
redistemplate.opsforzset().add("leaderboard", "user2", 1500);
redistemplate.opsforzset().add("leaderboard", "user3", 1200);
// 获取前10名
set<zsetoperations.typedtuple<object>> topusers =
redistemplate.opsforzset().reverserangewithscores("leaderboard", 0, 9);
}
}2.5 redis 在系统架构中的位置
┌─────────────────┐ ┌──────────────────┐ ┌─────────────────┐
│ spring boot │───▶│ redis │◀───│ other services │
│ application │ │ │ │ │
└─────────────────┘ └──────────────────┘ └─────────────────┘
│ │
│ │
▼ ▼
┌─────────────────┐ ┌──────────────────┐
│ database │ │ message queue │
│ (mysql) │ │ (rabbitmq) │
└─────────────────┘ └──────────────────┘三、rabbitmq:可靠的消息中间件
3.1 rabbitmq 的核心作用
rabbitmq 是一个开源的消息代理软件,实现了高级消息队列协议(amqp),主要作用:
- 应用解耦:分离系统组件,降低耦合度
- 异步处理:提高系统响应速度
- 流量削峰:应对突发流量,保护后端系统
- 消息分发:实现发布/订阅模式
3.2 rabbitmq 在 spring boot 中的配置
// rabbitmq 配置类
@configuration
public class rabbitmqconfig {
// 交换机
public static final string exchange_order = "order.exchange";
public static final string exchange_notification = "notification.exchange";
// 队列
public static final string queue_order_create = "order.create.queue";
public static final string queue_order_cancel = "order.cancel.queue";
public static final string queue_notification_email = "notification.email.queue";
public static final string queue_notification_sms = "notification.sms.queue";
// 路由键
public static final string routing_key_order_create = "order.create";
public static final string routing_key_order_cancel = "order.cancel";
public static final string routing_key_notification_all = "notification.#";
// 订单交换机(direct)
@bean
public directexchange orderexchange() {
return new directexchange(exchange_order);
}
// 通知交换机(topic)
@bean
public topicexchange notificationexchange() {
return new topicexchange(exchange_notification);
}
// 订单创建队列
@bean
public queue ordercreatequeue() {
return new queue(queue_order_create, true); // durable=true
}
// 订单取消队列
@bean
public queue ordercancelqueue() {
return new queue(queue_order_cancel, true);
}
// 邮件通知队列
@bean
public queue emailnotificationqueue() {
return new queue(queue_notification_email, true);
}
// 短信通知队列
@bean
public queue smsnotificationqueue() {
return new queue(queue_notification_sms, true);
}
// 绑定关系
@bean
public binding bindingordercreate(queue ordercreatequeue, directexchange orderexchange) {
return bindingbuilder.bind(ordercreatequeue)
.to(orderexchange)
.with(routing_key_order_create);
}
@bean
public binding bindingordercancel(queue ordercancelqueue, directexchange orderexchange) {
return bindingbuilder.bind(ordercancelqueue)
.to(orderexchange)
.with(routing_key_order_cancel);
}
@bean
public binding bindingemailnotification(queue emailnotificationqueue, topicexchange notificationexchange) {
return bindingbuilder.bind(emailnotificationqueue)
.to(notificationexchange)
.with(routing_key_notification_all);
}
@bean
public binding bindingsmsnotification(queue smsnotificationqueue, topicexchange notificationexchange) {
return bindingbuilder.bind(smsnotificationqueue)
.to(notificationexchange)
.with(routing_key_notification_all);
}
// json 消息转换器
@bean
public messageconverter jsonmessageconverter() {
return new jackson2jsonmessageconverter();
}
}3.3 rabbitmq 消息生产者
@service
public class ordermessageproducer {
@autowired
private rabbittemplate rabbittemplate;
// 发送订单创建消息
public void sendordercreatemessage(order order) {
try {
ordermessage message = new ordermessage(
order.getid(),
order.getuserid(),
order.gettotalamount(),
order.getstatus(),
localdatetime.now()
);
rabbittemplate.convertandsend(
rabbitmqconfig.exchange_order,
rabbitmqconfig.routing_key_order_create,
message,
new correlationdata(order.getid().tostring())
);
log.info("order create message sent: {}", order.getid());
} catch (exception e) {
log.error("failed to send order create message", e);
throw new messagesendexception("failed to send order message");
}
}
// 发送订单取消消息
public void sendordercancelmessage(long orderid, string reason) {
ordercancelmessage message = new ordercancelmessage(orderid, reason, localdatetime.now());
rabbittemplate.convertandsend(
rabbitmqconfig.exchange_order,
rabbitmqconfig.routing_key_order_cancel,
message
);
log.info("order cancel message sent: {}", orderid);
}
// 发送通知消息
public void sendnotification(notification notification) {
rabbittemplate.convertandsend(
rabbitmqconfig.exchange_notification,
"notification." + notification.gettype(),
notification
);
}
}
// 订单消息dto
@data
@allargsconstructor
@noargsconstructor
public class ordermessage {
private long orderid;
private long userid;
private bigdecimal totalamount;
private string status;
private localdatetime timestamp;
}
// 订单取消消息dto
@data
@allargsconstructor
@noargsconstructor
public class ordercancelmessage {
private long orderid;
private string reason;
private localdatetime timestamp;
}3.4 rabbitmq 消息消费者
@component
public class ordermessageconsumer {
@autowired
private inventoryservice inventoryservice;
@autowired
private emailservice emailservice;
@autowired
private notificationservice notificationservice;
// 处理订单创建消息
@rabbitlistener(queues = rabbitmqconfig.queue_order_create)
public void handleordercreate(ordermessage message) {
try {
log.info("processing order create message: {}", message.getorderid());
// 扣减库存
inventoryservice.deductinventory(message.getorderid());
// 发送确认邮件
emailservice.sendorderconfirmation(message.getorderid());
// 记录处理成功
log.info("order create message processed successfully: {}", message.getorderid());
} catch (exception e) {
log.error("failed to process order create message: {}", message.getorderid(), e);
// 可以在这里实现重试逻辑或死信队列处理
throw new amqprejectanddontrequeueexception("processing failed");
}
}
// 处理订单取消消息
@rabbitlistener(queues = rabbitmqconfig.queue_order_cancel)
public void handleordercancel(ordercancelmessage message) {
log.info("processing order cancel message: {}", message.getorderid());
// 恢复库存
inventoryservice.restoreinventory(message.getorderid());
// 发送取消通知
notificationservice.sendcancelnotification(message.getorderid(), message.getreason());
}
}
// 通知消息消费者
@component
public class notificationmessageconsumer {
@autowired
private emailservice emailservice;
@autowired
private smsservice smsservice;
@rabbitlistener(queues = rabbitmqconfig.queue_notification_email)
public void handleemailnotification(notification notification) {
log.info("processing email notification: {}", notification);
emailservice.sendnotification(notification);
}
@rabbitlistener(queues = rabbitmqconfig.queue_notification_sms)
public void handlesmsnotification(notification notification) {
log.info("processing sms notification: {}", notification);
smsservice.sendnotification(notification);
}
}3.5 rabbitmq 高级特性配置
@configuration
public class rabbitmqadvancedconfig {
// 死信交换机配置
public static final string dlx_exchange = "dlx.exchange";
public static final string dlx_queue = "dlx.queue";
public static final string dlx_routing_key = "dlx.routing.key";
// 重试队列配置
public static final string retry_queue = "order.create.retry.queue";
public static final int max_retry_count = 3;
@bean
public directexchange dlxexchange() {
return new directexchange(dlx_exchange);
}
@bean
public queue dlxqueue() {
return new queue(dlx_queue, true);
}
@bean
public binding dlxbinding() {
return bindingbuilder.bind(dlxqueue())
.to(dlxexchange())
.with(dlx_routing_key);
}
// 带死信队列的订单创建队列
@bean
public queue ordercreatequeuewithdlx() {
map<string, object> args = new hashmap<>();
args.put("x-dead-letter-exchange", dlx_exchange);
args.put("x-dead-letter-routing-key", dlx_routing_key);
args.put("x-message-ttl", 60000); // 1分钟ttl
return new queue(rabbitmqconfig.queue_order_create, true, false, false, args);
}
// 消息确认回调
@bean
public rabbittemplate.confirmcallback confirmcallback() {
return (correlationdata, ack, cause) -> {
if (ack) {
log.info("message confirmed with correlation data: {}", correlationdata);
} else {
log.error("message confirmation failed: {}, cause: {}", correlationdata, cause);
}
};
}
// 消息返回回调
@bean
public rabbittemplate.returnscallback returnscallback() {
return returned -> {
log.error("message returned: {}", returned);
};
}
}3.6 rabbitmq 在系统架构中的消息流
┌─────────────────┐ ┌──────────────────┐ ┌─────────────────┐
│ order service │───▶│ rabbitmq │───▶│ inventory │
│ │ │ │ │ service │
└─────────────────┘ └──────────────────┘ └─────────────────┘
│ │ │
│ │ │
│ ▼ │
│ ┌─────────────────┐ │
└─────────────▶│ email service │─────────────┘
└─────────────────┘
│
│
▼
┌─────────────────┐
│ sms service │
└─────────────────┘四、三者在项目中的协同工作
4.1 完整电商订单处理流程
@service
@transactional
public class orderprocessingservice {
@autowired
private orderservice orderservice;
@autowired
private redistemplate<string, object> redistemplate;
@autowired
private ordermessageproducer messageproducer;
@autowired
private inventoryservice inventoryservice;
// 创建订单的完整流程
public order createorder(orderrequest request) {
string lockkey = "lock:user:" + request.getuserid() + ":order";
string requestid = uuid.randomuuid().tostring();
try {
// 1. 获取分布式锁,防止重复提交
boolean locked = redistemplate.opsforvalue()
.setifabsent(lockkey, requestid, duration.ofseconds(5));
if (!boolean.true.equals(locked)) {
throw new businessexception("请勿重复提交订单");
}
// 2. 检查库存(redis 缓存)
boolean instock = inventoryservice.checkstock(request.getproductid(), request.getquantity());
if (!instock) {
throw new businessexception("库存不足");
}
// 3. 创建订单
order order = orderservice.createorder(request);
// 4. 发送订单创建消息到 rabbitmq
messageproducer.sendordercreatemessage(order);
// 5. 更新 redis 中的用户订单缓存
updateuserordercache(order.getuserid(), order);
// 6. 记录订单创建日志到 redis
logordercreation(order);
return order;
} finally {
// 释放分布式锁
if (requestid.equals(redistemplate.opsforvalue().get(lockkey))) {
redistemplate.delete(lockkey);
}
}
}
private void updateuserordercache(long userid, order order) {
string userorderskey = "user:" + userid + ":orders";
// 使用 redis list 存储用户最近订单
redistemplate.opsforlist().leftpush(userorderskey, order);
redistemplate.opsforlist().trim(userorderskey, 0, 49); // 保留最近50条订单
}
private void logordercreation(order order) {
string orderlogkey = "order:log:" + localdate.now().tostring();
map<string, object> logentry = new hashmap<>();
logentry.put("orderid", order.getid());
logentry.put("userid", order.getuserid());
logentry.put("amount", order.gettotalamount());
logentry.put("timestamp", localdatetime.now());
redistemplate.opsforhash().put(orderlogkey, order.getid().tostring(), logentry);
}
}4.2 系统架构图
┌─────────────────────────────────────────────────────────────────┐
│ client layer │
│ ┌─────────────────┐ ┌─────────────────┐ │
│ │ web browser │ │ mobile app │ │
│ └─────────────────┘ └─────────────────┘ │
│ │ │ │
└────────────┼───────────────────────────┼───────────────────────┘
│ │
▼ ▼
┌─────────────────────────────────────────────────────────────────┐
│ spring boot application │
│ ┌─────────────────┐ ┌─────────────────┐ │
│ │ controller │───▶│ service │ │
│ │ layer │ │ layer │ │
│ └─────────────────┘ └─────────────────┘ │
│ │ │ │
│ ▼ ▼ │
│ ┌─────────────────┐ ┌─────────────────┐ │
│ │ redis cache │ │ rabbitmq │ │
│ │ │ │ producer │ │
│ └─────────────────┘ └─────────────────┘ │
└────────────┼───────────────────────────┼───────────────────────┘
│ │
▼ ▼
┌─────────────────────────────────────────────────────────────────┐
│ backend services │
│ ┌─────────────────┐ ┌─────────────────┐ │
│ │ database │ │ rabbitmq │ │
│ │ (mysql) │ │ consumer │ │
│ └─────────────────┘ └─────────────────┘ │
│ │ │ │
│ │ ▼ │
│ │ ┌─────────────────┐ │
│ │ │ external │ │
│ │ │ services │ │
│ │ │ (email/sms/...) │ │
│ │ └─────────────────┘ │
│ │ │
│ └───────────────────────────────────────────────────┘
│ │
└─────────────────────────────────────────────────────────────────┘4.3 性能优化配置
# application.yml
spring:
# redis 配置
redis:
host: ${redis_host:localhost}
port: ${redis_port:6379}
password: ${redis_password:}
database: 0
lettuce:
pool:
max-active: 20
max-idle: 10
min-idle: 5
max-wait: 1000ms
shutdown-timeout: 100ms
# rabbitmq 配置
rabbitmq:
host: ${rabbitmq_host:localhost}
port: ${rabbitmq_port:5672}
username: ${rabbitmq_username:guest}
password: ${rabbitmq_password:guest}
virtual-host: /
# 确认模式
publisher-confirm-type: correlated
publisher-returns: true
# 消费者配置
listener:
simple:
acknowledge-mode: manual
prefetch: 10
concurrency: 5
max-concurrency: 10
retry:
enabled: true
max-attempts: 3
initial-interval: 1000ms
# 数据源配置
datasource:
url: jdbc:mysql://${db_host:localhost}:3306/ecommerce
username: ${db_username:root}
password: ${db_password:password}
hikari:
maximum-pool-size: 20
minimum-idle: 5
connection-timeout: 30000
idle-timeout: 600000
max-lifetime: 1800000
# 自定义配置
app:
cache:
ttl: 30m
order:
timeout: 30m
redis:
key-prefix: "app:"五、总结
通过本文的详细讲解,我们可以看到 spring boot、redis 和 rabbitmq 在现代分布式系统中各自扮演着重要角色:
- spring boot 提供了快速开发的能力,通过自动配置和丰富的 starter 简化了项目搭建和配置
- redis 作为高性能缓存和数据存储,显著提升了系统性能并提供了丰富的数据结构支持
- rabbitmq 实现了系统解耦和异步处理,提高了系统的可扩展性和可靠性
三者结合使用,可以构建出高性能、高可用、易扩展的现代分布式应用系统。在实际项目中,我们需要根据具体业务场景合理选择和使用这些技术,充分发挥它们的优势。
希望本文能够帮助大家更好地理解和使用 spring boot、redis 和 rabbitmq,在实际项目中构建出更加优秀的系统架构
到此这篇关于spring boot、redis、rabbitmq 在项目中的核心作用详解的文章就介绍到这了,更多相关spring boot、redis、rabbitmq 作用内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论