分布式实战
0.背景
三台windows主机
都搭建了springboot环境,并启动相同的项目
1.负载均衡
通过同一个url访问不同的主机
nginx部署在ip1机器上
- nginx配置文件
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
upstream springboot_servers {
server ip1:10100; # 第一台Spring Boot服务
server ip2:10101; # 第二台Spring Boot服务
server ip3:10102; # 第三台Spring Boot服务
}
server {
listen 80;
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
proxy_pass http://springboot_servers;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
}
- 访问
http://ip1/test/test
2.重构为springcloud架构
- 父模块参考cloud2022
- gateway
<!--gateway-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!--客户端负载均衡loadbalancer-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
<!--nacos-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
server:
port: 10000
servlet:
encoding:
force: true
charset: UTF-8
enabled: true
spring:
main:
allow-circular-references: true
application:
name: gateway
cloud:
nacos:
discovery:
server-addr: ip:port
namespace: lwx
username: lwx
password: lwx
locator:
lower-case-service-id: true
register-enabled: true
gateway:
discovery:
locator:
enabled: true
routes:
- id: lwx
uri: lb://lwx
predicates:
- Path=/lwx/**
- 子模块example
构建在三台机器上
3.分布式数据一致性
思路:从数据库获取age字段 逻辑上做加一处理 再update到数据库,压测来查看结果
- update语句是原子性的,直接使用sql做加一处理一定可以保持数据一致性
3.1 不加锁
单一jvm内也是数据不一致
LambdaQueryWrapper<TBaseOrgunitDist> lambdaQueryWrapper = new LambdaQueryWrapper<TBaseOrgunitDist>()
.eq(TBaseOrgunitDist::getId, "1");
TBaseOrgunitDist one = disMapper.selectOne(lambdaQueryWrapper);
Integer age = one.getAge();
age = age + 1;
LambdaUpdateWrapper<TBaseOrgunitDist> lambdaUpdateWrapper = new LambdaUpdateWrapper<TBaseOrgunitDist>()
.eq(TBaseOrgunitDist::getId, "1")
.set(TBaseOrgunitDist::getAge, age);
disMapper.update(null,lambdaUpdateWrapper);
3.2 加单一JVM锁
使用synchronized
单一jvm数据一致 但是分布式下数据不一致
@GetMapping("/update")
public synchronized String update() {
LambdaQueryWrapper
.eq(TBaseOrgunitDist::getId, "1");
TBaseOrgunitDist one = disMapper.selectOne(lambdaQueryWrapper);
Integer age = one.getAge();
age = age + 1;
LambdaUpdateWrapper<TBaseOrgunitDist> lambdaUpdateWrapper = new LambdaUpdateWrapper<TBaseOrgunitDist>()
.eq(TBaseOrgunitDist::getId, "1")
.set(TBaseOrgunitDist::getAge, age);
disMapper.update(null,lambdaUpdateWrapper);
return "pgTest";
}
3.3 分布式锁
redssion的Rlock
数据一致
@Autowired
private RedissonClient redissonClient;
@GetMapping("/update")
public String update() {
// 分布式锁
RLock lock = redissonClient.getLock("myLock");
try {
// 尝试加锁,最多等待 10 秒,锁的过期时间为 30 秒
boolean isLocked = lock.tryLock(10, 30, java.util.concurrent.TimeUnit.SECONDS);
if (isLocked) {
// 加锁成功,执行业务逻辑
System.out.println("Lock acquired, executing business logic...");
LambdaQueryWrapper<TBaseOrgunitDist> lambdaQueryWrapper = new LambdaQueryWrapper<TBaseOrgunitDist>()
.eq(TBaseOrgunitDist::getId, "1");
TBaseOrgunitDist one = disMapper.selectOne(lambdaQueryWrapper);
Integer age = one.getAge();
age = age + 1;
LambdaUpdateWrapper<TBaseOrgunitDist> lambdaUpdateWrapper = new LambdaUpdateWrapper<TBaseOrgunitDist>()
.eq(TBaseOrgunitDist::getId, "1")
.set(TBaseOrgunitDist::getAge, age);
disMapper.update(null,lambdaUpdateWrapper);
System.out.println(age);
} else {
System.out.println("Failed to acquire lock");
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
// 释放锁
if (lock.isHeldByCurrentThread()) {
lock.unlock();
System.out.println("Lock released");
}
}
return "pgTest";
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律