Springboot仿抖音app开发之评论业务模块后端复盘及相关业务知识总结
Springboot仿抖音app开发之粉丝业务模块后端复盘及相关业务知识总结
Springboot仿抖音app开发之用户业务模块后端复盘及相关业务知识总结
Springboot仿抖音app开发之消息业务模块后端复盘及相关业务知识总结
Springboot仿抖音app开发之用短视频务模块后端复盘及相关业务知识总结
Springboot仿抖音app开发之RabbitMQ 异步解耦(进阶)
数值同步入库
在之前的项目中,我们关于数据库的选型分别将用户id,nickname等存在mysql中,er将计数,验证码这些符合redis特性的数据存在redis中,这样在原来数据库中用户的计数信息就会显示为0,我们想要在用户的计数信息显示相关数据,,需要进行数值同步入库

java
// 点赞完毕,获得当前在redis中的总数
// 比如获得总计数为 1k/1w/10w,假定阈值(配置)为2000
// 此时1k满足2000,则触发入库

配置中心就是nacos,我们通过控制台修改阈值而不需要在代码中对阈值进行修改,当点赞数达到阈值数量之后,则自动保存到数据库中。
nacos的作用是什么
1. 服务发现与注册
- 服务注册:各个微服务启动时自动向Nacos注册中心注册自己的服务信息(IP地址、端口号等)
- 服务发现:其他服务可以通过Nacos查找需要调用的服务实例
- 健康检查:定期检查注册的服务是否健康运行,自动剔除不健康的实例
2. 配置管理
- 集中配置:将所有微服务的配置文件统一存储在Nacos中
- 动态更新:支持配置的实时推送,无需重启服务即可更新配置
- 多环境管理:支持dev、test、prod等不同环境的配置隔离
- 配置版本控制:支持配置的版本管理和回滚
3. 命名空间隔离
- 多租户:通过命名空间实现不同项目或环境的完全隔离
- 资源管理:每个命名空间可以独立管理服务和配置
4. 负载均衡
- 多实例支持:同一服务可以部署多个实例
- 自动负载均衡:在多个服务实例间自动分发请求
Nacos就像是一个"服务电话簿" + "配置管理员"
1. 服务电话簿的作用 📞
想象您有一个大公司,有很多部门:
- 用户服务部门(处理用户注册登录)
- 订单服务部门(处理订单)
- 支付服务部门(处理支付)
没有Nacos时:
- 用户服务想找订单服务,必须记住订单服务的具体地址(比如:192.168.1.100:8080)
- 如果订单服务搬到新地址了,用户服务就找不到了
- 如果订单服务有多个分店,用户服务不知道该找哪一个
有了Nacos后:
- 所有服务启动时都在Nacos这个"电话簿"里登记:我是订单服务,我在XXX地址
- 用户服务要找订单服务时,问Nacos:"订单服务在哪里?"
- Nacos回答:"订单服务有3个地址,我给你一个最好的"
- 如果某个订单服务挂了,Nacos会自动把它从电话簿里删除
2. 配置管理员的作用 📋
没有Nacos时:
- 每个服务都有自己的配置文件
- 要改个数据库地址,需要一个个服务去改
- 改完还要重启所有服务
有了Nacos后:
- 所有配置都放在Nacos里统一管理
- 要改数据库地址,只在Nacos里改一次
- 所有相关服务会自动收到通知并更新,不用重启
3. 您项目中的实际例子
您的日志显示:
复制代码
nacos registry, DEFAULT_GROUP imooc-red-book-nacos 172.22.79.93:8099 register finished
这就是说:您的"红书项目"已经在Nacos电话簿里登记了,告诉Nacos:
- "我是红书服务"
- "我在172.22.79.93:8099这个地址"
- "其他服务可以通过'imooc-red-book-nacos'这个名字找到我"
现在如果您有其他服务(比如用户服务、图片服务等),它们就可以通过Nacos找到您的红书服务,而不需要记住具体的IP地址了!
微服务架构中的服务调用
在一个完整的红书应用中,通常会拆分成多个独立的服务,每个服务负责不同的功能:
可能的服务架构:
- 用户服务:处理用户注册、登录、个人信息
- 内容服务:处理笔记发布、编辑、删除
- 图片服务:处理图片上传、存储、处理
- 推荐服务:根据用户喜好推荐内容
- 评论服务:处理评论、点赞功能
- 消息服务:处理系统通知、私信
实际调用场景举例:
场景1:发布笔记
- 用户在前端发布一篇笔记
- 内容服务 收到请求,需要:
- 调用用户服务验证用户身份
- 调用图片服务上传和处理图片
- 调用推荐服务更新用户兴趣标签
场景2:查看笔记详情
- 用户点击查看某篇笔记
- 内容服务 需要:
- 调用用户服务获取作者信息
- 调用评论服务获取评论列表
- 调用推荐服务获取相关推荐
从您的项目来看
您的项目名是imooc-red-book-nacos
,从启动日志可以看到它包含了:
- MongoDB(存储数据)
- RabbitMQ(消息队列)
- MinIO(文件存储)
- Swagger(API文档)
这看起来像是一个主要的业务服务,其他服务可能需要调用它来:
- 获取用户发布的内容
- 获取图片资源
- 处理业务逻辑
简单比喻
就像一个购物中心:
- 您的红书服务是"商品展示中心"
- 用户服务是"会员中心"
- 支付服务是"收银台"
- 当用户要买东西时,收银台需要找到商品展示中心确认商品信息和价格
所以其他服务找红书项目,是为了获取它提供的数据和功能,完成完整的业务流程!
为什么同一个服务要在nacos上注册多个端口,这样的作用是什么
负载均衡和高可用性
简单比喻:餐厅的多个收银台
想象一个热门餐厅:
- 只有1个收银台:客人排长队,效率低,收银员累坏了
- 有3个收银台:客人分流,效率高,某个收银员休息也不影响营业
在微服务中的实际应用
场景:红书项目有大量用户访问
单实例部署(只有一个端口):
红书服务: 172.22.79.93:8099 ← 所有用户请求都打到这里
- 服务器压力大,可能卡顿或崩溃
- 如果这个服务挂了,整个应用就不能用了
多实例部署(多个端口):
红书服务实例1: 172.22.79.93:8099
红书服务实例2: 172.22.79.93:8100
红书服务实例3: 172.22.79.93:8101
具体好处:
1. 分担压力 💪
- 1000个用户请求可以分配给3个实例处理
- 每个实例只需要处理约333个请求
- 响应速度更快
2. 高可用性 🛡️
- 如果8099端口的服务挂了
- 用户请求会自动转到8100或8101
- 用户感觉不到任何异常
3. 平滑升级 🔄
- 升级时可以先停掉一个实例(比如8099)
- 其他实例继续提供服务
- 升级完成后再启动,用户无感知
Nacos的自动调度
当其他服务要调用红书服务时:
复制代码
用户服务: "Nacos,我要调用红书服务"
Nacos: "红书服务有3个实例可用,我给你分配8100端口这个"
图片服务: "Nacos,我也要调用红书服务"
Nacos: "我给你分配8101端口这个,平衡一下负载"
构建服务注册到Nacos
引入相关依赖,在yml文件中完成配置
java
# application:
# name: imooc-red-book-nacos
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848 # nacos 所在的地址
username: nacos
password: nacos
# 打开监控
management:
endpoint:
web:
exposure:
include: '*'
java
<!-- SpringCloud 依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>2020.0.4</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- SpringCloud Alibaba 依赖 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2.2.6.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
启动项目,我们看到nacos官网显示

服务集群注册到Nacos
我们在yml文件中修改一下端口号的配置就行
java
server:
port: ${port:8099}
我们可以看到有多个实例

Nacos 实现动态配置管理
bootstrap.yml
java
spring:
application:
name: imooc-red-book-nacos # 应用名称,用于在Nacos中标识配置
cloud:
nacos:
config:
server-addr: 127.0.0.1:8848 # Nacos服务器地址
file-extension: yaml # 配置文件格式
username: nacos # Nacos认证用户名
password: nacos # Nacos认证密码
具体作用和重要性
1. 优先级最高的配置加载
bootstrap.yml
是Spring Cloud应用中优先级最高的配置文件,它在application.yml
之前加载,确保:
- 应用启动时首先连接到Nacos配置中心
- 从Nacos获取的配置能够覆盖本地配置
- 解决配置依赖问题
2. 配置中心连接信息
java
spring:
application:
name: imooc-red-book-nacos # 应用名称,用于在Nacos中标识配置
cloud:
nacos:
config:
server-addr: 127.0.0.1:8848 # Nacos服务器地址
file-extension: yaml # 配置文件格式
username: nacos # Nacos认证用户名
password: nacos # Nacos认证密码
3. 配置文件查找规则
根据这个配置,应用会按以下规则在Nacos中查找配置:
- Data ID :
${spring.application.name}-${spring.profiles.active}.${file-extension}
- 对于您的项目:
imooc-red-book-nacos-dev.yaml
- Group: DEFAULT_GROUP(默认)
- Namespace: public(默认)
为什么需要bootstrap.yml?
1. 解决配置加载顺序问题
启动顺序:
bootstrap.yml → 连接Nacos → 获取远程配置 → application.yml → 应用启动
2. 避免循环依赖
如果将Nacos配置放在application.yml
中:
- 应用需要先加载本地配置才能连接Nacos
- 但又需要从Nacos获取配置来启动应用
- 形成循环依赖
3. 配置中心的基础连接信息
bootstrap.yml
通常只包含:
- 应用名称
- 配置中心连接信息
- 服务发现基础配置
实际工作流程
- 应用启动 → 读取
bootstrap.yml
- 连接Nacos → 使用配置的server-addr和认证信息
- 获取远程配置 → 下载
imooc-red-book-nacos-dev.yaml(后面注册的一项配置管理)
- 合并配置 → 远程配置 + 本地配置
- 启动应用 → 使用合并后的完整配置
我们来看测试接口
java
@Slf4j
@Api(tags = "Hello 测试的接口")
@RestController
@RefreshScope
public class HelloController {
@Value("${nacos.counts}")
private Integer nacosCounts;
@GetMapping("nacosCounts")
public Object nacosCounts() {
return GraceJSONResult.ok("nacosCounts的数值为:" + nacosCounts);
}
@ApiOperation(value = "hello-这是一个hello的测试路由")
@GetMapping("/hello")
public Object hello() {
return GraceJSONResult.ok("Hello");
}
核心注解的作用
1. @RefreshScope 注解
java
@RefreshScope
public class HelloController {
这是实现动态配置的关键注解:
- 标记该Bean支持配置刷新
- 当配置发生变化时,Spring会重新创建该Bean实例
- 重新注入最新的配置值
2. @Value 注解
java
@Value("${nacos.counts}")
private Integer nacosCounts;
动态读取配置值:
- 从配置中心读取
nacos.counts
的值 - 支持配置热更新
动态配置管理的完整流程
1. 初始化阶段
java
应用启动 → bootstrap.yml连接Nacos → 获取nacos.counts配置 → 注入到nacosCounts字段
2. 运行时动态更新
Nacos配置修改 → 推送变更通知 → Spring接收通知 → 重新创建@RefreshScope的Bean → 重新注入新配置值
具体工作机制
配置变更检测
// 当你在Nacos中将 nacos.counts 从 123 改为 456 时:
// 变更前
nacosCounts = 123 // 接口返回:nacosCounts的数值为:123
// Nacos推送变更通知后
nacosCounts = 456 // 接口返回:nacosCounts的数值为:456
Bean生命周期管理
java
// @RefreshScope 的工作原理:
1. 正常情况:HelloController Bean实例缓存在Spring容器中
2. 配置变更:Spring销毁旧的Bean实例
3. 重新创建:创建新的HelloController实例,重新注入最新配置
4. 请求处理:后续请求使用新实例和新配置值
我们来看测试用例

现在nacos中配置的计数是666,测试接口响应的也是666

我们修改nacos中的配置,将其变成123,再来进行测试

我们看到显示的结果页变成了123

动态配置的优势体现
1. 零停机更新
- 修改配置后立即生效
- 不影响正在处理的请求
- 用户无感知
2. 实时性
- 配置变更通常在几秒内生效
- 支持高频配置调整
- 适合业务参数优化
3. 可测试性
- 可以通过接口实时查看配置值
- 便于验证配置是否生效
- 支持快速回滚
统计数值阈值刷入数据库
1. 动态阈值配置
java
@Value("${nacos.counts}")
private Integer nacosCounts; // 从Nacos动态获取阈值,如2000
作用:
- 阈值可以通过Nacos配置中心动态调整
- 无需重启应用即可修改触发条件
- 支持不同环境使用不同阈值
2. Redis计数累积
java
// 每次点赞都会让Redis中的计数+1
redis.increment(REDIS_VLOG_BE_LIKED_COUNTS + ":" + vlogId, 1);
流程:
用户点赞 → Redis计数+1 → 检查是否达到阈值 → 触发批量入库
3. 阈值检查与批量入库
java
String countsStr = redis.get(REDIS_VLOG_BE_LIKED_COUNTS + ":" + vlogId);
Integer counts = 0;
if (StringUtils.isNotBlank(countsStr)) {
counts = Integer.valueOf(countsStr);
if (counts >= nacosCounts) { // 关键:阈值比较
vlogService.flushCounts(vlogId, counts); // 批量入库
}
}
完整的工作流程
1. 正常点赞流程
用户A点赞 → Redis: vlog:123 = 1
用户B点赞 → Redis: vlog:123 = 2
用户C点赞 → Redis: vlog:123 = 3
...
用户N点赞 → Redis: vlog:123 = 2000 ← 达到阈值
2. 触发入库条件
java
if (counts >= nacosCounts) { // 假设nacosCounts = 2000
// 当Redis中的计数 >= 2000时,触发数据库更新
vlogService.flushCounts(vlogId, counts);
}
3. 批量入库操作
java
@Transactional
public void flushCounts(String vlogId, Integer counts) {
Vlog vlog = new Vlog();
vlog.setId(vlogId);
vlog.setLikeCounts(counts); // 将Redis中的总计数写入数据库
vlogMapper.updateByPrimaryKeySelective(vlog);
}
Nacos拓展 IP漂移技术
VIP的定义
VIP是一个不固定绑定到特定物理网卡上的IP地址,它可以在多台服务器之间"漂移",实现服务的高可用性。
VIP的工作原理
简单比喻:
想象VIP就像一个"移动的门牌号":
- 有两栋房子(服务器A和B)
- 门牌号188(VIP)原本挂在A房子上
- 当A房子出问题时,门牌号自动移到B房子上
- 客人(用户)始终通过188这个门牌号找房子,不需要记住具体是哪栋房子
技术实现:
正常情况:
服务器A: 192.168.1.10 (真实IP) + 192.168.1.100 (VIP) ← 用户访问这个
服务器B: 192.168.1.11 (真实IP)
故障时:
服务器A: 192.168.1.10 (故障)
服务器B: 192.168.1.11 (真实IP) + 192.168.1.100 (VIP) ← VIP漂移到这里
VIP的作用
1. 透明切换
- 用户始终访问同一个IP地址(VIP)
- 后端服务器切换对用户完全透明
- 无需修改客户端配置
2. 高可用保障
- 主服务器故障时,VIP自动漂移到备用服务器
- 保证服务连续性
3. 简化管理
- 管理员只需管理一个对外IP
- 内部服务器可以随意增减或维护

ip漂移技术中,双击热备和双主热备的作用和区别是啥
双机热备 (Active-Standby)
作用:
- 高可用性保障:确保服务的连续性,当主服务器故障时能快速切换
- 故障恢复:自动检测主服务器状态,故障时启动备用服务器
- IP地址保持:通过VIP(虚拟IP)漂移,用户访问不受影响
工作原理:
正常状态:
主服务器A (活跃) ← VIP绑定在这里
备服务器B (待机) ← 监控主服务器状态
故障时:
主服务器A (故障)
备服务器B (接管) ← VIP漂移到这里
特点:
- 同一时间只有一台服务器提供服务
- 备用服务器资源利用率低(处于待机状态)
- 切换时间通常在几秒到几十秒
- 实现相对简单,成本较低
双主热备 (Active-Active)
作用:
- 负载分担:两台服务器同时工作,提高整体性能
- 资源充分利用:避免备用服务器资源浪费
- 更高的可用性:即使一台故障,另一台仍能承担全部负载
工作原理:
正常状态:
主服务器A (活跃) ← 处理50%流量
主服务器B (活跃) ← 处理50%流量
都绑定VIP或使用负载均衡
故障时:
主服务器A (故障)
主服务器B (活跃) ← 承担100%流量
特点:
- 两台服务器同时提供服务
- 资源利用率高
- 需要数据同步机制(如数据库主主复制)
- 实现复杂度更高
- 性能更好,可承担更大负载
主要区别对比
特性 | 双机热备 | 双主热备 |
---|---|---|
服务器状态 | 一主一备 | 双主同时工作 |
资源利用率 | 低(50%) | 高(接近100%) |
故障切换时间 | 几秒到几十秒 | 几乎无感知 |
数据一致性 | 相对简单 | 需要复杂的同步机制 |
实现复杂度 | 简单 | 复杂 |
性能 | 单机性能 | 双机性能 |
成本 | 较低 | 较高 |
适用场景 | 一般业务系统 | 高并发、关键业务 |
实际应用场景
双机热备适用于:
- 中小型企业应用
- 对性能要求不是特别高的系统
- 预算有限的项目
- 数据一致性要求严格的场景
双主热备适用于:
- 大型互联网应用
- 高并发、高性能要求的系统
- 7×24小时不间断服务
- 对用户体验要求极高的场景
IP漂移在两种模式中的应用
双机热备中的IP漂移:
- VIP从故障主机漂移到备用主机
- 通过VRRP、Heartbeat等协议实现
- 漂移过程中会有短暂的服务中断
双主热备中的IP漂移:
- 通常配合负载均衡器使用
- 可能有多个VIP或使用DNS轮询
- 某台服务器故障时,IP流量重新分配
- 服务基本无中断