分布式实战

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 lambdaQueryWrapper = new 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";
}
posted @   lwx_R  阅读(1)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
点击右上角即可分享
微信分享提示