当前位置:   article > 正文

高并发一些解决方案_并发量越高接口的异常率越高 如何解决呢为什么

并发量越高接口的异常率越高 如何解决呢为什么

0.0 亿级商品并发响应

  1. LVS+Nginx 集群,前后分离,静态资源放入Nginx下,网关Nginx限流
  2. 大数据数据压缩
  3. 分流限流(防刷,限制每个用户/s请求次数,令牌等,黑白名单),容灾降级(网络容灾,服务降级等等)
  4. 异步(mq)+并行(多线程)处理
  5. 多级缓存架构(本地缓存,redis缓存)
  6. 分库分表,es搜索引擎
  7. 服务弹性化,多机房多活,监控
  8. 多种压测方案

1.0 多级缓存架构图

在这里插入图片描述

2.0 秒杀库存超卖解决方案

在这里插入图片描述

3.0 redis 访问倾斜/数据倾斜解决方案

在这里插入图片描述

4.0 redis 缓存与数据库不一致问题

在这里插入图片描述

5.0 下单自动取消—saas系统多租户id,取消时间不是统一的,自定义—如果是rabbitmq 可以用插件delayed;

30分钟和1分钟,看各自项目如何设置。如果有些商家设置时间是9999分钟时,过大,这种可以配合下xxljob定时任务,每天执行,如果有当天的任务,就放进rabbitmq里面;—这种看各自服务的设置
在这里插入图片描述

6.0 redis缓存穿透

缓存穿透是指缓存和数据库中都没有的数据,而用户不断发起请求。
解决:
1:接口限流与熔断,降级
2:对于像ID为负数或者ID远远超过定义的大小的非法请求数据直接过滤掉
3:存在的id,放入redis布隆过滤器BitMap(假如有几亿条数据,一次性存入里面也不合理,可以根据hash算法模式,存入多个bigMap里面)
4:数据库和缓存都查询不到的情况下,把空值存入到缓存里面,增加短效时间内部

7.0 redis缓存击穿

缓存击穿,加入一个key是热点,当这个key在失效的瞬间,大批量的请求直接请求数据库,
解决:
1、设置热点数据永远不过期。
2、接口限流与熔断,降级。重要的接口一定要做好限流策略,防止用户恶意刷接口,同时要降级准备,当接口中的某些 服务 不可用时候,进行熔断,失败快速返回机制。
3、使用互斥锁,通过redis的setnx实现互斥锁,使得访问进数据库,只有一个请求

8.0 redis 雪崩

缓存雪崩是指缓存中数据大批量到过期时间,而查询数据量巨大,引起数据库压力过大甚至down机
解决:
1、缓存数据的过期时间设置随机,防止同一时间大量数据过期现象发生。
2、接口限流与熔断,降级
3、如果缓存数据库是分布式部署,将热点数据均匀分布在不同搞得缓存数据库中。
4、设置热点数据永远不过期。

9.0 如何提高调用第三方接口—请求合并

1:假如并发量多的情况,比如A服务调B服务商品,假如A并发量很大,每次请求A就去调B服务,对B服务压力也大,就推荐,A可以队列arrayblockingqueue+线程completablefuture,每隔5ms,去重商品ID,拿到ID集,在请求B服务,对B服务性能就大大提高,也降低网络io请求
2:项目本身也可以这样开发,假如对商品查询要求高,假如每次都进入服务器,增加Redis,mysql 性能压力,可以定时收集商品ID集来做查询;
在这里插入图片描述

 @Autowired
    private ICeShiService ceShiService;


    private CountDownLatch countDownLatch = new CountDownLatch(1);

    @Test
    void contextLoads() {
        System.out.println("ssssss");
        for (long i = 0; i < 1000L; i++) {
            long finalI = i;
            Thread thread = new Thread(() -> {
                try {
                    countDownLatch.await();
                    ceShiService.ceShi(finalI);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
            countDownLatch.countDown();
            thread.start();
        }
        try {
            Thread.sleep(100000L);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
class CeShiDemo{
        Long id;
        CompletableFuture<String> completableFuture;
    }

    ArrayBlockingQueue<CeShiDemo> arrayBlockingQueue = new ArrayBlockingQueue<CeShiDemo>(1024*1024);


    Object object = new Object();
    @Override
    public String ceShi(long id) {
        CompletableFuture<String> a = new CompletableFuture();
        CeShiDemo ceShiDemo = new CeShiDemo();
        ceShiDemo.id = id;
        ceShiDemo.completableFuture = a;
        try {
            arrayBlockingQueue.put(ceShiDemo);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        String s = "ssss";
        try {
           s = a.get();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
        return s ;
    }

    @Override
    public String ceShi2(long id) {
        sleepFF();
        return null;
    }

    private ScheduledExecutorService service = Executors.newScheduledThreadPool(1);

   
     @PostConstruct
    public void init(){
        service.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                synchronized(object) {
                    int size = arrayBlockingQueue.size();
                    System.out.println(System.currentTimeMillis()+";;;"+size+"长度");
                    if (size > 0) {
                        List<CeShiDemo> list = new ArrayList<>();
                        sleepFF();
                        for (int i = 0; i < size; i++) {
                            CeShiDemo poll = arrayBlockingQueue.poll();
                            // todo 调用第三方接口 这里也可以用批量请求模式,可以改造
                            //返回数据,唤醒信息,如果是列表,返回对应数据回去
                            poll.completableFuture.complete("我回来了" + poll.id);
                        }
                    } else {
                        return;
                    }
                }
            }
        },100,100,TimeUnit.MILLISECONDS);



    }


    public void sleepFF(){
        try {
            Thread.sleep(100L);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/blog/article/detail/50171
推荐阅读
相关标签
  

闽ICP备14008679号