秒杀架构实践(中)

简介: 之前在 Java-Interview 中提到过秒杀架构的设计,这次基于其中的理论简单实现了一下。 本次采用循序渐进的方式逐步提高性能达到并发秒杀的效果

乐观锁更新


怎么来避免上述的现象呢?


最简单的做法自然是乐观锁了,这里不过多讨论这个,不熟悉的朋友可以看下这篇


来看看具体实现:


其实其他的都没怎么改,主要是 Service 层。


@Override
    public int createOptimisticOrder(int sid) throws Exception {
        //校验库存
        Stock stock = checkStock(sid);
        //乐观锁更新库存
        saleStockOptimistic(stock);
        //创建订单
        int id = createOrder(stock);
        return id;
    }
    private void saleStockOptimistic(Stock stock) {
        int count = stockService.updateStockByOptimistic(stock);
        if (count == 0){
            throw new RuntimeException("并发更新库存失败") ;
        }
    }


对应的 XML:


<update id="updateByOptimistic" parameterType="com.crossoverJie.seconds.kill.pojo.Stock">
        update stock
        <set>
            sale = sale + 1,
            version = version + 1,
        </set>
        WHERE id = #{id,jdbcType=INTEGER}
        AND version = #{version,jdbcType=INTEGER}
    </update>


同样的测试条件,我们再进行上面的测试 /createOptimisticOrder/1





这次发现无论是库存订单都是 OK 的。


查看日志发现:



很多并发请求会响应错误,这就达到了效果。


提高吞吐量


为了进一步提高秒杀时的吞吐量以及响应效率,这里的 web 和 Service 都进行了横向扩展。


  • web 利用 Nginx 进行负载。


  • Service 也是多台应用。




再用 JMeter 测试时可以直观的看到效果。


由于我是在阿里云的一台小水管服务器进行测试的,加上配置不高、应用都在同一台,所以并没有完全体现出性能上的优势( Nginx 做负载转发时候也会增加额外的网络消耗)。


shell 脚本实现简单的 CI


由于应用多台部署之后,手动发版测试的痛苦相信经历过的都有体会。


这次并没有精力去搭建完整的 CI CD,只是写了一个简单的脚本实现了自动化部署,希望对这方面没有经验的同学带来一点启发:


构建 web


#!/bin/bash
# 构建 web 消费者
#read appname
appname="consumer"
echo "input="$appname
PID=$(ps -ef | grep $appname | grep -v grep | awk '{print $2}')
# 遍历杀掉 pid
for var in ${PID[@]};
do
    echo "loop pid= $var"
    kill -9 $var
done
echo "kill $appname success"
cd ..
git pull
cd SSM-SECONDS-KILL
mvn -Dmaven.test.skip=true clean package
echo "build war success"
cp /home/crossoverJie/SSM/SSM-SECONDS-KILL/SSM-SECONDS-KILL-WEB/target/SSM-SECONDS-KILL-WEB-2.2.0-SNAPSHOT.war /home/crossoverJie/tomcat/tomcat-dubbo-consumer-8083/webapps
echo "cp tomcat-dubbo-consumer-8083/webapps ok!"
cp /home/crossoverJie/SSM/SSM-SECONDS-KILL/SSM-SECONDS-KILL-WEB/target/SSM-SECONDS-KILL-WEB-2.2.0-SNAPSHOT.war /home/crossoverJie/tomcat/tomcat-dubbo-consumer-7083-slave/webapps
echo "cp tomcat-dubbo-consumer-7083-slave/webapps ok!"
sh /home/crossoverJie/tomcat/tomcat-dubbo-consumer-8083/bin/startup.sh
echo "tomcat-dubbo-consumer-8083/bin/startup.sh success"
sh /home/crossoverJie/tomcat/tomcat-dubbo-consumer-7083-slave/bin/startup.sh
echo "tomcat-dubbo-consumer-7083-slave/bin/startup.sh success"
echo "start $appname success"


构建 Service


# 构建服务提供者
#read appname
appname="provider"
echo "input="$appname
PID=$(ps -ef | grep $appname | grep -v grep | awk '{print $2}')
#if [ $? -eq 0 ]; then
#    echo "process id:$PID"
#else
#    echo "process $appname not exit"
#    exit
#fi
# 遍历杀掉 pid
for var in ${PID[@]};
do
    echo "loop pid= $var"
    kill -9 $var
done
echo "kill $appname success"
cd ..
git pull
cd SSM-SECONDS-KILL
mvn -Dmaven.test.skip=true clean package
echo "build war success"
cp /home/crossoverJie/SSM/SSM-SECONDS-KILL/SSM-SECONDS-KILL-SERVICE/target/SSM-SECONDS-KILL-SERVICE-2.2.0-SNAPSHOT.war /home/crossoverJie/tomcat/tomcat-dubbo-provider-8080/webapps
echo "cp tomcat-dubbo-provider-8080/webapps ok!"
cp /home/crossoverJie/SSM/SSM-SECONDS-KILL/SSM-SECONDS-KILL-SERVICE/target/SSM-SECONDS-KILL-SERVICE-2.2.0-SNAPSHOT.war /home/crossoverJie/tomcat/tomcat-dubbo-provider-7080-slave/webapps
echo "cp tomcat-dubbo-provider-7080-slave/webapps ok!"
sh /home/crossoverJie/tomcat/tomcat-dubbo-provider-8080/bin/startup.sh
echo "tomcat-dubbo-provider-8080/bin/startup.sh success"
sh /home/crossoverJie/tomcat/tomcat-dubbo-provider-7080-slave/bin/startup.sh
echo "tomcat-dubbo-provider-8080/bin/startup.sh success"
echo "start $appname success"


之后每当我有更新,只需要执行这两个脚本就可以帮我自动构建。


都是最基础的 Linux 命令,相信大家都看得明白。


乐观锁更新 + 分布式限流


上文的结果看似没有问题,其实还差得远呢。


这里只是模拟了 300 个并发没有问题,但是当请求达到了 3000 ,3W,300W 呢?


虽说可以横向扩展可以支撑更多的请求。


但是能不能利用最少的资源解决问题呢?


其实仔细分析下会发现:


假设我的商品一共只有 10 个库存,那么无论你多少人来买其实最终也最多只有 10 人可以下单成功。


所以其中会有 99% 的请求都是无效的。


大家都知道:大多数应用数据库都是压倒骆驼的最后一根稻草。


通过 Druid 的监控来看看之前请求数据库的情况:


因为 Service 是两个应用。





数据库也有 20 多个连接。


怎么样来优化呢? 其实很容易想到的就是分布式限流


我们将并发控制在一个可控的范围之内,然后快速失败这样就能最大程度的保护系统。


相关文章
|
10天前
|
运维 负载均衡 监控
深入探索微服务架构的核心要素与实践策略
在当今软件开发领域,微服务架构已成为构建灵活、可扩展企业级应用的首选模式。本文旨在剖析微服务架构的设计理念,通过实例阐述其核心组件如服务注册与发现、配置管理、熔断机制等如何协同工作,以提升系统的敏捷性和维护性。同时,探讨了在实践中应对分布式系统复杂性的最佳策略,包括负载均衡、服务监控和日志聚合等关键技术,旨在为后端开发者提供一套完整的微服务实施指南。
29 1
|
19天前
|
运维 监控 API
深入浅出:微服务架构的设计与实践
在软件开发的世界中,微服务架构如同一股清新的风,吹散了单体应用带来的沉重与复杂。本文将带你走进微服务的世界,一探究竟,从理念到实践,我们一同领略微服务的魅力所在。
|
16天前
|
机器学习/深度学习 人工智能 自然语言处理
赋能百业:多模态处理技术与大模型架构下的AI解决方案落地实践
【9月更文挑战第4天】赋能百业:多模态处理技术与大模型架构下的AI解决方案落地实践
赋能百业:多模态处理技术与大模型架构下的AI解决方案落地实践
|
4天前
|
设计模式 Cloud Native API
云原生时代的微服务架构实践
【9月更文挑战第23天】在这篇文章中,我们将深入探讨云原生环境下的微服务架构设计原则、优势以及实施策略。文章不仅涉及理论概念,还结合具体的代码示例,帮助读者理解如何在实际项目中应用微服务架构。通过阅读本文,你将获得构建、部署和管理微服务的实用知识,为你的云原生项目奠定坚实的基础。
|
2天前
|
存储 运维 负载均衡
后端开发中的微服务架构实践与思考
本文旨在探讨后端开发中微服务架构的应用及其带来的优势与挑战。通过分析实际案例,揭示如何有效地实施微服务架构以提高系统的可维护性和扩展性。同时,文章也讨论了在采用微服务过程中需要注意的问题和解决方案。
|
7天前
|
缓存 NoSQL 数据库
构建高效后端服务:从架构设计到性能优化的实践之路
本文旨在探讨如何通过合理的架构设计和性能优化策略,构建一个既稳定又高效的后端服务。文章首先概述了后端服务开发中常见的挑战和误区,随后详细介绍了微服务架构、缓存机制、数据库优化、服务器配置以及代码审查等关键技术和方法。通过深入浅出的案例分析和实用建议,本文将为后端开发者提供一套系统化的指导方案,助力其打造出高性能的后端服务体系。
|
2天前
|
运维 持续交付 API
深入理解并实践微服务架构:从理论到实战
深入理解并实践微服务架构:从理论到实战
14 3
|
5天前
|
消息中间件 缓存 NoSQL
构建高效后端服务:微服务架构的深度实践
本文旨在探讨如何通过采用微服务架构来构建高效的后端服务。我们将深入分析微服务的基本概念、设计原则以及在实际项目中的应用案例,揭示其在提升系统可维护性、扩展性和灵活性方面的优势。同时,本文还将讨论在实施微服务过程中可能遇到的挑战,如服务治理、分布式事务和数据一致性等问题,并分享相应的解决策略和最佳实践。通过阅读本文,读者将能够理解微服务架构的核心价值,并具备将其应用于实际项目的能力。 ##
|
7天前
|
Kubernetes Cloud Native Serverless
探索云原生技术:从基础架构到应用实践
本文深入探讨了云原生技术的各个方面,包括其定义、核心原则、关键技术组件以及在现代企业中的应用。通过分析云原生如何推动数字化转型和提高业务敏捷性,文章旨在为读者提供对这一领域的全面了解和实际应用的指导。
33 7
|
5天前
|
人工智能 Cloud Native Java
新趋势、新开源、新实践|云栖大会 AI 原生应用架构专场邀您参会
新趋势、新开源、新实践|云栖大会 AI 原生应用架构专场邀您参会

热门文章

最新文章