关于高并发:高考成绩都出来了你的秒杀系统如何了

大家好,我是冰河~~ 高考问题都进去了,咱的《Seckill秒杀零碎》专栏如何了?明天给大家交个“期中作业”吧。 总体状况截止到目前,秒杀零碎从需要立项、架构设计、技术选型、环境搭建、编码实现、极致缓存设计到扣减库存防超卖设计,曾经实现16个大的篇章47篇文章。 这是不是更新完了?那必定没啊!尽管当初的秒杀零碎曾经实现了最外围的性能,然而还不是我现实中的样子,我想要大厂技术真正落地的秒杀零碎。咱做的是面向实在场景的秒杀零碎,应用的技术也是大厂中真正落地的技术,所以,咱的秒杀零碎内容还没有完结,波及到的核心技术如下图。 看到这张图后,小伙伴们肯定就明确了:尽管秒杀零碎曾经写了16个大的篇章,47篇文章了,然而基本就没有完结。因为大厂的秒杀零碎基本就没有这么简略的,如果47篇文章可能讲透并实现一个秒杀零碎,那这个所谓的秒杀零碎肯定是个Demo。然而咱们不做Demo,也杜绝做Demo,所以,这个秒杀零碎间隔完结还有一段时间! 专栏源码光说不练假把式,既然是带着大家做我的项目,那必定是少不了写代码,看看咱的代码吧,整体采纳DDD畛域驱动架构设计,在实战章节会每章对应一个代码分支,供小伙伴们对照章节练习。 值得注意的是:咱的代码里大量应用了设计模式,你能够在秒杀零碎里纵情感触设计模式的魅力。另外,因为咱做的秒杀零碎不是Demo,外面波及到的各种波及到高并发、高性能、高可扩大和高可保护的设计思维和编码实现,小伙伴们都能够使用到任何波及到高并发场景的业务零碎中。通过秒杀零碎,不仅仅能够从我的项目实战角度彻底把握高并发编程,更能亲自领会到大厂在高并发场景的应答之道。 视频安顿 冰河正在加班加点的为秒杀零碎录制对应的章节视频,其余专栏也必须安顿上,为的就是让大家更好的学习,更好的消化吸收,更好的学以致用。 好了,明天就到这儿吧,我是冰河,咱们下期见~~

June 30, 2023 · 1 min · jiezi

关于高并发:如何通过项目更好的学习并发编程

作者:冰河星球:http://m6z.cn/6aeFbs博客:https://binghe.gitcode.host文章汇总:https://binghe.gitcode.host/md/all/all.html源码获取地址:https://t.zsxq.com/0dhvFs5oR 积淀,成长,冲破,帮忙别人,成就自我。大家好,我是冰河~~ 明天,正式告诉大家一件事件:在今后一段时间内,冰河会带着大家一起从零开始搭建并开发一套可反对刹时百万流量的高并发秒杀零碎,这里会波及到很多互联网大厂开发过程中所应用的核心技术和架构设计模式,也有冰河在大厂工作过程中,自主研发和参加研发的企业级中间件技术。 在《Seckill秒杀零碎》专栏中,你学到的不仅仅是一套反对刹时百万流量的高并发、高性能、高可用、可扩大的秒杀零碎,更重要的是要学会大厂解决高并发、大流量场景的技术计划和架构设计思维,并学会如何将这些技术计划和架构设计思维落地到理论我的项目中。 一、秒杀专栏背景调研置信很多小伙伴学习了不少对于并发编程相干的基础知识,同时,不少小伙伴也看了冰河出版的《深刻了解高并发编程:外围原理与案例实战》与《深刻了解高并发编程:JDK核心技术》图书。当然,后续依据理论状况,可能会出版《深刻了解高并发编程》系列的其余书籍。然而很多小伙伴在和冰河交换的过程中,普遍存在如下几个问题: 始终在小公司做CRUD,并发编程没接触过,更别提如何高并发理论我的项目了。公司我的项目没什么并发,在线人数也不多,学了很多并发编程相干的常识不晓得怎么用。学了很多并发编程的常识,也晓得一些概念,能说出一些简略的计划,然而没理论我的项目教训。自我感觉把握了一些高并发编程的技术计划,然而如果真正做我的项目时,还是不晓得如何下手。简历上写了相熟并发编程,在面试过程中,面试官个别会问秒杀零碎,或者其余高并发我的项目实战问题,不晓得怎么答复。在大厂工作多年,参加了一些零碎的建设与研发,然而也没机会参加像秒杀零碎这样高并发、大流量的零碎的整个建设过程。其余问题。。。能够看到,从收集的这些并发编程相干的问题来看,存在的问题是普遍性的:小公司的小伙伴受限于业务,接触不到高并发、大流量的业务场景,大厂的小伙伴因为某些起因没有被分到高并发、大流量业务部门。但更多的是大体把握了并发编程的基础知识,而没有系统性落地成理论高并发我的项目的教训。 为了彻底解决小伙伴们的困惑,也为了进一步冲破大家的技术瓶颈,冰河带着他的《Seckill秒杀零碎》来了,在这里,你学到的不仅仅是一套反对刹时百万流量的高并发、高性能、高可用、可扩大的秒杀零碎,更重要的是要学会大厂解决高并发、大流量场景的技术计划和架构设计思维,并学会如何将这些技术计划和架构设计思维落地到理论我的项目中。。 二、为何要搞秒杀零碎说起秒杀零碎,我置信学习这个专栏的你肯定对秒杀零碎有所理解,甚至多多少少也参加了秒杀流动。为啥?因为国内头部电商平台每年的618、双11都会举办大促流动,置信你是参加过的,最起码你可能为这些流动奉献了流量。而每年的618、双11最直观的体现就是流量和交易额。 这些最直观的数字背地,却须要很多高并发编程的常识和技术作为撑持。作为程序员,或者说互联网技术人,尤其是理解一些并发编程技术和计划的开发者,肯定对每年618、双11大促背地的技术感兴趣。 单就秒杀零碎自身而言,它是高并发、大流量场景下最具代表性的零碎,如果你连秒杀零碎的各项技术细节都了然于胸了,那其余波及到并发的系统对你来说,还叫个事儿吗?另外,秒杀零碎背地波及到的高并发、高性能、高可用、可扩大的技术思路和架构模式与架构思维,你能够间接复用于任何须要撑持高并发、大流量的业务场景。 另外,个别只有互联网大厂才具备真正研发秒杀零碎的业务场景,所以,这次《Seckill秒杀零碎》专栏也是一次贴近大厂实在我的项目的机会,专栏中波及到的架构模式和技术点都是大厂在研发秒杀零碎过程中真正实际和优化过的架构模式与技术点,认真学习《Seckill秒杀零碎》专栏,认真消化吸收专栏中的每项知识点、技术思路和架构模式,并亲自动手实际每个并发编程的技巧和计划,置信你会有十分多的播种,而这些播种是实实在在的,也是互联网大厂常常应用的核心技术。 三、秒杀系统核心技术单就秒杀零碎自身而言,就是为应答刹时高并发、大流量场景而设计的反对高并发、大流量的零碎,其背地会波及到泛滥高并发、高性能、高可用的技术作为根底保障。同时,在零碎中,也要重点冲破库存与限购、防刷与风控、数据统一、热点隔离、动静拆散、削峰填谷、数据兜底、限流与降级、流控与容灾等核心技术问题。 所以,冰河总结了秒杀零碎所波及到的最外围的技术内容,整顿后如下图所示。 由图也能够看出,《Seckill秒杀零碎》专栏肯定不会让你悲观,它可能将真正的高并发编程常识串起来,造成知识面,并将这些高并发编程常识落地成秒杀零碎,而在开发秒杀零碎的过程中所应用到的技术,是互联网大厂真正在应用的核心技术。 留神:《Seckill秒杀零碎》专栏会大量应用到冰河出版的《深刻了解高并发编程:外围原理与案例实战》与《深刻了解高并发编程:JDK核心技术》图书中的常识,倡议学习《Seckill秒杀零碎》专栏的过程中,浏览《深刻了解高并发编程:外围原理与案例实战》与《深刻了解高并发编程:JDK核心技术》图书。 四、如何学习秒杀零碎1.退出 冰河技术 常识星球,能力查看星球专栏文章,查看置顶音讯,申请加入我的项目,能力看到我的项目代码和技术小册,如果未申请加入我的项目,点击我的项目链接,你会发现是404页面。 2.专栏的每一章会对应一个代码分支,须要切换对应的分支学习对应的文章的代码分支,同时,分支中的doc/assets/sql里是以后分支的最新SQL语句,在对应的分支查看SQL,更新到本人的数据库中即可。 3.学习过程中最好依照章节程序来学习,每一章前后都是比拟连贯的,并且每一章的代码实现也有先后顺序,这样依照从前往后的程序学习,最终你会实现一个残缺的秒杀零碎。 留神:学习的过程,不是复制粘贴代码的过程,赋值粘贴代码是没有任何意义的,最好的学习形式就是本人入手实现代码,而后思考、总结。 4.代码构造:master分支是最新的全量代码,专栏中每一章都会对应一个代码分支,切换到章节对应的代码分支后,即可依据以后章节学习对应的代码实现,不然,在master分支中看到的是全量的代码。 5.对应代码实现上的问题,能够在专栏对应的源码提issuse:https://gitcode.net/binghe001/seckill/-/issues。 6.冰河后续会为《Seckill秒杀零碎》专栏录制残缺的视频课程。 五、提交作业在学习秒杀零碎的过程中,为了有助于大家更好的消化吸收《Seckill秒杀零碎》的常识,冰河会为大家安排相应的作业。当然,也是为了心愿在学习的过程中,留下你实在的脚印,让咱们一起致力,冲破本身技术瓶颈。 1.代码作业作业空间:https://gitcode.net/seckillteam空间阐明:为常识星球的用户提供我的项目代码提交空间,不便针对我的项目进行技术交换,你能够把本人实现的《Seckill秒杀零碎》源码提交到空间中,依照 项目名称-用户星球编号-作者名称 的格局创立仓库,例如 seckill-1-binghe。 2.文字打卡大家能够在 冰河技术 常识星球中,提交文字作业也能够进行文字打卡,也能够到链接 https://gitcode.net/binghe001/seckill/-/issues 提交issues。次要依照如下形式进行总结: 1.明天你学了哪些章节?2.遇到的问题是什么?3.你是怎么解决问题的?4.明天的播种是什么? 基于大家的打卡或者作业反馈的问题,冰河会在后续以文章和直播的模式对立解决大家学习过程中的疑难。 写在最初对我的项目不太理解的小伙伴也能够到github:https://github.com/binghe001/distribute-seckill 进行理解,冰河会整顿局部源码和阐明到github,欢送各位小伙伴一起交换,一起学习,一起提高,在技术的路线上一起摸索,播种满满~~ 好了,明天就到这儿吧,我是冰河,咱们下期见~~

April 25, 2023 · 1 min · jiezi

关于高并发:横扫一线大厂面试的高并发笔记到底有多硬核

处处须要高并发 “为什么Java面试必问高并发?” 这个问题曾经让程序员们倍感头疼,尤其是想要跳槽到更大公司的程序员,是否丑陋的答复高并发的问题曾经成为求职者是否是一个优良程序员的评判规范,大厂面试尤为显著。 不得不说,高并发考验的就是程序员的实力和实战经验。随着流量变大,高并发曾经成为绕不开的话题,在解决高并发的时候,就会遇到越来越多的技术问题,例如接口响应超时、CPU load升高、死锁、GC频繁、大数据量存储等一系列问题。能够说,如果不会解决高并发,最初只能逐步被淘汰。所以,大厂的面试题里经常出现高并发也就不奇怪了。 因为文章篇幅无限,为了不耽搁大家贵重的工夫,这份PDF小编曾经为大家整顿好了,须要收费支付的敌人麻烦帮忙转发、转发、转发这篇文章(肯定要转发哦),而后【间接点击此处】即可收费获取。如何真正把握高并发第1章高并发时代的必备技能 随着5G利用、多终端利用、物联网利用、工业互联利用、大数据利用、人工智能利用的飞速发展,高并发开发时代未然到来,可能驾驭高并发和大数据的物联网架构师、高并发架构师、大数据架构师、Java高级工程师在人才市场也随之成为“香饽饽”,Netty、Redis、ZooKeeper、高性能HTTP服务器组件(如Nginx)、高并发Java组件(JUC包)等则成为宽广Java工程师所必须把握的开发技能 第2章 高并发IO的底层原理 本章从操作系统的底层原理动手,通过图文并茂的形式为大家深刻分析高并发IO的底层原理,并介绍如何通过设置来让操作系统反对高并发 第3章 Java NIO外围详解 高性能的Java通信相对离不开Java NIO组件,当初支流的技术框架或中间件服务器都应用了Java NIO组件,譬如Tomcat、Jetty、Netty。学习和把握Java NIO组件曾经不是一项加分技能,而是一项必备技能。 第4章 鼎鼎大名的Reactor模式 本书的准则是从根底讲起,而Reactor(反应器)模式是高性能网络编程在设计和架构层面的根底模式,算是根底的原理性知识。只有彻底理解反应器的原理,能力真正构建好高性能的网络应用、轻松地学习和把握高并发通信服务器与框架(如Netty框架、Nginx服务器)。 第5~8章重点解说Netty 目前Netty是高性能通信框架皇冠上当之无愧的明珠,是撑持其余泛滥驰名的高并发、分布式、大数据框架底层的框架。这几章从Reactor模式动手,以“四两拨千斤”的形式为大家介绍Netty原理。同时,还将介绍如何通过Netty来解决网络编程中的重点难题,如Protobuf序列化问题、半包问题等。 第9章 HTTP原理与Web服务器实战 本章介绍一个小的HTTP服务器程序——HTTP Echo回显服务器。 第10章 高并发HTTP通信的外围原理 HTTP是应用层协定,是建设在传输层TCP根底之上的。在通信过程中,TCP每一次连贯的建设和拆除都会经验三次握手和四次挥手,性能力和效率是比拟低的。HTTP一个显著的特点是无状态的,并且最后的设计初衷是用于短连贯场景,申请工夫连贯、申请完开释连贯,以尽快将开释服务资源供其余客户端应用。这就导致每一次原始HTTP协定的传输都须要进行连贯的建设和拆除,从而导致性能比拟低 第11章 WebSocket原理与实战 WebSocket协定的指标是在一个独立的长久连贯上提供全双工双向通信。客户端和服务器能够向对方被动发送和接收数据。WebSocket通信协议于2011年被IETF公布为RFC6455规范,后又公布了RFC7936规范补充标准。WebSocket API也被W3C(World Wide Web Consortium,万维网联盟)定为规范。 第12章 SSL/TLS外围原理与实战 SSL(Secure Sockets Layer,安全套接层)是1994年由网景公司为Netscape Navigator浏器设计和研发的平安传输技术。NetscapeNavigator浏览器是驰名的浏览器Firefox(Firefox是继Chrome和Safari之后最受欢迎的浏览器)的前身。 第13章 ZooKeeper分布式协调 高并发零碎为了应答流量增长须要进行节点的横向扩大,所以高并发零碎往往都是分布式系统。高并发零碎根本都须要进行节点与节点之间间的配合协调,这就须要用到分布式协调中间件(如ZooKeeper)。 ...

April 13, 2023 · 1 min · jiezi

关于高并发:并发提升-20-倍单节点数万-QPSApache-Doris-高并发特性解读

随着用户规模的极速扩张,越来越多用户将 Apache Doris 用于构建企业外部的对立剖析平台,这一方面须要 Apache Doris 去承当更大业务规模的解决和剖析——既蕴含了更大规模的数据量、也蕴含了更高的并发承载,而另一方面,也意味着须要应答企业更加多样化的数据分析诉求,从过来的统计报表、即席查问、交互式剖析等典型 OLAP 场景,拓展到举荐、风控、标签画像以及 IoT 等更多业务场景中,而数据服务(Data Serving)就是其中具备代表性的一类需要。Data Serving 通常指的是向用户或企业客户提供数据拜访服务,用户应用较为频繁的查问模式个别是依照 Key 查问一行或多行数据,例如: 订单详情查问商品详情查问物流状态查问交易详情查问用户信息查问用户画像属性查问...与面向大规模数据扫描与计算的 Adhoc 不同,Data Serving 在理论业务中通常出现为高并发的点查问—— 查问返回的数据量较少、通常只需返回一行或者大量行数据,但对于查问耗时极为敏感、冀望在毫秒内返回查问后果,并且面临着超高并发的挑战。 在过来面对此类业务需要时,通常采取不同的零碎组件别离承载对应的查问拜访。OLAP 数据库个别是基于列式存储引擎构建,且是针对大数据场景设计的查问框架,通常以数据吞吐量来掂量零碎能力,因而在 Data Serving 高并发点查场景的体现往往不迭用户预期。基于此,用户个别引入 Apache HBase 等 KV 零碎来应答点查问、Redis 作为缓存层来分担高并发带来的零碎压力。而这样的架构往往比较复杂,存在冗余存储、保护老本高的问题。交融对立的剖析范式为 Apache Doris 能承载的工作负载带来了挑战,也让咱们更加系统化地去思考如何更好地满足用户在此类场景的业务需要。基于以上思考,在行将公布的 2.0 版本中,咱们在原有性能根底上引入了一系列面向点查问的优化伎俩,单节点可达数万 QPS 的超高并发,极大拓宽了实用场景的能力边界。 #  如何应答高并发查问?始终以来高并发就是 Apache Doris 的劣势之一。对于高并发查问,其外围在于如何均衡无限的系统资源耗费与并发执行带来的高负载。换而言之,须要最大化升高单个 SQL 执行时的 CPU、内存和 IO 开销,其关键在于缩小底层数据的 Scan 以及随后的数据计算,其次要优化形式有如下几种: 分辨别桶裁剪Apache Doris 采纳两级分区,第一级是 Partition,通常能够将工夫作为分区键。第二级为 Bucket,通过 Hash 将数据打散至各个节点中,以此晋升读取并行度并进一步提高读取吞吐。通过正当地划分辨别桶,能够进步查问性能,以下列查问语句为例: select * from user_table where id = 5122 and create_date = '2022-01-01'用户以create_time作为分区键、ID 作为分桶键,并设置了 10 个 Bucket, 通过分辨别桶裁剪后可疾速过滤非必要的分区数据,最终只需读取极少数据,比方 1 个分区的 1 个 Bucket 即可疾速定位到查问后果,最大限度缩小了数据的扫描量、升高了单个查问的延时。 ...

March 23, 2023 · 3 min · jiezi

关于高并发:深入理解高并发编程JDK核心技术冰河新书上市

大家好,我是冰河~~ 废话说多了没用,并发编程技术始终是高级程序员进阶高级工程师的前提条件,也是成为大厂程序员的必备技能,更是冲破本身技术瓶颈的必经之路。 2022年6月我出版了“冰河技术丛书”之“深刻了解高并发编程”系列的第1部作品——《深刻了解高并发编程:外围原理与案例实战》,书中全面粗疏地介绍了高并发编程的基础知识、外围原理、实战案例和零碎架构等内容,帮忙读者从根本上了解并发编程呈现各种诡异Bug问题的本源,并从原理与实战层面找到解决问题的计划。随后这本书被翻译成繁体版——《深刻高平行開發:深度原理&專案實戰》进行发售。 明天,再次给大家隆重的发表一个好消息:继出版《海量数据处理与大数据技术实战》、《MySQL技术大全:开发、优化与运维实战》和《深刻了解分布式事务:原理与实战》、《深刻了解高并发编程:外围原理与案例实战》和《深刻高平行開發:深度原理&專案實戰》后,通过一年多的认真打磨,冰河的第6本图书——《深刻了解高并发编程:JDK核心技术》正式上市了。 写作背景2022年6月出版《深刻了解高并发编程:外围原理与案例实战》一书后,思来想去,隐约感觉书中尽管全面粗疏地介绍了高并发编程的基础知识、外围原理、实战案例和零碎架构等内容,可能帮忙读者从根本上了解并发编程呈现各种诡异Bug问题的本源,也可能从原理与实战层面找到解决问题的计划。然而,貌似还短少对于《深刻了解高并发编程:外围原理与案例实战》一书中提到的一些外围原理的深度落地实际分析。 那么问题来了:《深刻了解高并发编程:外围原理与案例实战》一书中,在外围原理篇具体介绍了并发编程的各种外围原理,那如何对这些外围原理的实际进行分析呢?再一个就是这些并发编程实际最好是大家都可能非常容易接触到的,这样,各位小伙伴就可能一边看书,一边实际了。 通过一段时间的调研,我把眼光聚焦到了JDK上,置信只有大家学习Java,就必定会接触JDK,而JDK中有很多并发编程工具类,各种并发编程类库,比方:并发容器类、并发阻塞队列、并发非阻塞队列、并发工具类、锁工具类、无锁原子类、线程工具类和线程池等等,都是JDK中对于并发编程外围原理的深度实际。并且JDK中这些并发编程的类库经验了理论生产环境中高并发、大流量的考验,是学习高并发编程十分好的实际案例,并且这些案例是任何一个学习Java的小伙伴非常容易取得的贵重资源。 所以,思来想去,最终将这本书聚焦到JDK上,并且为新书起了一个新的名字——《深刻了解高并发编程:JDK核心技术》,从名字上看,也可能看出,这是一本聚焦JDK并发编程核心技术的图书,并且是“冰河技术丛书”之“深刻了解高并发编程”系列的第2部作品,确定好书名和方向后,接下来,就是致力的去写作了。 本书全貌本书从理论需要登程,将全书分为三个大的篇章,别离是:JDK高并发编程的基础知识、外围工具和线程池核心技术。 第一篇 根底篇(第1~2章) 本篇简略地介绍了过程与线程的基本概念、线程调度与上下文切换、过程与线程的综合比照、如何查看过程与线程的运行时信息,以及线程和线程组的基本操作。 第二篇 外围工具篇(第3~13章) 本篇通过大量源码和案例具体介绍了JDK的各种并发工具,涵盖同步汇合、并发List汇合类、并发Set汇合类、并发Map汇合类、并发阻塞队列、并发非阻塞队列、并发工具类、锁工具类、无锁原子类、线程工具类和异步编程工具类。简直每个章节都配有JDK外围工具类的源码及实战案例,有助于读者了解。 第三篇 线程池核心技术篇(第14~16章) 本篇深刻分析了JDK中线程池的外围源码。包含线程池顶层接口和抽象类、线程池正确运行的外围流程、线程池执行工作的外围流程、Worker线程的外围流程、线程池优雅退出的外围流程、ScheduledThreadPoolExecutor类与Timer类的区别、定时工作线程池的初始化、调度流程和优雅敞开流程等。通过对本篇的学习,读者可能从源码级别深刻理解线程池的外围原理和执行流程。 为了进一步加深读者对线程池的了解,在本篇的随书源码中,会给出残缺的手写线程池的案例程序。 学完播种本书适宜:联网行业从业人员、高校师生、中高级开发人员、架构师、技术经理及技术专家和对高并发编程感兴趣的人员学习浏览。另外,因为本书是专一介绍JDK高并发编程技术的图书,强烈建议Java方向的小伙伴人手一册。 学完并把握书籍中的内容后,从此,你的简历上不再仅仅是简略的列举CRUD我的项目,还能够写上相熟或精通JDK中提供的各种并发编程类库,并且还能够具备本人手写一个线程池的能力。这下,你就能够和其他人在并发编程方面拉开差距了。 另外,“冰河技术丛书”之“深刻了解高并发编程”系列目前已出版两本图书,别离是《深刻了解高并发编程:外围原理与案例实战》和《深刻了解高并发编程:JDK核心技术》。后续依据理论状况,还会出版其余的并发书籍,如果想彻底深刻了解高并发编程,能够继续关注“冰河技术丛书”之“深刻了解高并发编程”系列图书。不仅仅是为你的简历和面试加分,更重要的是要让你彻底了解并发编程,为你的职业生涯保驾护航。 下手新书明天,冰河特意为大家申请了 5折优惠,名额不多,先到先得 ,兄弟们盘它,购买后退出图书专有读者群,由冰河自己亲自答疑解惑,我想把经验的真正大规模高并发我的项目架构与研发教训全副传授给你,跟冰河一起彻底深刻了解高并发编程。 https://u.jd.com/izMwOkE感激图书编辑:张晶、杨中兴 感激大佬举荐(排名局部先后):蒋涛(CSDN创始人、总裁)、邹欣(CSDN副总裁)、李海翔(腾讯数据库资深研究员、首席架构师)、林子熠(阿里巴巴JVM技术专家、CCF系统软件专委会执行委员)、于君泽(资深技术专家、公众号“技术琐话”作者)、沈剑(互联网架构专家,公众号“架构师之路”作者)、秦金卫(长亮科技平台技术部副总经理、Apache Dubbo/ShardingSphere PMC)、张开涛(《亿级流量网站架构核心技术》作者)、季敏(Seata开源社区创始人)、李鹏云(杭州任你说智能科技CTO)、程军(前饿了么技术总监,公众号“军哥手记”作者)、骆俊武(京东批发架构师)、纯净的微笑(公众号“纯净的微笑”作者)、黄哲铿/Mr.K(“顿悟山丘”征询创始人、公众号“技术领导力”作者)、李伟(Apache RocketMQ北京社区联结发起人 && Commiter)、翟永超(公众号“程序猿DD”维护者、《Spring Cloud微服务实战》作者)。 感激各位读者、粉丝敌人:始终以来对冰河的反对。 最初给大家上个长图。 好了,明天就到这儿吧,我是冰河,咱们下期见~~

March 17, 2023 · 1 min · jiezi

关于高并发:高并发系统设计的15个锦囊

记得很久之前,去面试过字节跳动。被三面的面试官问了一道场景设计题目:如何设计一个高并发零碎。过后我答复得比拟毛糙,最近回想起来,所以整顿了设计高并发零碎的15个锦囊,置信大家看完会有帮忙的。 如何了解高并发零碎所谓设计高并发零碎,就是设计一个零碎,保障它整体可用的同时,可能解决很高的并发用户申请,可能接受很大的流量冲击。 咱们要设计高并发的零碎,那就须要解决好一些常见的零碎瓶颈问题,如内存不足、磁盘空间有余,连接数不够,网络宽带不够等等,以应答突发的流量洪峰。 1. 分而治之,横向扩大如果你只部署一个利用,只部署一台服务器,那抗住的流量申请是十分无限的。并且,单体的利用,有单点的危险,如果它挂了,那服务就不可用了。 因而,设计一个高并发零碎,咱们能够分而治之,横向扩大。也就是说,采纳分布式部署的形式,部署多台服务器,把流量分流开,让每个服务器都承当一部分的并发和流量,晋升整体零碎的并发能力。 2. 微服务拆分(零碎拆分)要进步零碎的吞吐,进步零碎的解决并发申请的能力。除了采纳分布式部署的形式外,还能够做微服务拆分,这样就能够达到摊派申请流量的目标,进步了并发能力。 所谓的微服务拆分,其实就是把一个单体的利用,按性能单一性,拆分为多个服务模块。比方一个电商零碎,拆分为用户零碎、订单零碎、商品零碎等等。 3. 分库分表当业务量暴增的话,MySQL单机磁盘容量会撑爆。并且,咱们晓得数据库连接数是无限的。在高并发的场景下,大量申请拜访数据库,MySQL单机是扛不住的!高并发场景下,会呈现too many connections报错。 所以高并发的零碎,须要思考拆分为多个数据库,来抗住高并发的毒打。而如果你的单表数据量十分大,存储和查问的性能就会遇到瓶颈了,如果你做了很多优化之后还是无奈晋升效率的时候,就须要思考做分表了。个别千万级别数据量,就须要分表,每个表的数据量少一点,晋升SQL查问性能。 当面试官问要求你设计一个高并发零碎的时候,个别都要说到分库分表这个点。 4. 池化技术在高并发的场景下,数据库连接数可能成为瓶颈,因为连接数是无限的。 咱们的申请调用数据库时,都会先获取数据库的连贯,而后依附这个连贯来查问数据,搞完出工,最初敞开连贯,开释资源。如果咱们不必数据库连接池的话,每次执行SQL,都要创立连贯和销毁连贯,这就会导致每个查问申请都变得更慢了,相应的,零碎解决用户申请的能力就升高了。 因而,须要应用池化技术,即数据库连接池、HTTP 连接池、Redis 连接池等等。应用数据库连接池,能够防止每次查问都新建连贯,缩小不必要的资源开销,通过复用连接池,进步零碎解决高并发申请的能力。 同理,咱们应用线程池,也能让工作并行处理,更高效地实现工作。 5. 主从拆散通常来说,一台单机的MySQL服务器,能够反对500左右的TPS和10000左右的QPS,即单机撑持的申请拜访是无限的。因而你做了分布式部署,部署了多台机器,部署了主数据库、从数据库。 然而,如果双十一搞流动,流量必定会猛增的。如果所有的查问申请,都走主库的话,主库必定扛不住,因为查问申请量是十分十分大的。因而个别都要求做主从拆散,而后实时性要求不高的读申请,都去读从库,写的申请或者实时性要求高的申请,才走主库。这样就很好爱护了主库,也进步了零碎的吞吐。 当然,如果答复了主从拆散,面试官可能扩大开问你主从复制原理,问你主从提早问题等等,这块大家须要全方位温习好哈。 6. 应用缓存无论是操作系统,浏览器,还是一些简单的中间件,你都能够看到缓存的影子。咱们应用缓存,次要是晋升零碎接口的性能,这样高并发场景,你的零碎就能够反对更多的用户同时拜访。 罕用的缓存包含:Redis缓存,JVM本地缓存,memcached等等。就拿Redis来说,它单机就能轻轻松松应答几万的并发,你读场景的业务,能够用缓存来抗高并发。 缓存尽管用得爽,然而要留神缓存应用的一些问题: 缓存与数据库的一致性问题缓存雪崩缓存穿透缓存击穿7. CDN,减速动态资源拜访商品图片,icon等等动态资源,能够对页面做动态化解决,缩小拜访服务端的申请。如果用户散布在全国各地,有的在上海,有的在深圳,地区相差很远,网速也各不相同。为了让用户最快拜访到页面,能够应用CDN。CDN能够让用户就近获取所需内容。 什么是CDN? Content Delivery Network/Content Distribution Network,翻译过去就是内容散发网络,它示意将动态资源散发到位于多个地理位置机房的服务器,能够做到数据就近拜访,减速了动态资源的访问速度,因而让零碎更好解决失常别的动静申请。8. 音讯队列,削锋咱们搞一些双十一、双十二等经营流动时,须要防止流量暴涨,打垮利用零碎的危险。因而个别会引入音讯队列,来应答高并发的场景。 假如你的利用零碎每秒最多能够解决2k个申请,每秒却有5k的申请过去,能够引入音讯队列,利用零碎每秒从音讯队列拉2k申请解决得了。 有些搭档放心这样可能会呈现音讯积压的问题: 首先,搞一些经营流动,不会每时每刻都那么多申请过去你的零碎(除非有人歹意攻打),高峰期过来后,积压的申请能够缓缓解决;其次,如果音讯队列长度超过最大数量,能够间接摈弃用户申请或跳转到谬误页面;9. ElasticSearchElasticsearch,大家都应用得比拟多了吧,个别搜寻性能都会用到它。它是一个分布式、高扩大、高实时的搜寻与数据分析引擎,简称为ES。 咱们在聊高并发,为啥聊到ES呢?因为ES能够扩容不便,人造撑持高并发。当数据量大的时候,不必动不动就加机器扩容,分库等等,能够思考用ES来反对简略的查问搜寻、统计类的操作。 10. 降级熔断熔断降级是爱护零碎的一种伎俩。以后互联网零碎个别都是分布式部署的。而分布式系统中偶然会呈现某个根底服务不可用,最终导致整个零碎不可用的状况, 这种景象被称为服务雪崩效应。 比方分布式调用链路A->B->C....,下图所示: 如果服务C呈现问题,比方是因为慢SQL导致调用迟缓,那将导致B也会提早,从而A也会提早。堵住的A申请会耗费占用零碎的线程、IO、CPU等资源。当申请A的服务越来越多,占用计算机的资源也越来越多,最终会导致系统瓶颈呈现,造成其余的申请同样不可用,最初导致业务零碎解体。为了应答服务雪崩, 常见的做法是熔断和降级。最简略是加开关管制,当上游零碎出问题时,开关关上降级,不再调用上游零碎。还能够选用开源组件Hystrix来反对。 你要保障设计的零碎能应答高并发场景,那必定要思考熔断降级逻辑进来。 11. 限流限流也是咱们应答高并发的一种计划。咱们当然心愿,在高并发大流量过去时,零碎能全副申请都失常解决。然而有时候没方法,零碎的CPU、网络带宽、内存、线程等资源都是无限的。因而,咱们要思考限流。 如果你的零碎每秒扛住的申请是一千,如果一秒钟来了十万申请呢?换个角度就是说,高并发的时候,流量洪峰来了,超过零碎的承载能力,怎么办呢? 这时候,咱们能够采取限流计划。就是为了爱护零碎,多余的申请,间接抛弃。 什么是限流:在计算机网络中,限流就是管制网络接口发送或接管申请的速率,它可避免DoS攻打和限度Web爬虫。限流,也称流量管制。是指零碎在面临高并发,或者大流量申请的状况下,限度新的申请对系统的拜访,从而保证系统的稳定性。能够应用Guava的RateLimiter单机版限流,也能够应用Redis分布式限流,还能够应用阿里开源组件sentinel限流。 面试的时候,你说到限流这块的话?面试官很大概率会问你限流的算法,因而,大家在筹备面试的时候,须要温习一下这几种经典的限流算法哈 12. 异步回顾一下什么是同步,什么是异步呢?以办法调用为例,它代表调用方要阻塞期待被调用办法中的逻辑执行实现。这种形式下,当被调用办法响应工夫较长时,会造成调用方短暂的阻塞,在高并发下会造成整体零碎性能降落甚至产生雪崩。异步调用恰恰相反,调用方不须要期待办法逻辑执行实现就能够返回执行其余的逻辑,在被调用办法执行结束后再通过回调、事件告诉等形式将后果反馈给调用方。因而,设计一个高并发的零碎,须要在失当的场景应用异步。如何应用异步呢?后端能够借用音讯队列实现。比方在海量秒杀申请过去时,先放到音讯队列中,疾速响应用户,通知用户申请正在解决中,这样就能够开释资源来解决更多的申请。秒杀申请解决完后,告诉用户秒杀抢购胜利或者失败。 13. 接口的惯例优化设计一个高并发的零碎,须要设计接口的性能足够好,这样零碎在雷同工夫,就能够解决更多的申请。当说到这里的话,能够跟面试官说说接口优化的一些计划了。 14. 压力测试确定零碎瓶颈设计高并发零碎,离不开最重要的一环,就是压力测试。就是在零碎上线前,须要对系统进行压力测试,测分明你的零碎撑持的最大并发是多少,确定零碎的瓶颈点,让本人心里有底,最好预防措施。 压测完要剖析整个调用链路,性能可能呈现问题是网络层(如带宽)、Nginx层、服务层、还是数据路缓存等中间件等等。 ...

January 7, 2023 · 1 min · jiezi

关于高并发:InterruptedException异常会对并发编程产生哪些影响

写在后面InterruptedException异样可能没你想的那么简略!前言当咱们在调用Java对象的wait()办法或者线程的sleep()办法时,须要捕捉并解决InterruptedException异样。如果咱们对InterruptedException异样处理不当,则会产生咱们意想不到的结果! 程序案例例如,上面的程序代码,InterruptedTask类实现了Runnable接口,在run()办法中,获取以后线程的句柄,并在while(true)循环中,通过isInterrupted()办法来检测以后线程是否被中断,如果以后线程被中断就退出while(true)循环,同时,在while(true)循环中,还有一行Thread.sleep(100)代码,并捕捉了InterruptedException异样。整个代码如下所示。 package io.binghe.concurrent.lab08;/** * @author binghe * @version 1.0.0 * @description 线程测试中断 */public class InterruptedTask implements Runnable{ @Override public void run() { Thread currentThread = Thread.currentThread(); while (true){ if(currentThread.isInterrupted()){ break; } try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } }}上述代码的本意是通过isInterrupted()办法查看线程是否被中断了,如果中断了就退出while循环。其余线程通过调用执行线程的interrupt()办法来中断执行线程,此时会设置执行线程的中断标记位,从而使currentThread.isInterrupted()返回true,这样就可能退出while循环。 这看上去没啥问题啊!但真的是这样吗?咱们创立一个InterruptedTest类用于测试,代码如下所示。 package io.binghe.concurrent.lab08;/** * @author binghe * @version 1.0.0 * @description 测试线程中断 */public class InterruptedTest { public static void main(String[] args){ InterruptedTask interruptedTask = new InterruptedTask(); Thread interruptedThread = new Thread(interruptedTask); interruptedThread.start(); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } interruptedThread.interrupt(); }}咱们运行main办法,如下所示。 ...

November 25, 2022 · 1 min · jiezi

关于高并发:图解-聊聊秒杀

1.需要剖析“秒杀”这个词在电商行业中呈现的频率较高,如京东或者淘宝平台的各种“秒杀”流动,最典型的就是“双11抢购”。 “秒杀”是指在无限的工夫内对无限的商品数量进行抢购的一种行为,这是商家以“高价量少”的商品来获取用户的一种营销伎俩。 01. 功能性需要其实,整个秒杀的业务场景并不简单,可即查看参加秒杀的商品信息,加上购买和领取的动作,如下图所示。 秒杀业务最大的挑战在于3点: 刹时:持续时间极短,对于热门且具备极强竞争力的商品通常只有一秒。流量微小:因为价格低廉,商品性价比高,而且失常买是须要很高的价格,所以才会吸引大量的用户来争抢。数量无限:因为商品的高价且性价比高,所以只有很无限的商品数量参加秒杀。同时,在保障高并发流量承接的前提下,为了加强用户的体验和流动规定的公平性,以及避免受到歹意毁坏等,特此减少如下需要: (1)用户在秒杀页面无需始终刷新“抢购”按钮,待秒杀流动开始时,按钮主动点亮。 (2)在偏心以及避免歹意毁坏的准则下,在下单之前减少验证码的录入,或者答题的相干环节。 (3)库存不能呈现问题,即不多扣也不少扣。 (4)整个秒杀流动过程继续10分钟。 02. 性能指标预估通过秒杀的需要形容可得出,以后秒杀流动次要须要预估三块的性能指标:存储容量、并发量、网络带宽。 1)存储容量因为是秒杀流动,且参加的商品根本都是高价高性价比的,数量是十分无限的。所以,在订单存储上根本不必去过多思考。 2)并发量针对5000万用户均匀每人拜访2次,则并发量为每秒16.7万左右(5000w2/1060),在预留一部分,能够预估到每秒25万左右(也能够进行double下)。 3)网络带宽在带宽方面,须要进行相干优化,采取数据传输越少越好,假如单条传输在0.5KB,则依据并发量预估网络带宽为:977Mb左右(25w0.5KB=122MB8bit=977Mb)。 03. 非功能性需要做任何零碎都要思考非功能性需要,特地是公司的外围零碎,以后秒杀业务零碎非功能性需要次要体现在如下几点: 高可用,在秒杀流动的整个继续期间内,都能对用户提供服务。高性能,让每个用户都能感触到极快的秒杀响应,不能呈现大批量用户提早较高的景象。可扩大,当流量比预期更高时,有平滑扩大的策略(也有局部产品设计成敌对的回绝策略)。2.概要设计通过对秒杀业务的自身认知以及下面提到的秒杀业务需要,本次秒杀零碎须要着重设计如下几点: (1)动静拆散:如何保障用户在不刷新页面的状况下,仍然能进行秒杀相干数据的获取且不会耽搁秒杀流动的开始。 (2)流量分层,针对微小流量,如何进行无效的防控,免得造成后盾服务的不堪重负,以及如何防止前端页面的卡死。 (3)高可用:如何确保后盾继续提供服务。 (4)扣减库存:如何无效扣减库存。 01. 动静拆散动静拆散是指,将动态页面与动静页面(或者静态数据与动态数据)解耦拆散,用不同零碎承载对应流量。这样能够晋升整个服务拜访性能和可维护性。 商品秒杀页面的静态数据以及动态数据,均是不同的中央提供,如下图所示。 静态数据是指,页面中简直不怎么变动的数据(即不根据用户的Cookie、根本信息、地区,及工夫等各种属性来生成的数据),例如: CSS和JavaScript中的动态文件。流动页中的HTML动态文件。图片等相干资源文件。其余与用户信息无关的静态数据。对于这种分离出来的静态数据能够进行缓存。在缓存之后,这些静态数据的拜访效率就进步了,零碎也更快了。能够应用代理服务器进行静态数据的缓存。 动态数据是指,根据以后用户属性动静生成的数据,在浏览淘宝首页时,每个用户所看到的商品都是不一样的,这就是淘宝的“千人千面”——针对不同用户做不同的举荐;在百度搜寻中是根据不同用户的输出条件,以及用户的习惯给出不同的后果页。这其中的数据就是动态数据。 02. 流量分层在“秒杀”业务中,商品价格具备弱小的吸引力,所以会受到很多用户的关注,然而商品数量是无限的。所以,在千万的用户中可能只有100人能失去商品,对于零碎来说,有90%以上的流量属于有效流量。 “秒杀”业务心愿有大量的用户来关注“秒杀”流动,然而在用户真正下单时又不能将这些流量全副放过,所以,须要设计一套高效的流量管控计划,来无效地管制申请流量,过滤掉没必要的流量。 对于刹时流量洪峰能够采纳倒三角的分层级逐层管制形式,共分为CDN、反向代理(Nginx)、后端服务及DB这四个层级。接下来,就来看看每一层级是怎么管制流量的,如下图所示。 03. 高可用要想在整个“秒杀”流动继续期间内,仍然能对用户提供良好的体验,则秒杀零碎架构在设计时不能设计成单节点的架构。 单节点是所有零碎设计中的大忌,因为单节点零碎意味着零碎的不稳定性较高,可能会呈现不可用的状况,会给企业带来间接的损失。在零碎设计(特地是“秒杀”这类对高并发要求极高的零碎)时,必须保证系统的高可用,如下图所示。 04. 扣减库存对于“秒杀”流动,通常,公司是不容许商品超卖(即下单胜利的数量不能大于商品存存数量)的。一旦超卖,则会给公司造成损失。如果被歹意流量利用,则损失是微小的。 库存对于电商平台来说是一个重要的业务指标,所以在技术上须要正当设计扣减库存,不能呈现“超卖”景象。通常,扣减库存常有以下3种形式: 下单扣库存:在用户下单后就扣减库存。领取扣库存:用户付完款后再扣减库存。预扣库存:在用户下完订单后,零碎会为其锁定库存一段时间,在超过锁定工夫后会主动开释锁定的库存。05. 零碎架构设计依据下面探讨,针对以后秒杀架构如下图所示。 如上架构比拟简洁,次要分为以下5层。 用户层:用户端的展示局部,次要波及商品的相干信息及以后“秒杀”流动的信息。CDN层:缓存“秒杀”流动的动态资源文件。负载平衡层:拦挡申请及散发路由等。服务层:“秒杀”流动的具体交易的相干逻辑解决。基础设施层:数据存储、大数据计算及音讯推送相干操作。其部署架构图如下: 3.具体设计01. 动静拆散设计 施行动静拆散架构能够采纳“分而治之”的方法,行将动态数据和静态数据解耦,别离应用各自的架构零碎来承载对应的流量: 对于静态数据,举荐缩短用户申请门路,因为门路越短,访问速度也就越快。另外,即尽可能将静态数据缓存起来。对于动态数据,个别用户端须要和服务端进行交互能力获取,所以,申请门路较长,访问速度会慢一点。下图展现了动静拆散计划。静态数据访问速度很快,而动态数据访问速度较慢。那么试想下,能够将须要动静获取的数据给提前生成好,而后应用动态页面减速技术来拜访吗?如果这样能够,那动态数据拜访的速度就变快了。 这样是能够的,须要用到比拟风行的“页面动态化”技术。页面动态化技术是指,间接缓存HTTP连贯,而不仅是缓存数据。如下图所示,代理服务器依据申请的URL间接将HTTP对应的响应头及响应音讯体返回,流程简洁且高效。 02. 流量分层设计流量分层次要体现在对于CDN层、反向代理层、后端服务层以及数据层流量进行管制。 1)CDN层流量管制由动静拆散技术能够想到:应尽量将尽可能多的数据提前生成,而后将其放入CDN节点缓存中(因为CDN层在物理架构上离用户比拟近)。 所以,如果绝大部分的流量都在这一层获取数据,则达到后端的流量会缩小很多,如下图所示。 2)反向代理层流量管制在动静拆散计划中,讲到通过“页面动态化技术”减速动态数据的获取,即提前将动态数据生成好,而后对其进行动态化解决。 所以,这里就能够根据页面动态化减速技术,通过后端服务Job的形式定时提前生成前端须要动态的数据;而后,将其发送到内容散发服务上;最初,散发服务会将这些动态化页面数据散发到所有的反向代理服务器上,如下图所示。 在“秒杀”业务中,流动详情页上有一个倒计时的模块,用户能够看到以后“秒杀”流动还残余多少工夫开始。 这种逻辑简略的性能能够间接应用Nginx来实现:利用nginx-lua插件,应用lua脚本获取以后Nginx服务器的工夫进行计算倒计时。 另外,商品库存数据也能够通过Nginx间接拜访分布式缓存来获取,如下图所示。 “秒杀”业务中的商品价格很低,对于用户有很大的吸引力,所以可能会有人利用“秒杀器”进行不公平竞争,且有可能存在竞争对手歹意刷申请的状况。 如果存在这样的状况,那本次流动就是有危险的,万一被歹意流量独占了库存,则会导致失常用户不能抢购商品,也有可能这种歹意的申请会对后端系统造成重大冲击,甚至造成后端系统瘫痪。 对于这种歹意申请,最好有一套机制能提前感知,并将歹意申请提前封存。能够在Nginx层中管制;也能够在Nginx中配置用户的拜访频率(例如每分钟只能拜访10次);还能够应用Lua脚本编写一些简略业务逻辑的接口,例如,通过调用接口间接封掉指定IP地址或UserAgent的申请。 ...

October 30, 2022 · 1 min · jiezi

关于高并发:高并发深度解析ScheduledThreadPoolExecutor类的源代码

在【高并发专题】的专栏中,咱们深度剖析了ThreadPoolExecutor类的源代码,而ScheduledThreadPoolExecutor类是ThreadPoolExecutor类的子类。明天咱们就来一起手撕ScheduledThreadPoolExecutor类的源代码。 构造方法咱们先来看下ScheduledThreadPoolExecutor的构造方法,源代码如下所示。 public ScheduledThreadPoolExecutor(int corePoolSize) { super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS, new DelayedWorkQueue());}public ScheduledThreadPoolExecutor(int corePoolSize, ThreadFactory threadFactory) { super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS, new DelayedWorkQueue(), threadFactory);}public ScheduledThreadPoolExecutor(int corePoolSize, RejectedExecutionHandler handler) { super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS, new DelayedWorkQueue(), handler);}public ScheduledThreadPoolExecutor(int corePoolSize, ThreadFactory threadFactory, RejectedExecutionHandler handler) { super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS, new DelayedWorkQueue(), threadFactory, handler);}从代码构造上来看,ScheduledThreadPoolExecutor类是ThreadPoolExecutor类的子类,ScheduledThreadPoolExecutor类的构造方法实际上调用的是ThreadPoolExecutor类的构造方法。 schedule办法接下来,咱们看一下ScheduledThreadPoolExecutor类的schedule办法,源代码如下所示。 public ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit) { //如果传递的Runnable对象和TimeUnit工夫单位为空 //抛出空指针异样 if (command == null || unit == null) throw new NullPointerException(); //封装工作对象,在decorateTask办法中间接返回ScheduledFutureTask对象 RunnableScheduledFuture<?> t = decorateTask(command, new ScheduledFutureTask<Void>(command, null, triggerTime(delay, unit))); //执行延时工作 delayedExecute(t); //返回工作 return t;}public <V> ScheduledFuture<V> schedule(Callable<V> callable, long delay, TimeUnit unit) //如果传递的Callable对象和TimeUnit工夫单位为空 //抛出空指针异样 if (callable == null || unit == null) throw new NullPointerException(); //封装工作对象,在decorateTask办法中间接返回ScheduledFutureTask对象 RunnableScheduledFuture<V> t = decorateTask(callable, new ScheduledFutureTask<V>(callable, triggerTime(delay, unit))); //执行延时工作 delayedExecute(t); //返回工作 return t;}从源代码能够看出,ScheduledThreadPoolExecutor类提供了两个重载的schedule办法,两个schedule办法的第一个参数不同。能够传递Runnable接口对象,也能够传递Callable接口对象。在办法外部,会将Runnable接口对象和Callable接口对象封装成RunnableScheduledFuture对象,实质上就是封装成ScheduledFutureTask对象。并通过delayedExecute办法来执行延时工作。 ...

October 24, 2022 · 3 min · jiezi

关于高并发:高并发场景微服务实战一

高并发场景微服务实战(一)你好,我是程序员Alan,很快乐遇见你. 说到高并发和微服务,你是不是和我一样有很多的困惑? 晓得微服务开发热门,但始终是在行看热闹,不晓得外面具体有哪些内容。晓得高并发零碎开发常识,是获取大厂Offer的利器,可是工作中遇不到高并发的需要场景。理解过微服务开发、高并发零碎开发实践,苦于没实战经验。晓得单个技术点的利用,但怎么将技术交融起来有些含糊。为了解决本人的这些困惑,将微服务架构开发体系,高并发零碎设计体系串联起来。在面对新机会时能把握住机会,在理论产品开发中,能做到胸有成竹。 我重复思考之后,决定以一个虚构的高并发场景的微服务零碎为主线,一步步将技术点串联起来,多线程 -> 高并发 -> 服务注册 -> 服务发现 -> 服务接口治理 -> 配置核心 -> 分布式事务 -> 对立网关 -> 服务限流降级 -> 性能测试等,一个点一个点缓缓啃,由点成线,由线成面, 系统性从 0 到 1 的发明一个高并发场景的微服务零碎。通过,场景 -> 原理 -> 实际 -> 压测 -> 发现问题 -> 学习常识 -> 优化零碎,周而复始。来帮忙本人更快、更深刻地了解和消化。 为了帮忙其余有这些困惑的敌人,我会一步步把本人的设计和实现过程记录下来,把散落在网络上各处的知识点整合起来,缩小大家筛选梳理这些常识所要花费的大量工夫老本。 最初我再具体说一下本人为什么要学习高并发零碎设计和微服务开发,供大家参考。 求职时加强技术自信。咱们都能显著的感触到往年是互联网的寒冬,经济局势很不好。很多公司都降本增效,也就是裁员、缩小招聘的人员数量,另一方面又冀望咱们打工人能够给公司带来更大的价值。 那么对于公司来说,仅仅懂得 CRUD, 简历中不足亮点的程序员,就不如有高并发、微服务零碎设计教训和有架构能力的程序员有吸引力了。 晋升技术实力,减少职业转型的可能性。减少职业转型的可能:在介绍工作和工作技能时,我和敌人经常会自嘲的称本人为互联网民工、搬砖的,只会 CV 和 CRUD。这是自嘲,也是写实。因为咱们都只是公司里一颗小小的螺丝钉长期从事部分性能开发。然而软件系统是一个简单工程,只有从更高的角度统观全局,思考业务的方方面面以及将来可能的演进方向,能力深刻理解一个产品或我的项目的外在含意,而这个话语权往往把握在更高职级的开发者、设计师、架构师手中,如果把握了一套微服务架构、开发理念,减少了向更高职级降职的可能性。 晋升技术实力:计算机领域里尽管知识点庞杂,但很多核心思想都是相通的。高并发零碎设计和微服务零碎开发的技术和设计思维,无论是对于初入职场的工程师还是对于有肯定工作教训的同学来说都有很大的帮忙。 解决工作中软件研发难题。微服务:随着公司业务复杂度和用户量的晋升,单体利用,大量性能代码沉积在一起,显得特地臃肿繁冗,开发保护老本很高。这在日常运维、降级保护时十分不便,一个小性能的变更都有可能导致整个工程呈现问题甚至宕机,如果是运行中的生产环境解体,由此所造成的经济损失或不好的社会影响,将是不可估量的。而引入微服务,能够更好的解决这一系列的问题。 高并发:即便公司业务流量安稳,并不示意不会遇到一些高并发的需要场景。同样是缓存的应用,在低并发下只须要理解根本的应用形式,但在高并发场景下须要关注缓存命中率,如何应答缓存穿透,如何防止雪崩,如何解决缓存一致性等问题,这就减少了设计方案的复杂度,对设计者能力的要求也会更高。 所以,为了防止遇到问题时慌手慌脚,有必要提前储备足够多的微服务和高并发常识,从而具备随时应答可能呈现的相干需要的能力。 我想说的是,解决产品问题不应该是最终的指标,晋升技术能力和技术视线才是咱们始终不变的谋求。 放弃技术的前瞻性。研发技术迭代突飞猛进,新概念新利用也是层出不穷,云原生架构、容器化运维、中台等等,都与微服务有着奥妙的关系,只有放弃技术的持续性,能力更好的学习新技术,否则会很不利于新技术的落地利用。 站在伟人的肩膀上: 码闻强—SpringCloud微服务实战唐扬—高并发零碎设计40问阿里开发者、大淘宝技术

October 23, 2022 · 1 min · jiezi

关于高并发:高并发ScheduledThreadPoolExecutor与Timer的区别和简单示例

JDK 1.5开始提供ScheduledThreadPoolExecutor类,ScheduledThreadPoolExecutor类继承ThreadPoolExecutor类重用线程池实现了工作的周期性调度性能。在JDK 1.5之前,实现工作的周期性调度次要应用的是Timer类和TimerTask类。本文,就简略介绍下ScheduledThreadPoolExecutor类与Timer类的区别,ScheduledThreadPoolExecutor类相比于Timer类来说,到底有哪些劣势,以及二者别离实现任务调度的简略示例。 二者的区别线程角度Timer是单线程模式,如果某个TimerTask工作的执行工夫比拟久,会影响到其余工作的调度执行。ScheduledThreadPoolExecutor是多线程模式,并且重用线程池,某个ScheduledFutureTask工作执行的工夫比拟久,不会影响到其余工作的调度执行。零碎工夫敏感度Timer调度是基于操作系统的相对工夫的,对操作系统的工夫敏感,一旦操作系统的工夫扭转,则Timer的调度不再准确。ScheduledThreadPoolExecutor调度是基于绝对工夫的,不受操作系统工夫扭转的影响。是否捕捉异样Timer不会捕捉TimerTask抛出的异样,加上Timer又是单线程的。一旦某个调度工作出现异常,则整个线程就会终止,其余须要调度的工作也不再执行。ScheduledThreadPoolExecutor基于线程池来实现调度性能,某个工作抛出异样后,其余工作仍能失常执行。工作是否具备优先级Timer中执行的TimerTask工作整体上没有优先级的概念,只是依照零碎的相对工夫来执行工作。ScheduledThreadPoolExecutor中执行的ScheduledFutureTask类实现了java.lang.Comparable接口和java.util.concurrent.Delayed接口,这也就阐明了ScheduledFutureTask类中实现了两个十分重要的办法,一个是java.lang.Comparable接口的compareTo办法,一个是java.util.concurrent.Delayed接口的getDelay办法。在ScheduledFutureTask类中compareTo办法办法实现了工作的比拟,间隔下次执行的工夫距离短的工作会排在后面,也就是说,间隔下次执行的工夫距离短的工作的优先级比拟高。而getDelay办法则可能返回间隔下次工作执行的工夫距离。是否反对对工作排序Timer不反对对工作的排序。ScheduledThreadPoolExecutor类中定义了一个动态外部类DelayedWorkQueue,DelayedWorkQueue类实质上是一个有序队列,为须要调度的每个工作依照间隔下次执行工夫距离的大小来排序是否获取返回的后果Timer中执行的TimerTask类只是实现了java.lang.Runnable接口,无奈从TimerTask中获取返回的后果。ScheduledThreadPoolExecutor中执行的ScheduledFutureTask类继承了FutureTask类,可能通过Future来获取返回的后果。通过以上对ScheduledThreadPoolExecutor类和Timer类的剖析比照,置信在JDK 1.5之后,就没有应用Timer来实现定时任务调度的必要了。 二者简略的示例这里,给出应用Timer和ScheduledThreadPoolExecutor实现定时调度的简略示例,为了简便,我这里就间接应用匿名外部类的模式来提交工作。 Timer类简略示例源代码示例如下所示。 package io.binghe.concurrent.lab09;import java.util.Timer;import java.util.TimerTask;/** * @author binghe * @version 1.0.0 * @description 测试Timer */public class TimerTest { public static void main(String[] args) throws InterruptedException { Timer timer = new Timer(); timer.scheduleAtFixedRate(new TimerTask() { @Override public void run() { System.out.println("测试Timer类"); } }, 1000, 1000); Thread.sleep(10000); timer.cancel(); }}运行后果如下所示。 测试Timer类测试Timer类测试Timer类测试Timer类测试Timer类测试Timer类测试Timer类测试Timer类测试Timer类测试Timer类ScheduledThreadPoolExecutor类简略示例源代码示例如下所示。 package io.binghe.concurrent.lab09;import java.util.concurrent.*;/** * @author binghe * @version 1.0.0 * @description 测试ScheduledThreadPoolExecutor */public class ScheduledThreadPoolExecutorTest { public static void main(String[] args) throws InterruptedException { ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(3); scheduledExecutorService.scheduleAtFixedRate(new Runnable() { @Override public void run() { System.out.println("测试测试ScheduledThreadPoolExecutor"); } }, 1, 1, TimeUnit.SECONDS); //主线程休眠10秒 Thread.sleep(10000); System.out.println("正在敞开线程池..."); // 敞开线程池 scheduledExecutorService.shutdown(); boolean isClosed; // 期待线程池终止 do { isClosed = scheduledExecutorService.awaitTermination(1, TimeUnit.DAYS); System.out.println("正在期待线程池中的工作执行实现"); } while(!isClosed); System.out.println("所有线程执行完结,线程池敞开"); }}运行后果如下所示。 ...

October 12, 2022 · 1 min · jiezi

关于高并发:教你如何让自己的商城系统扛得住高并发而不崩溃

本文次要围绕一下3个方面带大家理解高并发 1.什么是商城高并发 2.如何进步商城并发量 3.具备高并发的劣势和益处 一、什么是商城高并发? 高并发(High Concurrency)是零碎运行过程中遇到的一种“短时间内大量操作申请”的状况,次要产生在web零碎中通过大量拜访收到大量申请时(例如12306的抢票状况;双十一流动)。这种状况的产生会导致系统在此期间执行大量的操作,比方申请资源、数据库操作等。 高并发也是互联网分布式系统架构设计中必须思考的因素之一,它通常是指,通过设计保证系统可能同时并行处理很多申请。 高并发相干罕用的一些指标有响应工夫(Response Time),吞吐量(Throughput),每秒查问率QPS(Query Per Second),并发用户数等。 响应工夫:系统对申请做出响应的工夫。例如零碎解决一个HTTP申请须要200ms,这个200ms就是零碎的响应工夫。 吞吐量:单位工夫内解决的申请数量。 QPS:每秒响应申请数。在互联网畛域,这个指标和吞吐量辨别的没有这么显著。 并发用户数:同时承载失常应用零碎性能的用户数量。例如一个即时通讯零碎,同时在线量肯定水平上代表了零碎的并发用户数。 二、CRMEBpro商城零碎是如何进步并发率的呢? 1.分布式缓存:redis、memcached等,联合CDN解决图片文件的拜访等。 2.音讯队列中间件:activeMQ等。,能够解决大量音讯的异步解决能力。 3.利用拆分:将一个我的项目拆分成多个我的项目部署,用dubbo解决多个我的项目之间的通信。 4.数据库垂直拆分和程度拆分(子数据库和子表)等。 5.将数据库的读写离开,解决大数据的查问问题。 6.也能够用nosql,比方mongoDB联合mysql。 7.还须要建设大数据接入状况下的服务降级和限流机制。 8.采纳swoole架构,多线程Reactor+多过程Worker,因为reactor基于epoll,所以每个reactor能够解决无数个连贯申请。 9.加强单机硬件性能(优先):例如:减少CPU核数如32核,降级更好的网卡如万兆,降级更好的硬盘如SSD,裁减硬盘容量如2T,裁减零碎内存如128G。 三、高并发商城的劣势和益处 1、速度劣势: 多处理器:多处理器上的并发无疑会让程序运行的更快。 单处理器:如果是单处理器的机器,那么并发编程和程序编程相比可能没有什么变动。然而,如果其中一个工作可能被阻塞,即便是单处理器,应用并发编程也会带来很大的益处,这样当一个工作被阻塞时,其余工作能够持续运行。 反馈灵活的用户界面:单处理器上性能改良的最典型的例子是“事件驱动编程”,例如创立一个带有按钮的响应性用户界面。如果咱们不应用并发编程,那么咱们须要在咱们编写的每个代码段中检测用户输出。如果咱们应用并发编程,咱们只须要重启一个线程来监听用户输出。 并发实现:实现并发最间接的形式是在操作系统层面,应用过程,一个自蕴含的程序,应用本人的地址空间。操作系统会将过程互相隔离,所以对过程编程绝对容易,不须要思考共享资源的同步问题。然而在Java的并发编程中,因为线程共享内存或IO等雷同的资源,所以在Java多线程编程中要思考共享资源的同步问题。 过程和Java线程之间的抉择:过程确实是一种实现并发的形式,butunfortunately there are generally quantity and overhead limitations toprocesses that prevent their applicability across the concurrency spectrum. 2、设计上的劣势: 一般来说,线程使得你可能创立更加松耦合的设计。 单处理器:只管单处理器下面的并发编程在同一时刻处理器依然只能做一件事件,然而带来一个组织下面的重要劣势:就是你的设计(design)会极大地简化。比方仿真。 仿真举例:如果没有并发,仿真将变得十分艰难。 一般来说仿真波及到多个交互元素,其中每一个都有“本人的想法”,只管从程序员的角度来看每一个仿真元素都是被同一个处理器所驱动,然而设计上来看,每一个仿真元素都伪装有本人的处理器以及运行独立的工作。 总结: 咱们应用redis,音讯队列,读写拆散,swoole架构,集群部署,进步服务器配置等就能进步咱们商城的并发量,反对了高并发,咱们就能够发展各种商城流动不再放心因为用户量大而导致的服务器瘫痪造成的损失。如果商城不反对高并发,在秒杀等货送的时候可能将库存秒杀成正数,服务器内存爆满和瘫痪等问题。CRMEB PRO商城完满解决了这些问题。

October 11, 2022 · 1 min · jiezi

关于高并发:高并发通过源码深度解析ThreadPoolExecutor类是如何保证线程池正确运行的

大家好,我是冰河~~ 对于线程池的外围类ThreadPoolExecutor来说,有哪些重要的属性和外部类为线程池的正确运行提供重要的保障呢? ThreadPoolExecutor类中的重要属性在ThreadPoolExecutor类中,存在几个十分重要的属性和办法,接下来,咱们就介绍下这些重要的属性和办法。 ctl相干的属性AtomicInteger类型的常量ctl是贯通线程池整个生命周期的重要属性,它是一个原子类对象,次要用来保留线程的数量和线程池的状态,咱们看下与这个属性相干的代码如下所示。 //次要用来保留线程数量和线程池的状态,高3位保留线程状态,低29位保留线程数量private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));//线程池中线程的数量的位数(32-3)private static final int COUNT_BITS = Integer.SIZE - 3;//示意线程池中的最大线程数量//将数字1的二进制值向右移29位,再减去1private static final int CAPACITY = (1 << COUNT_BITS) - 1;//线程池的运行状态private static final int RUNNING = -1 << COUNT_BITS;private static final int SHUTDOWN = 0 << COUNT_BITS;private static final int STOP = 1 << COUNT_BITS;private static final int TIDYING = 2 << COUNT_BITS;private static final int TERMINATED = 3 << COUNT_BITS;//获取线程状态private static int runStateOf(int c) { return c & ~CAPACITY; }//获取线程数量private static int workerCountOf(int c) { return c & CAPACITY; }private static int ctlOf(int rs, int wc) { return rs | wc; }private static boolean runStateLessThan(int c, int s) { return c < s;}private static boolean runStateAtLeast(int c, int s) { return c >= s;}private static boolean isRunning(int c) { return c < SHUTDOWN;}private boolean compareAndIncrementWorkerCount(int expect) { return ctl.compareAndSet(expect, expect + 1);}private boolean compareAndDecrementWorkerCount(int expect) { return ctl.compareAndSet(expect, expect - 1);}private void decrementWorkerCount() { do {} while (! compareAndDecrementWorkerCount(ctl.get()));}对于线程池的各状态阐明如下所示。 ...

August 30, 2022 · 3 min · jiezi

关于高并发:一次线上事故我顿悟了异步的精髓

在高并发的场景下,异步是一个极其重要的优化方向。 前段时间,生产环境产生一次事变,笔者认为事变的场景十分具备典型性 。 写这篇文章,笔者想和大家深入探讨该场景的架构优化计划。心愿大家读完之后,能够对异步有更粗浅的了解。 1 业务场景老师登录教研平台,会看到课程列表,点击课程后,课程会以视频的模式展示进去。 拜访课程详情页面,蕴含两个外围动作: 读取课程视频信息 : 从缓存服务器 Redis 获取课程的视频信息 ,返回给前端,前端通过视频组件渲染。 写入课程观看行为记录 : 当老师观看视频的过程中,浏览器每隔3秒发动申请,教研服务将观看行为记录插入到数据库表中。而且随着用户在线人数越多,写操作的频率也会指数级增长。 上线初期,这种设计运行还算良好,但随着在线用户的增多,零碎响应越来越慢,大量线程阻塞在写入视频观看进度表上的 Dao 办法。上。 首先咱们会想到一个十分直观的计划,晋升写入数据库的能力。 优化 SQL 语句;晋升 MySQL 数据库硬件配置 ;分库分表。这种计划其实也能够满足咱们的需要,然而通过扩容硬件并不便宜,另外写操作能够容许适当提早和失落大量数据,那这种计划更显得性价比有余。 那么架构优化的方向应该是:“缩小写动作的耗时,晋升写动作的并发度”, 只有这样能力让零碎更顺畅的运行。 于是,咱们想到了第二种计划:写申请异步化。 线程池模式本地内存 + 定时工作MQ 模式Agent 服务 + MQ 模式2 线程池模式2014年,笔者在艺龙旅行网负责红包零碎相干工作。经营零碎会调用红包零碎给特定用户发送红包,当这些用户登录 app 后,app 端会调用红包零碎的激活红包接口 。 激活红包接口是一个写操作,速度也比拟快(20毫秒左右),接口的日申请量在2000万左右。 利用拜访高峰期,红包零碎会变得不稳固,激活接口常常超时,笔者为了疾速解决问题,采取了一个十分毛糙的计划: "控制器收到申请后,将写操作放入到独立的线程池中后,立刻返回给前端,而线程池会异步执行激活红包办法"。 坦白的讲,这是一个十分无效的计划,优化后,红包零碎十分稳固。 回到教研的场景,见下图,咱们也能够设计相似线程池模型的计划: 应用线程池模式,须要留神如下几点: 线程数不宜过高,防止占用过多的数据库连接池 ;须要思考评估线程池队列的大小,免得呈现内存溢出的问题。3 本地内存 + 定时工作开源中国统计浏览数的计划十分经典。 用户拜访过一次文章、新闻、代码详情页面,拜访次数字段加 1 , 在 oschina 上这个操作是异步的,拜访的时候只是将数据在内存中保留,每隔固定工夫将这些数据写入数据库。 示例代码如下: 咱们能够借鉴开源中国的计划 : 控制器接收申请后,观看进度信息存储到本地内存 LinkedBlockingQueue 对象里;异步线程每隔1分钟从队列里获取数据 ,组装成 List 对象,最初调用 Jdbc batchUpdate 办法批量写入数据库;批量写入次要是为了晋升零碎的整体吞吐量,每次批量写入的 List 大小也不宜过大 。这种计划长处是:不改变原有业务架构,简略易用,性能也高。该计划同样须要思考内存溢出的危险。 ...

July 11, 2022 · 1 min · jiezi

关于高并发:多年亿级流量下的高并发经验总结我毫无保留的写在了这本书中

大家好,我是冰河~~ 明天,给大家隆重的发表一个好消息:继出版《海量数据处理与大数据技术实战》、《MySQL技术大全:开发、优化与运维实战》和《深刻了解分布式事务:原理与实战》之后,冰河的第4本书——《深刻了解高并发编程:外围原理与案例实战》正式上市了。 明天,我正式为大家送上本书的首发,全书彩印,全彩插图。更为重要的是,明天我为大家争取到了全网最低价5折优惠!!!!! 情谊提醒:全网最低价5折优惠名额有限,先到先得,截止到2022-06-20,想要全网最低价5折优惠的小伙伴能够先拖到文末二维码下单,手慢无,锁定订单后再回来听我啰嗦。 写作背景回想起为何写这本书,记得我刚开明 冰河技术 微信公众号时,连载的就是 【精通高并发系列】的专栏文章。很多小伙伴反馈说在我公众号里可能零碎的学习高并发编程的常识了。之所以我会连载【精通高并发系列】的专栏文章,是因为并发编程对于程序员来说,始终是一项十分头疼的技术。并发编程并不像其余业务那样简单明了。在编写并发程序时,往往会呈现各种诡异的Bug问题,这种Bug问题会经常以某种诡异的景象呈现,这种景象又会迅速隐没,并且这种问题在大部分场景下又很难复现。 起初,我将公众号里【精通高并发系列】的专栏文章,整顿成《深刻了解高并发编程》开源小册。这本《深刻了解高并发编程》开源小册和其余的并发编程电子书不同,它涵盖了源码解析、根底案例、实战案例、面试和零碎架构的常识,不仅有实践,更有实战案例和企业级的实在架构场景。一经公布,便火便全网。 只管这本开源小册在网上很火,然而对于我来说,这本开源小册并没有达到我心中现实的模样。我想把它彻底重构、甚至是重写来为大家提供一本更加零碎、更具深度、场景更贴近理论的并发编程书籍。于是,我便开始了对本书的写作构思。 全书构造本书从理论需要登程,全面并且粗疏地介绍了无关高并发编程的基础知识、外围原理、实战案例和零碎架构的相干常识。 根底篇:介绍了操作系统线程调度的相干常识和并发编程的基础知识。操作系统线程调度的常识蕴含:冯诺依曼计算机模型、CPU架构、操作系统线程和Java与操作系统线程的关系。并发编程的基础知识蕴含:并发编程的基本概念、并发编程的危险和并发编程中的锁等。 外围原理篇:以大量图解的形式具体介绍了并发编程中各项技术的外围原理。涵盖并发编程的三大外围问题、并发编程的实质问题、原子性的外围原理、可见性与有序性的外围原理、synchronized外围原理、AQS外围原理、Lock锁外围原理、CAS外围原理、死锁外围原理、锁优化、线程池外围原理和ThreadLocal外围原理。深刻了解外围原理篇的相干技术,有助于更好的了解高并发编程。 实战案例篇:在外围原理篇的根底上,实现了四个残缺的实战案例。蕴含:手动开发线程池实战、基于CAS实现自旋锁实战、基于读写锁实现缓存实战和基于AQS实现可重入锁实战。每个实战案例都是外围原理篇的落地实现,把握这四个实战案例的实现形式,有助于更好的在理论我的项目中开发高并发程序。 零碎架构篇:以高并发、大流量场景下典型的分布式锁架构和秒杀零碎架构为例,深刻分析了分布式锁和秒杀零碎的架构细节,使读者可能站在更高的架构层面来了解高并发编程。 总之,每个章节依据理论须要配有相干的原理图和流程图,在实战案例篇章,本书会提供残缺的实战案例源码。书中的每个解决方案都通过高并发大流量的生产环境的考验,能够间接拿来解决生产环境理论产生的高并发问题。通过对本书的浏览和学习,可能让读者更加全面、深刻、透彻的了解高并发编程的基础知识,外围原理,实战案例和零碎架构,进步高并发编程问题的解决能力和我的项目的实战能力,以及站在更高层面思考高并发编程零碎架构的能力。 本书特色本书与其余并发编程书籍不同的中央在于:力求让读者在欠缺基础理论常识的同时,兼顾晋升并发实战能力,以及站在更高层面思考高并发编程零碎架构的能力。 1.成体系介绍高并发编程的图书 纵观整个图书市场,简直找不到一本全面并且粗疏地介绍无关高并发编程的基础知识、外围原理、实战案例和零碎架构的图书,本书从以上四个方面全面、粗疏并且层层递进的介绍了高并发编程的基础知识、各项技术的外围原理和实战案例以及零碎架构的相干常识。 2.大量图解和开发案例 为了不便读者的了解,笔者在介绍高并发编程的基础知识、外围原理和零碎架构章节中会配有大量的图解和图表,在实战案例章节中会配有残缺的高并发编程案例,读者依照本书的案例进行学习,并运行本书的案例代码,可能更加深刻的了解和把握高并发编程相干的常识。另外,这些案例代码和图解的draw.io原文件,会一起收录于随书材料里。读者也能够从上面的链接获取残缺的实战案例源码和相干的随书材料。 GitHub:https://github.com/binghe001/mykit-concurrent-principle。Gitee:https://gitee.com/binghe001/mykit-concurrent-principle。3.技术点全面 本书中,全面并且粗疏的介绍了高并发编程的各项常识,蕴含高并发编程的基础知识、外围原理、实战案例,零碎架构。通过本书的学习,读者可能全面的把握高并发编程的原理和利用。 4.案例应用性强 本书中对于高并发编程的各项技术点都配有相干的案例,都是实现高并发编程相干技术点的典型案例,具备很强的实用性,不便读者随时查阅和参考。 5.具备较高的实用价值 本书中大量的实战案例来源于笔者理论的工作总结,尤其是本书中实战案例篇与零碎架构篇波及的内容,均来源于笔者的理论工作经验总结,书中的残缺案例稍加批改与欠缺便可利用于理论的生产环境中。 本书浏览答疑 弱小的专家阵容举荐 如何购买本书说了这么多,置信小伙伴们最关怀的就是如何购买本书了。这里,冰河为大家申请了全网最低价5折优惠,名额有限,先到先得,截止到2022-06-20,具体关注 冰河技术 微信公众号或者加我微信 hacker_binghe 具体理解。 好了,明天就到这儿吧,我是冰河,咱们下期见~~

June 17, 2022 · 1 min · jiezi

关于高并发:千万级高并发进阶笔记基础实战解决方案都有了

市面上Java相干的书籍,大多比拟适宜初学者,只涵盖根底内容,并不多见那种深刻某个高级主题并富裕思想性的专题书籍。尽管本书对读者的Java根底有肯定的要求,但这本书胜在内容丰盛,解说深入浅出,置信对于这个专题有趣味的读者肯定不会感到乏味和艰涩。 须要获取的小伙伴能够【点击此处】即可收费获取到! Java高并发编程详解,多线程架构设计第一局部多线程根底 疾速意识线程深刻了解Thread构造函数Thread API的具体介绍线程平安与数据同步ThreadGroup具体解说Hook线程以及捕捉线程执行异样线程池原理以及自定义线程池 [外链图片转存失败,源站可能有防盗链机制,倡议将图片保留下来间接上传(img-YmSROT79-1655207562137)(https://upload-images.jianshu...)] [外链图片转存失败,源站可能有防盗链机制,倡议将图片保留下来间接上传(img-CAySOvJj-1655207562145)(https://upload-images.jianshu...)] 第二局部 Java ClassLoader 类的加载过程JVM类加载器线程上下文类加载器 第三局部 深刻了解volatile关键字 volatile关键字的介绍深刻volatile关键字7种单例设计模式的设计 [外链图片转存失败,源站可能有防盗链机制,倡议将图片保留下来间接上传(img-P4o3ETya-1655207562157)(https://upload-images.jianshu...)] 第四局部 多线程设计架构模式 监控工作的生命周期Single Thread Execution设计模式读写锁拆散设计模式不可变对象设计模式Future设计模式Guarded Suspension设计模式线程上下文设计模式Balking设计模式Latch设计模式Thread-Per-Message设计模式Twe Phase Termination设计模式Worker-Thread设计模式Active Objects设计模式Event Bus设计模式Event Driv设计模式 ...

June 14, 2022 · 1 min · jiezi

关于高并发:千万级高并发进阶笔记涵盖基础实战解决方案

市面上Java相干的书籍,大多比拟适宜初学者,只涵盖根底内容,并不多见那种深刻某个高级主题并富裕思想性的专题书籍。尽管本书对读者的Java根底有肯定的要求,但这本书胜在内容丰盛,解说深入浅出,置信对于这个专题有趣味的读者肯定不会感到乏味和艰涩。 须要获取的小伙伴能够间接【点击此处】即可收费获取!! Java高并发编程详解,多线程架构设计第一局部多线程根底 第二局部 Java ClassLoader 第三局部 深刻了解volatile关键字 第四局部 多线程设计架构模式 如果看完这些局部内容截图还是不太懂得话上面会给大家展现一下目录:须要获取的小伙伴能够间接【点击此处】即可收费获取!!

May 28, 2022 · 1 min · jiezi

关于高并发:高并发从源码角度分析创建线程池究竟有哪些方式

大家好,我是冰河~~ 在Java的高并发畛域,线程池始终是一个绕不开的话题。有些童鞋始终在应用线程池,然而,对于如何创立线程池仅仅停留在应用Executors工具类的形式,那么,创立线程池到底存在哪几种形式呢?就让咱们一起从创立线程池的源码来深入分析到底有哪些形式能够创立线程池。 应用Executors工具类创立线程池在创立线程池时,初学者用的最多的就是Executors 这个工具类,而应用这个工具类创立线程池时非常简单的,不须要关注太多的线程池细节,只须要传入必要的参数即可。Executors 工具类提供了几种创立线程池的办法,如下所示。 Executors.newCachedThreadPool:创立一个可缓存的线程池,如果线程池的大小超过了须要,能够灵便回收闲暇线程,如果没有可回收线程,则新建线程Executors.newFixedThreadPool:创立一个定长的线程池,能够控制线程的最大并发数,超出的线程会在队列中期待Executors.newScheduledThreadPool:创立一个定长的线程池,反对定时、周期性的工作执行Executors.newSingleThreadExecutor: 创立一个单线程化的线程池,应用一个惟一的工作线程执行工作,保障所有工作依照指定程序(先入先出或者优先级)执行Executors.newSingleThreadScheduledExecutor:创立一个单线程化的线程池,反对定时、周期性的工作执行Executors.newWorkStealingPool:创立一个具备并行级别的work-stealing线程池其中,Executors.newWorkStealingPool办法是Java 8中新增的创立线程池的办法,它可能为线程池设置并行级别,具备更高的并发度和性能。除了此办法外,其余创立线程池的办法实质上调用的是ThreadPoolExecutor类的构造方法。 例如,咱们能够应用如下代码创立线程池。 Executors.newWorkStealingPool();Executors.newCachedThreadPool();Executors.newScheduledThreadPool(3);应用ThreadPoolExecutor类创立线程池从代码构造上看ThreadPoolExecutor类继承自AbstractExecutorService,也就是说,ThreadPoolExecutor类具备AbstractExecutorService类的全副性能。 既然Executors工具类中创立线程池大部分调用的都是ThreadPoolExecutor类的构造方法,所以,咱们也能够间接调用ThreadPoolExecutor类的构造方法来创立线程池,而不再应用Executors工具类。接下来,咱们一起看下ThreadPoolExecutor类的构造方法。 ThreadPoolExecutor类中的所有构造方法如下所示。 public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) { this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, Executors.defaultThreadFactory(), defaultHandler);}public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory) {this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, defaultHandler);}public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, RejectedExecutionHandler handler) {this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, Executors.defaultThreadFactory(), handler);}public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler) { if (corePoolSize < 0 || maximumPoolSize <= 0 || maximumPoolSize < corePoolSize || keepAliveTime < 0) throw new IllegalArgumentException(); if (workQueue == null || threadFactory == null || handler == null) throw new NullPointerException(); this.acc = System.getSecurityManager() == null ? null : AccessController.getContext(); this.corePoolSize = corePoolSize; this.maximumPoolSize = maximumPoolSize; this.workQueue = workQueue; this.keepAliveTime = unit.toNanos(keepAliveTime); this.threadFactory = threadFactory; this.handler = handler;}由ThreadPoolExecutor类的构造方法的源代码可知,创立线程池最终调用的构造方法如下。 ...

May 26, 2022 · 3 min · jiezi

关于高并发:高并发深度解析线程池中那些重要的顶层接口和抽象类

大家好,我是冰河~~ 在上一篇《【高并发】不得不说的线程池与ThreadPoolExecutor类浅析》一文中,从整体上介绍了Java的线程池。如果细细品味线程池的底层源码实现,你会发现整个线程池体系的设计是十分优雅的!这些代码的设计值得咱们去细细品味和钻研,从中学习优雅代码的设计规范,造成本人的设计思维,为我所用!哈哈,说多了,接下来,咱们就来看看线程池中那些十分重要的接口和抽象类,深度剖析下线程池中是如何将形象这一思维使用的酣畅淋漓的! 通过对线程池中接口和抽象类的剖析,你会发现,整个线程池设计的是如此的优雅和弱小,从线程池的代码设计中,咱们学到的不只是代码而已!! 题外话:膜拜Java大神Doug Lea,Java中的并发包正是这位老爷子写的,他是这个世界上对Java影响力最大的一个人。 一、接口和抽象类总览说起线程池中提供的重要的接口和抽象类,基本上就是如下图所示的接口和类。 接口与类的简略阐明: Executor接口:这个接口也是整个线程池中最顶层的接口,提供了一个无返回值的提交工作的办法。ExecutorService接口:派生自Executor接口,扩大了很过性能,例如敞开线程池,提交工作并返回后果数据、唤醒线程池中的工作等。AbstractExecutorService抽象类:派生自ExecutorService接口,实现了几个十分实现的办法,供子类进行调用。ScheduledExecutorService定时工作接口,派生自ExecutorService接口,领有ExecutorService接口定义的全副办法,并扩大了定时工作相干的办法。接下来,咱们就别离从源码角度来看下这些接口和抽象类从顶层设计上提供了哪些性能。 二、Executor接口Executor接口的源码如下所示。 public interface Executor { //提交运行工作,参数为Runnable接口对象,无返回值 void execute(Runnable command);}从源码能够看出,Executor接口非常简单,只提供了一个无返回值的提交工作的execute(Runnable)办法。 因为这个接口过于简略,咱们无奈得悉线程池的执行后果数据,如果咱们不再应用线程池,也无奈通过Executor接口来敞开线程池。此时,咱们就须要ExecutorService接口的反对了。 三、ExecutorService接口ExecutorService接口是非定时工作类线程池的外围接口,通过ExecutorService接口可能向线程池中提交工作(反对有返回后果和无返回后果两种形式)、敞开线程池、唤醒线程池中的工作等。ExecutorService接口的源码如下所示。 package java.util.concurrent;import java.util.List;import java.util.Collection;public interface ExecutorService extends Executor { //敞开线程池,线程池中不再承受新提交的工作,然而之前提交的工作持续运行,直到实现 void shutdown(); //敞开线程池,线程池中不再承受新提交的工作,会尝试进行线程池中正在执行的工作。 List<Runnable> shutdownNow(); //判断线程池是否曾经敞开 boolean isShutdown(); //判断线程池中的所有工作是否完结,只有在调用shutdown或者shutdownNow办法之后调用此办法才会返回true。 boolean isTerminated(); //期待线程池中的所有工作执行完结,并设置超时工夫 boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException; //提交一个Callable接口类型的工作,返回一个Future类型的后果 <T> Future<T> submit(Callable<T> task); //提交一个Callable接口类型的工作,并且给定一个泛型类型的接管后果数据参数,返回一个Future类型的后果 <T> Future<T> submit(Runnable task, T result); //提交一个Runnable接口类型的工作,返回一个Future类型的后果 Future<?> submit(Runnable task); //批量提交工作并取得他们的future,Task列表与Future列表一一对应 <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks) throws InterruptedException; //批量提交工作并取得他们的future,并限定解决所有工作的工夫 <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit) throws InterruptedException; //批量提交工作并取得一个曾经胜利执行的工作的后果 <T> T invokeAny(Collection<? extends Callable<T>> tasks) throws InterruptedException, ExecutionException; //批量提交工作并取得一个曾经胜利执行的工作的后果,并限定解决工作的工夫 <T> T invokeAny(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException;}对于ExecutorService接口中每个办法的含意,间接上述接口源码中的正文即可,这些接口办法都比较简单,我就不一一反复列举形容了。这个接口也是咱们在应用非定时工作类的线程池中最常应用的接口。 ...

May 10, 2022 · 4 min · jiezi

关于高并发:没有高并发项目经验但经常被问高并发性能调优问题怎么办

这篇文章对很多没有高并发教训的程序员来说,会十分有帮忙。 很多程序员可能都遇到过相似的困惑: 我没有高并发我的项目教训,然而面试的时候常常被问到高并发、性能调优方面的问题,该怎么办?明天给大家说一本人学习高并发的办法。 你能够本人写一个小的电商我的项目,倡议最简略的单体构造的电商我的项目即可。 从最简略的单体我的项目开始,而后依照以下三个阶段来学习高并发。 第一阶段在高并发条件下,学习对单机性能进行优化。 用 Docker 容器先去运行电商我的项目,而后再用 jmeter、wrk 等工具去压测。 在压测期间,你会发现:因为零碎每个模块不同,所以性能体现就不一样。 这是失常的,不同模块、不同产品对并发指标的要求自身想·是不一样的。例如,商品浏览和下订单,一个读为主,一个写为主。 基于这种状况,你最好要编写简单的压测脚本,能主动实现不同模块的压测工作。 而后在这种一直地压测探测下,去探测问题,并且通过优化代码、JVM 去解决问题。 比方,解决误用 HashMap 导致死循环的问题。又比方,误用不带缓存的文件 IO 流氓,去读取文件的问题等等。 该程序和 JVM 优化结束后,你可能又会发现数据库也存在问题。于是,你又要去钻研如何优化数据库 SQL,如何对数据库分表等问题。 也是在这个阶段,你可能还会学到,缓存的必要性以及同步缓存数据状态的重要性等重要知识点。 在搞了单机优化后,没有方法再通过单机的压测学到什么新的货色了。于是,转向第二阶段。 第二阶段从阿里云买了两台机器,开始尝试应用负载平衡去分担高并发的压力。 同样的,也是借助压测工具去模仿了高并发。在压测期间,负载平衡和零碎每每呈现和单机齐全不一样的问题。 比方,负载平衡自身的性能问题。比方,在一些时候,负载平衡前面的机器负载是不均衡的,须要对负载算法进行调整。 这个阶段,你会接触到负载平衡中大部分的细节。 然而,高并发中,很多零碎的形成会很简单,以至于须要分布式架构零碎的水平。他们须要各种中间件做通信,做存储。 所以,持续第三阶段的练习。 第三阶段为了能相熟市面上各种中间件的应用,开始对单体的电商平台进行革新。 比方,把一些本地调用的办法,替换成 Dubbo 近程调用。 比方,将一些模块间接调用,替换成 MQ 中间件传音讯。 再比方,一些放在关系数据库的被频繁拜访的数据,改存在 MongoDB 中…… 当然,压测仍然持续。就这样,你能够实际到很多中间件和分布式框架的应用。 在模仿高并发练习的同时,别忘了去读各种高并发高性能的书籍。比方,《大型网站服务器容量布局》、《互联网守业核心技术:构建可伸缩的web利用》等书籍。 三个阶段的学习之后,面试的大部分根底问题你根本能够应酬了。 毕竟在程序员这个圈子里,90% 以上的人可能都没有真正的高并发教训。作为面试官来说: 为什么咱们须要找有高并发教训的人? 说白了,咱们想找的程序员其实就是: 不会乱写性能很差的代码能敏锐地感知到影响零碎的问题能独立的解决因为高并发引发的问题咱们找相熟高可用的人,其实并不要求这个人肯定能给出什么独特的高可用计划。咱们要求的是,他能晓得高可用的常识后,去意识到高可用的重要性。 比方限流性能呈现问题,他要能马上意识到这是个很重要的问题,从而把解决的优先级提到很高。 通过以上三个阶段的学习和练习,根本是能够把握这些技能的,这就够了,剩下的细节,就靠在理论工作再实际吧。 此外也心愿各位面试官,在招人的时候,如果遇到好苗子能够适当宽容一些,给新人们一点机会。

May 7, 2022 · 1 min · jiezi

关于高并发:高并发不得不说的线程池与ThreadPoolExecutor类浅析

大家好,我是冰河~~ 明天,咱们一起来简略聊聊线程池中的ThreadPoolExecutor类,好了,不多说了,开始进入明天的正题。 一、抛砖引玉既然Java中反对以多线程的形式来执行相应的工作,但为什么在JDK1.5中又提供了线程池技术呢?这个问题大家自行脑补,多动脑,必定没害处,哈哈哈。。。 说起Java中的线程池技术,在很多框架和异步解决中间件中都有波及,而且性能禁受起了短暂的考验。能够这样说,Java的线程池技术是Java最外围的技术之一,在Java的高并发畛域中,Java的线程池技术是一个永远绕不开的话题。既然Java的线程池技术这么重要(怎么能说是这么重要呢?那是相当的重要,那家伙老重要了,哈哈哈),那么,本文咱们就来简略的说下线程池与ThreadPoolExecutor类。至于线程池中的各个技术细节和ThreadPoolExecutor的底层原理和源码解析,咱们会在【高并发专题】专栏中进行深度解析。 引言:本文是高并发中线程池的开篇之作,就临时先不深刻解说,只是让大家从整体上意识下线程池中最外围的类之一——ThreadPoolExecutor,对于ThreadPoolExecutor的底层原理和源码实现,以及线程池中的其余技术细节的底层原理和源码实现,咱们会在【高并发专题】接下来的文章中,进行死磕。 二、Thread间接创立线程的弊病(1)每次new Thread新建对象,性能差。 (2)线程不足对立治理,可能无限度的新建线程,相互竞争,有可能占用过多系统资源导致死机或OOM。 (3)短少更多的性能,如更多执行、定期执行、线程中断。 (4)其余弊病,大家自行脑补,多动脑,没害处,哈哈。 三、线程池的益处(1)重用存在的线程,缩小对象创立、沦亡的开销,性能佳。 (2)能够无效管制最大并发线程数,进步系统资源利用率,同时能够防止过多资源竞争,防止阻塞。 (3)提供定时执行、定期执行、单线程、并发数管制等性能。 (4)提供反对线程池监控的办法,可对线程池的资源进行实时监控。 (5)其余益处,大家自行脑补,多动脑,没害处,哈哈。 四、线程池1.线程池类构造关系线程池中的一些接口和类的构造关系如下图所示。 后文会死磕这些接口和类的底层原理和源码。 2.创立线程池罕用的类——ExecutorsExecutors.newCachedThreadPool:创立一个可缓存的线程池,如果线程池的大小超过了须要,能够灵便回收闲暇线程,如果没有可回收线程,则新建线程Executors.newFixedThreadPool:创立一个定长的线程池,能够控制线程的最大并发数,超出的线程会在队列中期待Executors.newScheduledThreadPool:创立一个定长的线程池,反对定时、周期性的工作执行Executors.newSingleThreadExecutor: 创立一个单线程化的线程池,应用一个惟一的工作线程执行工作,保障所有工作依照指定程序(先入先出或者优先级)执行Executors.newSingleThreadScheduledExecutor:创立一个单线程化的线程池,反对定时、周期性的工作执行Executors.newWorkStealingPool:创立一个具备并行级别的work-stealing线程池3.线程池实例的几种状态Running:运行状态,能接管新提交的工作,并且也能解决阻塞队列中的工作Shutdown: 敞开状态,不能再接管新提交的工作,然而能够解决阻塞队列中曾经保留的工作,当线程池处于Running状态时,调用shutdown()办法会使线程池进入该状态Stop: 不能接管新工作,也不能解决阻塞队列中曾经保留的工作,会中断正在解决工作的线程,如果线程池处于Running或Shutdown状态,调用shutdownNow()办法,会使线程池进入该状态Tidying: 如果所有的工作都曾经终止,无效线程数为0(阻塞队列为空,线程池中的工作线程数量为0),线程池就会进入该状态。Terminated: 处于Tidying状态的线程池调用terminated()办法,会应用线程池进入该状态留神:不须要对线程池的状态做非凡的解决,线程池的状态是线程池外部依据办法自行定义和解决的。 4.合理配置线程的一些倡议(1)CPU密集型工作,就须要尽量压迫CPU,参考值能够设置为NCPU+1(CPU的数量加1)。 (2)IO密集型工作,参考值能够设置为2*NCPU(CPU数量乘以2) 五、线程池最外围的类之一——ThreadPoolExecutor1.构造方法ThreadPoolExecutor参数最多的构造方法如下: public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler rejectHandler) 其余的构造方法都是调用的这个构造方法来实例化对象,能够说,咱们间接剖析这个办法之后,其余的构造方法咱们也明确是怎么回事了!接下来,就对此构造方法进行具体的剖析。 留神:为了更加深刻的剖析ThreadPoolExecutor类的构造方法,会适当调整参数的程序进行解析,以便于大家更能深刻的了解ThreadPoolExecutor构造方法中每个参数的作用。 上述构造方法接管如下参数进行初始化: (1)corePoolSize:外围线程数量。 (2)maximumPoolSize:最大线程数。 (3)workQueue:阻塞队列,存储期待执行的工作,很重要,会对线程池运行过程产生重大影响。 其中,上述三个参数的关系如下所示: 如果运行的线程数小于corePoolSize,间接创立新线程解决工作,即便线程池中的其余线程是闲暇的。如果运行的线程数大于等于corePoolSize,并且小于maximumPoolSize,此时,只有当workQueue满时,才会创立新的线程解决工作。如果设置的corePoolSize与maximumPoolSize雷同,那么创立的线程池大小是固定的,此时,如果有新工作提交,并且workQueue没有满时,就把申请放入到workQueue中,期待闲暇的线程,从workQueue中取出工作进行解决。如果运行的线程数量大于maximumPoolSize,同时,workQueue曾经满了,会通过回绝策略参数rejectHandler来指定解决策略。根据上述三个参数的配置,线程池会对工作进行如下解决形式: 当提交一个新的工作到线程池时,线程池会依据以后线程池中正在运行的线程数量来决定该工作的解决形式。解决形式总共有三种:间接切换、应用有限队列、应用有界队列。 间接切换罕用的队列就是SynchronousQueue。应用有限队列就是应用基于链表的队列,比方:LinkedBlockingQueue,如果应用这种形式,线程池中创立的最大线程数就是corePoolSize,此时maximumPoolSize不会起作用。当线程池中所有的外围线程都是运行状态时,提交新工作,就会放入期待队列中。应用有界队列应用的是ArrayBlockingQueue,应用这种形式能够将线程池的最大线程数量限度为maximumPoolSize,能够升高资源的耗费。然而,这种形式使得线程池对线程的调度更艰难,因为线程池和队列的容量都是无限的了。依据下面三个参数,咱们能够简略得出如何升高系统资源耗费的一些措施: 如果想升高系统资源的耗费,包含CPU使用率,操作系统资源的耗费,上下文环境切换的开销等,能够设置一个较大的队列容量和较小的线程池容量。这样,会升高线程解决工作的吞吐量。如果提交的工作常常产生阻塞,能够思考调用设置最大线程数的办法,从新设置线程池最大线程数。如果队列的容量设置的较小,通常须要将线程池的容量设置的大一些,这样,CPU的使用率会高些。如果线程池的容量设置的过大,并发量就会减少,则须要思考线程调度的问题,反而可能会升高解决工作的吞吐量。接下来,咱们持续看ThreadPoolExecutor的构造方法的参数。 (4)keepAliveTime:线程没有工作执行时最多放弃多久工夫终止 当线程池中的线程数量大于corePoolSize时,如果此时没有新的工作提交,外围线程外的线程不会立刻销毁,须要期待,直到期待的工夫超过了keepAliveTime就会终止。 (5)unit:keepAliveTime的工夫单位 (6)threadFactory:线程工厂,用来创立线程 默认会提供一个默认的工厂来创立线程,当应用默认的工厂来创立线程时,会使新创建的线程具备雷同的优先级,并且是非守护的线程,同时也设置了线程的名称 (7)rejectHandler:回绝解决工作时的策略 如果workQueue阻塞队列满了,并且没有闲暇的线程池,此时,持续提交工作,须要采取一种策略来解决这个工作。 线程池总共提供了四种策略: 间接抛出异样,这也是默认的策略。实现类为AbortPolicy。用调用者所在的线程来执行工作。实现类为CallerRunsPolicy。抛弃队列中最靠前的工作并执行当前任务。实现类为DiscardOldestPolicy。间接抛弃当前任务。实现类为DiscardPolicy。2.ThreadPoolExecutor提供的启动和进行工作的办法(1)execute():提交工作,交给线程池执行(2)submit():提交工作,可能返回执行后果 execute+Future(3)shutdown():敞开线程池,期待工作都执行完(4)shutdownNow():立刻敞开线程池,不期待工作执行完 3.ThreadPoolExecutor提供的实用于监控的办法(1)getTaskCount():线程池已执行和未执行的工作总数(2)getCompletedTaskCount():已实现的工作数量(3)getPoolSize():线程池以后的线程数量(4)getCorePoolSize():线程池外围线程数(5)getActiveCount():以后线程池中正在执行工作的线程数量 好了,明天就到这儿吧,我是冰河,咱们下期见~~

April 21, 2022 · 1 min · jiezi

关于高并发:高并发两种异步模型与深度解析Future接口

大家好,我是冰河~~ 本文有点长,然而满满的干货,以理论案例的模式剖析了两种异步模型,并从源码角度深度解析Future接口和FutureTask类,心愿大家踏下心来,关上你的IDE,跟着文章看源码,置信你肯定播种不小! 一、两种异步模型在Java的并发编程中,大体上会分为两种异步编程模型,一类是间接以异步的模式来并行运行其余的工作,不须要返回工作的后果数据。一类是以异步的模式运行其余工作,须要返回后果。 1.无返回后果的异步模型 无返回后果的异步工作,能够间接将工作丢进线程或线程池中运行,此时,无奈间接取得工作的执行后果数据,一种形式是能够应用回调办法来获取工作的运行后果。 具体的计划是:定义一个回调接口,并在接口中定义接管工作后果数据的办法,具体逻辑在回调接口的实现类中实现。将回调接口与工作参数一起放进线程或线程池中运行,工作运行后调用接口办法,执行回调接口实现类中的逻辑来处理结果数据。这里,给出一个简略的示例供参考。 定义回调接口package io.binghe.concurrent.lab04;/** * @author binghe * @version 1.0.0 * @description 定义回调接口 */public interface TaskCallable<T> { T callable(T t);}便于接口的通用型,这里为回调接口定义了泛型。 定义工作后果数据的封装类package io.binghe.concurrent.lab04;import java.io.Serializable;/** * @author binghe * @version 1.0.0 * @description 工作执行后果 */public class TaskResult implements Serializable { private static final long serialVersionUID = 8678277072402730062L; /** * 工作状态 */ private Integer taskStatus; /** * 工作音讯 */ private String taskMessage; /** * 工作后果数据 */ private String taskResult; //省略getter和setter办法 @Override public String toString() { return "TaskResult{" + "taskStatus=" + taskStatus + ", taskMessage='" + taskMessage + '\'' + ", taskResult='" + taskResult + '\'' + '}'; }}创立回调接口的实现类回调接口的实现类次要用来对工作的返回后果进行相应的业务解决,这里,为了不便演示,只是将后果数据返回。大家须要依据具体的业务场景来做相应的剖析和解决。 ...

March 25, 2022 · 8 min · jiezi

关于高并发:请求合并与拆分在并发场景中应用

一、序言在并发场景中,当热点缓存Key生效时,流量霎时打到数据库中,此所谓缓存击穿景象;当大范畴的缓存Key生效时,流量也会打到数据库中,此所谓缓存雪崩景象。 当应用分布式行锁时,可能无效解决缓存击穿问题;当应用分布式表锁时,可能解决缓存雪崩问题。实际操作中,分布式表锁不在思考范畴,理由是升高并发量。 本文将从另一个角度登程,将申请流量合并和拆分,以进步零碎的并发量。 二、实践根底流量的合并与拆分原理是将多条申请合并成一条申请,执行后再将后果拆分。在数据库与缓存架构中,缓存Key生效的霎时,大量反复申请打到数据库中。实际上除了第一条申请为无效申请,随后的申请为有效申请,节约数据库连贯资源。 流量的合并与拆分实际是额定唤醒一个线程,每隔固定工夫(比方200毫秒)发送合并后的申请,执行实现后将查问后果进行拆分,散发到原始申请中,原始申请响应用户申请。 从利用到数据库之间连贯资源需要显著降落,从而进步数据库连贯资源利用率。 三、利用实际(一)编码与应用基于MybatisPlus提供一个内置封装的服务类QueueServiceImpl,通明的实现查问详情流量的合并与拆分,使用者可屏蔽外部实现。 <dependency> <groupId>xin.altitude.cms</groupId> <artifactId>ucode-cms-common</artifactId> <version>1.4.4</version></dependency>对于肯定工夫区间内的所有申请,合并成一条申请解决。 @Overridepublic BuOrder getOrderById(Long orderId) { return getById(orderId);}举例说明,如果特定工夫区间内会集了雷同的主键申请,那么合并后的申请查问一次数据库便可能响应所有的申请。 子类重写父类办法,可批改合并与拆分的行为。 @Overrideprotected RequstConfig createRequstConfig() { RequstConfig config = new RequstConfig(); /* 单次最大合并申请数量 */ config.setMaxRequestSize(100); /* 外围线程池大小 */ config.setCorePoolSize(1); /* 申请距离(毫秒) */ config.setRequestInterval(200); return config;}(二)实现细节1、ConcurrentLinkedQueue应用ConcurrentLinkedQueue并发平安队列用于缓冲和接管申请,定时工作以固定频率从队列中生产数据,将多条申请条件合并后汇总查问。 2、CompletableFutureCompletableFuture类是合并与拆分的要害类,原始申请将查问条件封装成CompletableFuture对象,提交到队列中后陷入阻塞,定时工作分批次组装查问条件,失去后果后将后果拆分并存入CompletableFuture对象中,原始申请线程被唤醒,持续响应用户申请。 3、ScheduledExecutorService以肯定的工夫距离发送合并后的申请。 (二)其它利用场景利用于数据库间流量的合并申请与拆分,首先进步数据库连贯资源(稀缺资源)利用率,其次进步网络间数据传输效率。100条数据收发100次与100条数据收发1次的效率差异。 1、服务间接口调用服务间API接口调用同样实用于流量的合并与拆分:比方向订单服务发送Http API申请,同一时刻有100个用户发动查问申请,应用流量合并与拆分的思维可将多个订单查问申请转换成批查问申请,失去后果后散发到不同的申请线程,响应用户申请。 四、小结在本文中,选用的队列是本地并发平安的队列,在分布式系统中,本地队列是否适合?此处选用本地队列基于两点思考:一是无严格的分布式的需要;二是CompletableFuture类不反对序列化。思考应用Redis做分布式队列的想法无奈实现,你用本地队列,只管会有大量查问条件数据冗余(不影响后果),回避了分布式队列的网络IO提早,反而有更优的查问效率。 本计划仅在高并发场景受害,属于针对并发场景进行架构的优化,一般我的项目应用惯例操作即可。 演示我的项目代码地址 喜爱本文点个♥️赞♥️反对一下,如有须要,可通过微信dream4s与我分割。相干源码在GitHub,视频解说在B站,本文珍藏在博客天地。

March 16, 2022 · 1 min · jiezi

关于高并发:高并发深入理解线程的执行顺序

大家好,我是冰河~~ 最近常常有读者问我:冰河,线程到底是依照怎么的程序执行的呀?为了同一答复大家的这个问题,明天我就独自写一篇文章吧。好了,不多说了,进入明天的正题。 一、线程的执行程序是不确定的调用Thread的start()办法启动线程时,线程的执行程序是不确定的。也就是说,在同一个办法中,间断创立多个线程后,调用线程的start()办法的程序并不能决定线程的执行程序。 例如,这里,看一个简略的示例程序,如下所示。 package io.binghe.concurrent.lab03;/** * @author binghe * @version 1.0.0 * @description 线程的程序,间接调用Thread.start()办法执行不能确保线程的执行程序 */public class ThreadSort01 { public static void main(String[] args){ Thread thread1 = new Thread(() -> { System.out.println("thread1"); }); Thread thread2 = new Thread(() -> { System.out.println("thread2"); }); Thread thread3 = new Thread(() -> { System.out.println("thread3"); }); thread1.start(); thread2.start(); thread3.start(); }}在ThreadSort01类中别离创立了三个不同的线程,thread1、thread2和thread3,接下来,在程序中依照程序别离调用thread1.start()、thread2.start()和thread3.start()办法来别离启动三个不同的线程。 那么,问题来了,线程的执行程序是否依照thread1、thread2和thread3的程序执行呢?运行ThreadSort01的main办法,后果如下所示。 thread1thread2thread3再次运行时,后果如下所示。 thread1thread3thread2第三次运行时,后果如下所示。 thread2thread3thread1能够看到,每次运行程序时,线程的执行程序可能不同。线程的启动程序并不能决定线程的执行程序。 二、如何确保线程的执行程序1.确保线程执行程序的简略示例在理论业务场景中,有时,后启动的线程可能须要依赖先启动的线程执行实现能力正确的执行线程中的业务逻辑。此时,就须要确保线程的执行程序。那么如何确保线程的执行程序呢? 能够应用Thread类中的join()办法来确保线程的执行程序。例如,上面的测试代码。 package io.binghe.concurrent.lab03;/** * @author binghe * @version 1.0.0 * @description 线程的程序,Thread.join()办法可能确保线程的执行程序 */public class ThreadSort02 { public static void main(String[] args) throws InterruptedException { Thread thread1 = new Thread(() -> { System.out.println("thread1"); }); Thread thread2 = new Thread(() -> { System.out.println("thread2"); }); Thread thread3 = new Thread(() -> { System.out.println("thread3"); }); thread1.start(); //实际上让主线程期待子线程执行实现 thread1.join(); thread2.start(); thread2.join(); thread3.start(); thread3.join(); }}能够看到,ThreadSot02类比ThreadSort01类,在每个线程的启动办法上面增加了调用线程的join()办法。此时,运行ThreadSort02类,后果如下所示。 ...

January 17, 2022 · 2 min · jiezi

关于高并发:阿里P8推荐NettyRedisZookeeper高并发实战看完真不错

挪动时代、5G时代、物联网时代的大幕曾经开启,它们对于高性能、高并发的开发常识和技术的要求,抬升了 Java工程师的学习台阶和面试门槛。 大公司的面试题从某个侧面映射出生产场景中对专项技术的要求。高并发的面试题以前根本是BAT等大公司的专利,当初简直蔓延至与Java我的项目相干的整个行业。例如,与Java NIO、Reactor模式、高性能通信、分布式锁、分布式ID、分布式缓存、高并发架构等技术相干的面试题,从以前的加分题变成了当初的根底题,这也映射出开发Java我的项目所必须的技术栈:分布式Java框架、Redis缓存、分布式搜寻ElasticSearch、分布式协调ZooKeeper、音讯队列Kafka、高性能通信框架Netty。 《Netty、Redis、Zookeeper高并发实战》为了让大家扎稳高性能根底,浅显易懂地分析高并发IO的底层原理,粗疏细腻地解析Reactor高性能模式,图文并茂地介绍Java异步回调模式。把握这些根底原理,可能帮忙大家解决Java后盾开发的一些理论问题。 本书共12章,次要介绍高性能通信框架Netty,并详尽介绍Netty的EventLoop、Handler、Pipeline、ByteBuf、Decoder、Encoder等重要组件,而后介绍单体IM的实战设计和模块实现。本书对ZooKeeper、 Curator API、Redis、Jedis API的应用也进行详尽的介绍,让大家具备高并发、可扩大零碎的设计和开发能力。 因为内容较多,本次将展现局部截图,如果看得不过瘾想更加深刻地理解本笔记彻底把握,只需转发后【戳此处】即可来获取收费支付形式了!第一章:高并发时代的必备技能 第二章:高并发IO的底层原理 第三章:Java NIO通信根底详解 第四章:鼎鼎大名的Reactor反应器模式 第五章:并发根底中的Future异步回调模式 因为内容较多,本次将展现局部截图,如果看得不过瘾想更加深刻地理解本笔记彻底把握,只需转发后【戳此处】即可来获取收费支付形式了!第六章:Netty原理与根底 第七章:Decoder与Encoder重要组件 第八章:JSON和ProtoBuf序列化 第九章:基于Netty的单体IM零碎的开发实际 第十章:ZooKeeper分布式协调 因为内容较多,本次将展现局部截图,如果看得不过瘾想更加深刻地理解本笔记彻底把握,只需转发后【戳此处】即可来获取收费支付形式了!第十一章:分布式缓存Redis 第十二章:亿级高并发IM架构的开发实际 因为内容较多,本次将展现局部截图,如果看得不过瘾想更加深刻地理解本笔记彻底把握,只需转发后【戳此处】即可来获取收费支付形式了!

December 28, 2021 · 1 min · jiezi

关于高并发:多点-DMALL-x-StarRocks实现存储引擎的收敛保障高查询并发及低延迟要求

多点 DMALL 成立于2015年,是一站式全渠道数字批发解决方案服务商。数字化解构重构批发产业,提供端到端的商业 SaaS 解决方案。目前,多点 DMALL 已与120多家连锁零售商、品牌商等达成单干,笼罩四个国家和地区15000家门店,模式受到宽泛验证。 多点大数据部门应用 StarRocks 逐渐代替了 Impala、Impala on Kudu、Apache Kylin 等存储引擎,实现了存储引擎的收敛,简化了实时数据处理链路,同时也能保障较高的查问并发以及较低的响应提早要求。 “作者:任伟,多点生存大数据部门资深研发工程师”背景介绍多点大数据部门为外部业务研发团队、数据分析师、内部用户以及合作伙伴,提供了根底的大数据产品、平台服务,帮忙批发企业解决了从根本的数据汇总治理、对立的数据计算利用、到各种场景下对数据的多模式应用的需要,可笼罩批发企业绝大部分数据诉求。 技术层面,多点大数据部门基于 Hadoop 开源技术栈,并进行了局部二次开发后构建起了以下的一个技术架构全景图。从下到上分为基础设施层、数据源层、数据集成层、离线/实时计算层、集市层、剖析存储层、数据服务/应用层,数据开发、数据模型核心与运维管理层对各层提供反对。 基础设施层:包含超大带宽的专线网络;私有云、公有云、机房托管的混合云部署; 数据源层:包含企业 OLTP 数据库、业务数据、日志数据、三方接入数据;数据集成层:DataBus 是多点自研数据同步平台,解决企业内各业务线之间、跨企业组织之间以及跨行业的数据汇聚、交融等问题,将不同零碎的数据互相买通,实现数据自在流动; 离线计算层:利用 Hive / Spark 高可扩大的批处理能力承当离线数仓的 ETL 和数据模型加工; 实时计算层:利用 Flink / Spark Streaming 实现实时数据的 ETL(包含维度裁减,多流 Join,实时汇总)等; 离线/实时集市层:应用数仓分层模型构建 ODS(原始数据层)、DWD(数据明细层)、DWS(汇总层)、DIM(维度层)、DWT(主题层)、ADS(应用层),并依据公司业务拆分不同的数据域; 剖析存储层:次要依赖 Druid、ClickHouse、Impala on Kudu、Apache Kylin、Elasticsearch、HBase、MySQL、StarRocks 提供 OLAP 查问能力; 数据服务/应用层:该层通过提供 BI 剖析产品、数据服务接口、营销、报表类产品,向外部经营人员、内部客户、合作伙伴提供数据分析决策能力。 原有架构痛点上述架构解决了多点绝大部分数据诉求,在整个架构中,无论是基于 Hive、Spark 的离线计算,基于 Flink、Spark Streaming 的实时计算;基于 HDFS、Kafka 的存储;基于数仓分层模型建设等计划都已根本成熟。然而在 OLAP 畛域,无论是多点还是业界依然处于百家争鸣,各有千秋的状态。纵观多点在 OLAP 引擎的摸索实际中,遇到了各种各样的问题,总结起来如下: 技术老本因为下层业务场景简单,各个场景的技术难点、外围点均不一样。多点生存在整个技术架构降级的过程中先后引入了 HBase、Elasticsearch、Druid、ClickHouse、Impala on Kudu、Apache Kylin 等 OLAP 引擎。然而随着技术栈增多,技术曲线平缓,没有短缺的资源进行多技术栈的保护,造成了比拟高的技术老本。 ...

December 15, 2021 · 2 min · jiezi

关于高并发:The-art-of-multipropcessor-programming-读书笔记3-自旋锁与争用2

本系列是 The art of multipropcessor programming 的读书笔记,在原版图书的根底上,联合 OpenJDK 11 以上的版本的代码进行了解和实现。并依据集体的查资料以及了解的经验,给各位想更深刻了解的人分享一些集体的材料自旋锁与争用3. 队列锁之前实现的基于回退的锁,除了通用性以外,还有如下两个问题: CPU 高速缓存一致性流量:尽管因为回退存在,所以流量比 TASLock 要小,然而多线程拜访锁的状态还是有肯定因为缓存一致性导致的流量耗费的。可能升高拜访临界区的效率:因为所有线程的 sleep 提早过大,导致以后所有线程都在 sleep,然而锁实际上曾经开释。能够将线程放入一个队列,来解决下面两个问题: 队列中,每个线程查看它的前驱线程是否曾经实现,判断锁是否被开释,不必拜访锁的状态。这样拜访的是不同的内存,缩小了锁开释批改状态导致的 CPU 高速缓存一致性流量不须要 sleep,能够通过前驱线程告知线程锁被开释,尝试获取锁,进步了拜访临界区的效率最初,通过队列,也是实现了 FIFO 的公平性。 3.1. 基于数组的锁咱们通过一个数组来实现队列的性能,其流程是: 须要的存储: boolean 数组,为 true 则代表对应槽位的线程获取到了锁,为 false 则为对应槽位的线程没有获取到了锁保留以后最新槽位的原子变量,每次上锁都会将这个原子变量加 1,之后对 boolean 数组的大小取余。这个值代表这个线程占用了 boolean 数组的这个地位,boolean 数组的这个地位的值代表这个线程是否获取到了锁。这也阐明,boolean 数组的容量决定了这个锁同时能够有多少线程进行争用ThreadLocal,记录以后线程占用的 boolean 数组的地位上锁流程: 原子变量 + 1,对 boolean 数组的大小取余失去 current将 current 记录到 ThreadLocal当 boolean 数组 cuurent 地位的值为 false 的时候,自旋期待解锁流程: 从 ThreadLocal 中获取以后线程对应的地位 mine将 boolean 数组的 mine 地位标记为 false将 boolean 数组的 mine + 1 对数组大小取余的地位(避免数组越界)标记为 true其源码是: ...

November 6, 2021 · 2 min · jiezi

关于高并发:Interrupted-Exception异常可能没你想的那么简单

摘要: 当咱们在调用Java对象的wait()办法或者线程的sleep()办法时,须要捕捉并解决InterruptedException异样。如果咱们对InterruptedException异样处理不当,则会产生咱们意想不到的结果!本文分享自华为云社区《【高并发】由InterruptedException异样引发的思考》,作者:冰 河。 前言当咱们在调用Java对象的wait()办法或者线程的sleep()办法时,须要捕捉并解决Interrupted Exception异样。如果咱们对Interrupted Exception异样处理不当,则会产生咱们意想不到的结果! 程序案例例如,上面的程序代码,Interrupted Task类实现了Runnable接口,在run()办法中,获取以后线程的句柄,并在while(true)循环中,通过isInterrupted()办法来检测以后线程是否被中断,如果以后线程被中断就退出while(true)循环,同时,在while(true)循环中,还有一行Thread.sleep(100)代码,并捕捉了Interrupted Exception异样。整个代码如下所示。 package io.binghe.concurrent.lab08;/** * @author binghe * @version 1.0.0 * @description 线程测试中断 */public class Interrupted Task implements Runnable{ @Override public void run() { Thread currentThread = Thread.currentThread(); while (true){ if(currentThread.isInterrupted()){ break; } try { Thread.sleep(100); } catch (Interrupted Exception e) { e.printStack Trace(); } } }}上述代码的本意是通过isInterrupted()办法查看线程是否被中断了,如果中断了就退出while循环。其余线程通过调用执行线程的interrupt()办法来中断执行线程,此时会设置执行线程的中断标记位,从而使currentThread.isInterrupted()返回true,这样就可能退出while循环。 这看上去没啥问题啊!但真的是这样吗?咱们创立一个Interrupted Test类用于测试,代码如下所示。 package io.binghe.concurrent.lab08;/** * @author binghe * @version 1.0.0 * @description 测试线程中断 */public class InterruptedTest { public static void main(String[] args){ InterruptedTask interruptedTask = new InterruptedTask(); Thread interruptedThread = new Thread(interruptedTask); interruptedThread.start(); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } interruptedThread.interrupt(); }}咱们运行main办法,如下所示。 ...

October 8, 2021 · 1 min · jiezi

关于高并发:你知道线程池是如何退出程序的吗

摘要:本文,咱们就来从源码角度深度解析线程池是如何优雅的退出程序的。本文分享自华为云社区《【高并发】从源码角度深度解析线程池是如何实现优雅退出的》,作者:冰 河 。 本文,咱们就来从源码角度深度解析线程池是如何优雅的退出程序的。首先,咱们来看下ThreadPoolExecutor类中的shutdown()办法。 shutdown()办法当应用线程池的时候,调用了shutdown()办法后,线程池就不会再承受新的执行工作了。然而在调用shutdown()办法之前放入工作队列中的工作还是要执行的。此办法是非阻塞办法,调用后会立刻返回,并不会期待工作队列中的工作全副执行结束后再返回。咱们看下shutdown()办法的源代码,如下所示。 public void shutdown() { //获取线程池的全局锁 final ReentrantLock mainLock = this.mainLock; mainLock.lock(); try { //查看是否有敞开线程池的权限 checkShutdownAccess(); //将以后线程池的状态设置为SHUTDOWN advanceRunState(SHUTDOWN); //中断Worker线程 interruptIdleWorkers(); //为ScheduledThreadPoolExecutor调用钩子函数 onShutdown(); // hook for } finally { //开释线程池的全局锁 mainLock.unlock(); } //尝试将状态变为TERMINATED tryTerminate();}总体来说,shutdown()办法的代码比较简单,首先查看了是否有权限来敞开线程池,如果有权限,则再次检测是否有中断工作线程的权限,如果没有权限,则会抛出SecurityException异样,代码如下所示。 //查看是否有敞开线程池的权限checkShutdownAccess();//将以后线程池的状态设置为SHUTDOWNadvanceRunState(SHUTDOWN);//中断Worker线程interruptIdleWorkers();其中,checkShutdownAccess()办法的实现代码如下所示。 private void checkShutdownAccess() { SecurityManager security = System.getSecurityManager(); if (security != null) { security.checkPermission(shutdownPerm); final ReentrantLock mainLock = this.mainLock; mainLock.lock(); try { for (Worker w : workers) security.checkAccess(w.thread); } finally { mainLock.unlock(); } }}对于checkShutdownAccess()办法的代码了解起来比较简单,就是检测是否具备敞开线程池的权限,期间应用了线程池的全局锁。 ...

September 10, 2021 · 2 min · jiezi

关于高并发:从源码角度解析线程池中顶层接口和抽象类

摘要:咱们就来看看线程池中那些十分重要的接口和抽象类,深度剖析下线程池中是如何将形象这一思维使用的酣畅淋漓的。本文分享自华为云社区《【高并发】深度解析线程池中那些重要的顶层接口和抽象类》,作者:冰 河。 通过对线程池中接口和抽象类的剖析,你会发现,整个线程池设计的是如此的优雅和弱小,从线程池的代码设计中,咱们学到的不只是代码而已!! 题外话:膜拜Java大神Doug Lea,Java中的并发包正是这位老爷子写的,他是这个世界上对Java影响力最大的一个人。 一、接口和抽象类总览说起线程池中提供的重要的接口和抽象类,基本上就是如下图所示的接口和类。 接口与类的简略阐明: Executor接口:这个接口也是整个线程池中最顶层的接口,提供了一个无返回值的提交工作的办法。ExecutorService接口:派生自Executor接口,扩大了很过性能,例如敞开线程池,提交工作并返回后果数据、唤醒线程池中的工作等。AbstractExecutorService抽象类:派生自ExecutorService接口,实现了几个十分实现的办法,供子类进行调用。ScheduledExecutorService定时工作接口,派生自ExecutorService接口,领有ExecutorService接口定义的全副办法,并扩大了定时工作相干的办法。接下来,咱们就别离从源码角度来看下这些接口和抽象类从顶层设计上提供了哪些性能。 二、Executor接口Executor接口的源码如下所示。 public interface Executor { //提交运行工作,参数为Runnable接口对象,无返回值 void execute(Runnable command);}从源码能够看出,Executor接口非常简单,只提供了一个无返回值的提交工作的execute(Runnable)办法。 因为这个接口过于简略,咱们无奈得悉线程池的执行后果数据,如果咱们不再应用线程池,也无奈通过Executor接口来敞开线程池。此时,咱们就须要ExecutorService接口的反对了。 三、ExecutorService接口ExecutorService接口是非定时工作类线程池的外围接口,通过ExecutorService接口可能向线程池中提交工作(反对有返回后果和无返回后果两种形式)、敞开线程池、唤醒线程池中的工作等。ExecutorService接口的源码如下所示。 package java.util.concurrent;import java.util.List;import java.util.Collection;public interface ExecutorService extends Executor { //敞开线程池,线程池中不再承受新提交的工作,然而之前提交的工作持续运行,直到实现 void shutdown(); //敞开线程池,线程池中不再承受新提交的工作,会尝试进行线程池中正在执行的工作。 List<Runnable> shutdownNow(); //判断线程池是否曾经敞开 boolean isShutdown(); //判断线程池中的所有工作是否完结,只有在调用shutdown或者shutdownNow办法之后调用此办法才会返回true。 boolean isTerminated(); //期待线程池中的所有工作执行完结,并设置超时工夫 boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException; //提交一个Callable接口类型的工作,返回一个Future类型的后果 <T> Future<T> submit(Callable<T> task); //提交一个Callable接口类型的工作,并且给定一个泛型类型的接管后果数据参数,返回一个Future类型的后果 <T> Future<T> submit(Runnable task, T result); //提交一个Runnable接口类型的工作,返回一个Future类型的后果 Future<?> submit(Runnable task); //批量提交工作并取得他们的future,Task列表与Future列表一一对应 <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks) throws InterruptedException; //批量提交工作并取得他们的future,并限定解决所有工作的工夫 <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit) throws InterruptedException; //批量提交工作并取得一个曾经胜利执行的工作的后果 <T> T invokeAny(Collection<? extends Callable<T>> tasks) throws InterruptedException, ExecutionException; //批量提交工作并取得一个曾经胜利执行的工作的后果,并限定解决工作的工夫 <T> T invokeAny(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException;}对于ExecutorService接口中每个办法的含意,间接上述接口源码中的正文即可,这些接口办法都比较简单,我就不一一反复列举形容了。这个接口也是咱们在应用非定时工作类的线程池中最常应用的接口。 ...

August 19, 2021 · 4 min · jiezi

关于高并发:jmmvolatile学习

一、古代计算机实践模型与工作形式古代计算机模型是基于-冯诺依曼计算机模型计算机在运行时,先从内存中取出第一条指令,通过控制器的译码,按指令的要求,从存储器中取出数据进行指定的运算和逻辑操作等加工,而后再按地址把后果送到内存中去。接下来,再取出第二条指令,在控制器的指挥下实现规定操作。依此进行上来。直至遇到进行指令。程序与数据一样存贮,按程序编排的程序,一步一步地取出指令,主动地实现指令规定的操作是计算机最根本的工作模型。这一原理最后是由美籍匈牙利数学家冯.诺依曼于1945年提进去的,故称为冯.诺依曼计算机模型。计算机五大外围组成部分: 控制器(Control):是整个计算机的中枢神经,其性能是对程序规定的管制信息进行解释,依据其要求进行管制,调度程序、数据、地址,协调计算机各局部工作及内存与外设的访问等。运算器(Datapath):运算器的性能是对数据进行各种算术运算和逻辑运算,即对数据进行加工解决。存储器(Memory):存储器的性能是存储程序、数据和各种信号、命令等信息,并在需要时提供这些信息。输出(Input system):输出设施是计算机的重要组成部分,输出设施与输出设备合你为外部设备,简称外设,输出设施的作用是将程序、原始数据、文字、字符、管制命令或现场采集的数据等信息输出到计算机。常见的输出设施有键盘、鼠标器、光电输出机、磁带机、磁盘机、光盘机等。输入(Output system):输出设备与输出设施同样是计算机的重要组成部分,它把外算机的两头后果或最初后果、机内的各种数据符号及文字或各种管制信号等信息输入进去。微机罕用的输出设备有显示终端CRT、打印机、激光印字机、绘图仪及磁带、光盘机等。下图-冯诺依曼计算机模型图古代计算机硬件构造原理图 CPU内部结构划分 1、管制单元管制单元是整个CPU的指挥控制中心,由指令寄存器IR(Instruction Register)、指令译码器ID(Instruction Decoder)和 操作控制器OC(Operation Controller) 等组成,对协调整个电脑有序工作极为重要。它依据用户事后编好的程序,顺次从存储器中取出各条指令,放在指令寄存器IR中,通过指令译码(剖析)确定应该进行什么操作,而后通过操作控制器OC,按确定的时序,向相应的部件收回微操作管制信号。操作控制器OC中次要包含:节奏脉冲发生器、管制矩阵、时钟脉冲发生器、复位电路和启停电路等管制逻辑。 2、运算单元运算单元是运算器的外围。能够执行算术运算(包含加减乘数等根本运算及其附加运算)和逻辑运算(包含移位、逻辑测试或两个值比拟)。绝对管制单元而言,运算器承受管制单元的命令而进行动作,即运算单元所进行的全副操作都是由管制单元收回的管制信号来指挥的,所以它是执行部件。 3、存储单元 存储单元包含 CPU 片内缓存Cache和寄存器组,是 CPU 中临时存放数据的中央,外面保留着那些期待解决的数据,或曾经解决过的数据,CPU 拜访寄存器所用的工夫要比拜访内存的工夫短。 寄存器是CPU外部的元件,寄存器领有十分高的读写速度,所以在寄存器之间的数据传送十分快。采纳寄存器,能够缩小 CPU 拜访内存的次数,从而进步了 CPU 的工作速度。寄存器组可分为专用寄存器和通用寄存器。专用寄存器的作用是固定的,别离存放相应的数据;而通用寄存器用处宽泛并可由程序员规定其用处。计算机硬件多CPU架构: 在window上的工作管理器能够看见 多CPU 一个古代计算机通常由两个或者多个CPU,如果要运行多个程序(过程)的话,如果只有一个CPU的话,就意味着要常常进行过程上下文切换,因为单CPU即使是多核的,也只是多个处理器外围,其余设施都是共用的,所以 多个过程就必然要常常进行过程上下文切换,这个代价是很高的。 CPU多核 一个古代CPU除了处理器外围之外还包含寄存器、L1L2L3缓存这些存储设备、浮点运算单元、整数运算单元等一些辅助运算设施以及外部总线等。一个多核的CPU也就是一个CPU上有多个处理器外围,这样有什么益处呢?比如说当初咱们要在一台计算机上跑一个多线程的程序,因为是一个过程里的线程,所以须要一些共享一些存储变量,如果这台计算机都是单核单线程CPU的话,就意味着这个程序的不同线程须要常常在CPU之间的内部总线上通信,同时还要解决不同CPU之间不同缓存导致数据不统一的问题,所以在这种场景下多核单CPU的架构就能施展很大的劣势,通信都在外部总线,共用同一个缓存。 CPU寄存器 ‘每个CPU都蕴含一系列的寄存器,它们是CPU内内存的根底。CPU在寄存器上执行操作的速度远大于在主存上执行的速度。这是因为CPU拜访寄存器的速度远大于主存。 CPU缓存 即高速缓冲存储器,是位于CPU与主内存间的一种容量较小但速度很高的存储器。因为 CPU的速度远高于主内存,CPU间接从内存中存取数据要期待肯定工夫周期,Cache中保留着CPU刚用过或循环应用的一部分数据,当CPU再次应用该局部数据时可从Cache中间接调用,缩小CPU的等待时间,进步了零碎的效率。 一级Cache(L1 Cache)二级Cache(L2 Cache)三级Cache(L3 Cache)内存 一个计算机还蕴含一个主存。所有的CPU都能够拜访主存。主存通常比CPU中的缓存大得多。 CPU读取存储器数据过程 CPU要取寄存器XX的值,只须要一步:间接读取。 CPU要取L1 cache的某个值,须要1-3步(或者更多):把cache行锁住,把某个数据拿来,解锁,如果没锁住就慢了。CPU要取L2 cache的某个值,先要到L1 cache里取,L1当中不存在,在L2里,L2开始加锁,加锁当前,把L2里的数据复制到L1,再执行读L1的过程,下面的3步,再解锁。CPU取L3 cache的也是一样,只不过先由L3复制到L2,从L2复制到L1,从L1到CPU。 CPU取内存则最简单:告诉内存控制器占用总线带宽,告诉内存加锁,发动内存读申请,期待回应,回应数据保留到L3(如果没有就到L2),再从L3/2到L1,再从L1到CPU,之后解除总线锁定。 多线程环境下存在的问题 缓存一致性问题 在多处理器零碎中,每个处理器都有本人的高速缓存,而它们又共享同一主内存 (MainMemory)。基于高速缓存的存储交互很好地解决了处理器与内存的速度矛盾,然而也引入了新的问题:缓存一致性(CacheCoherence)。当多个处理器的运算工作都波及同一块主内存区域时,将可能导致各自的缓存数据不统一的状况,如果真的产生这种状况,那同步回到主内存时以谁的缓存数据为准呢?为了解决一致性的问题,须要各个处理器拜访缓存时都遵循一些协定,在读写时要依据协定来进行操作,这类协定有MSI、MESI(IllinoisProtocol)、MOSI、Synapse、Firefly及DragonProtocol,等等MESI中每个缓存行都有四个状态,别离是E(exclusive)、M(modified)、S(shared)、I(invalid)。上面咱们介绍一下这四个状态别离代表什么意思。 M:代表该缓存行中的内容被批改了,并且该缓存行只被缓存在该CPU中。这个状态的缓存行中的数据和内存中的不一样,在将来的某个时刻它会被写入到内存中(当其余CPU要读取该缓存行的内容时。或者其余CPU要批改该缓存对应的内存中的内容时(集体了解CPU要批改该内存时先要读取到缓存中再进行批改),这样的话和读取缓存中的内容其实是一个情理)。 E:E代表该缓存行对应内存中的内容只被该CPU缓存,其余CPU没有缓存该缓存对应内存行中的内容。这个状态的缓存行中的内容和内存中的内容统一。该缓存能够在任何其余CPU读取该缓存对应内存中的内容时变成S状态。或者本地处理器写该缓存就会变成M状态。 S:该状态意味着数据不止存在本地CPU缓存中,还存在别的CPU的缓存中。这个状态的数据和内存中的数据是统一的。当有一个CPU批改该缓存行对应的内存的内容时会使该缓存行变成 I 状态。 I:代表该缓存行中的内容时有效的。例子:假如有两个CPU。 指令重排序问题 为了使得处理器外部的运算单元能尽量被充分利用,处理器可能会对输出代码进行乱序执行(Out-Of-Order Execution)优化,处理器会在计算之后将乱序执行的后果重组,保障该后果与程序执行的后果是统一的,但并不保障程序中各个语句计算的先后顺序与输出代码中的程序统一。因而,如果存在一个计算工作依赖另一个计算工作的两头后果,那么其程序性并不能靠代码的先后顺序来保障。与处理器的乱序执行优化相似,Java虚拟机的即时编译器中也有相似的指令重排序(Instruction Reorder)优化 指令重排序的证实(解决办法:应用volatile、锁或者手动增加内存屏障) package com.jiagouedu.jmm; public class VolatileReOrderSample { ...

July 4, 2021 · 3 min · jiezi

关于高并发:接招吧最强-高并发-系统设计-46-连问分分钟秒杀一众面试者

接招吧!最强 “高并发” 零碎设计 46 连问,分分钟秒杀一众面试者!谈起 “高并发” 零碎设计相干常识,我想你必须要认知到的一个问题是:它是你获取一线大厂Offer 必不可少的利器!!对于各大公司(比方阿里、腾讯、今日头条等)来说,仅仅懂得CRUD的程序员便不如有 “高并发”零碎设计 教训的程序员有吸引力! 所以当你面试时,面试官会要求你有高并发设计教训,且有的面试官会询问你的零碎在遭逢百万并发时可能有哪些瓶颈点,以及有什么优化思路等问题...为的就是测验你是否真的理解这方面的内容...为助你迅速把握 “高并发”零碎设计 的相干常识内容等,这46连问(含解析)你必须铭刻于心,蕴含:根底篇 - 数据库篇 - 缓存篇 - 音讯队列篇 - 分布式服务篇 - 保护篇 - 实战篇 留神:篇幅起因,以下皆以图片展现这份 最强 “高并发” 零碎设计 46 连问(附解析)有近400页 ☛ 原件(点击下载)“高并发” 零碎设计 - 根底篇01 为什么你要学习高并发零碎设计02 高并发零碎:它的通用设计办法是什么03 架构分层:咱们为什么肯定要这么做04 零碎设计指标(一):如何晋升零碎性能05 零碎设计指标(二):零碎怎么做到高可用06 零碎设计指标(三):如何让零碎易于扩大07 面试现场第一期:当问到组件实现原理时,面试官是在刁难你吗 “高并发” 零碎设计 - 根底篇 触类旁通坚固必问思考题: 高并发零碎演进是一个渐进的过程,并非欲速不达的,那么你在零碎演进过程中积攒了哪些教训又踩到了哪些坑呢?咱们提到了分层架构的多种模型,比方三层架构模型,阿里巴巴提出的分层架构模型,那么在你日常开发的过程中,会如何来做架构分层呢?你感觉如此分层的劣势是什么呢?咱们提到了一些性能优化的准则和根本的思考点,那么你在日常工作中有哪些性能优化的伎俩和教训呢?提到了很多保障高可用的伎俩,那么你在工作中会有哪些保证系统高可用的设计技巧呢?传统关系型数据库的可扩展性是很差的,那么在你看来,常见的 NoSQL 数据库是如何解决扩展性的问题呢?“高并发” 零碎设计 - 数据库篇08 池化技术:如何缩小频繁创立数据库连贯的性能损耗09 数据库优化计划(一):查问申请减少时,如何做主从拆散 10 数据库优化计划(二):写入数据量减少时,如何实现分库分表11 发号器:如何保障分库分表后ID的全局唯─性 12 NoSQL:在高并发场景下,数据库和 NoSQL 如何做到互补 “高并发” 零碎设计 - 数据库篇 触类旁通坚固必问思考题: 在理论的我的项目中,你可能会用到其余的池化技术,那么联合池化的内容,分享一下在研发过程中,还应用过哪些其它池化技术吗?又因池化技术踩过哪些坑,过后你是怎么解决的?咱们提到,存储节点间相互复制数据是一种常见的,晋升零碎可用性和性能的形式,那么你还理解哪些组件有应用这种形式呢?它们的复制形式又是如何的呢?分库分表实际上是分布式存储中一种数据分片的解决方案,那么你还理解哪些分布式存储组件也应用了相似的技术呢?它的实现形式你理解吗?理解了分布式发号器的实现原理和生成 ID 的个性,那么在你的零碎中你的 ID 是如何生成的呢?NoSQL 数据库是能够与传统的关系型数据库配合,一起解决数据存储问题的,那么在日常工作中,你用到了哪些 NoSQL 数据库呢?在选型的时候是基于什么样的思考呢?“高并发” 零碎设计 - 缓存篇13 缓存:数据库成为瓶颈后,动态数据的查问要如何减速14 缓存的应用姿态(一):如何抉择缓存的读写策略15 缓存的应用姿态(二):缓存如何做到高可用16 缓存的应用姿态(三):缓存穿透了怎么办17 C D N:动态资源如何减速 18 数据的迁徙应该如何做 ...

May 28, 2021 · 1 min · jiezi

关于高并发:互联网高并发技术方案选型思考和实践

本文试图通过渐进的技术剖析,和大家分享咱们在互联网高并发技术计划抉择上的一些思考和决策;从技术选型的高度为架构师在面对高并发业务设计时须要思考的方方面面做一个参考。 Beautiful Concurrency & Pretty Erlang ========================================== 前言 环信以“连贯人与人,连贯人与商业”为使命,旨在为宽广企业开发者提供最优质的寰球即时通讯PaaS服务。如何实现高并发场景下,弹性化的保障服务质量是咱们一贯的业务要求和技术谋求。 本文试图通过渐进的技术剖析,和大家分享咱们在互联网高并发技术计划抉择上的一些思考和决策;从技术选型的高度为架构师在面对高并发业务设计时须要思考的方方面面做一个参考。 接下来,enjoy: Beautiful Concurrency – 并发的必要性世界是并发的,软件也应该是并发的咱们生存在其中的世界,就是一个微小的并发零碎。每时每刻,在世界的每一个角落,人类的每一个个体都在和这个世界进行着频繁的能量交互,信息交互也是其中的重要组成部分;当咱们转换身份,以造物主的视角鸟瞰这个世界里所有的万物(动物,动物,陆地,土壤,机器等等)时,也能够看到它们同样在和这个世界进行着无休止的能量/信息交互。 为了与这个世界进行无效的交互,软件也应该是并发的。 世界是散布的,软件也应该是散布的地球是圆的,世界是平的,不管怎样,从宇宙大爆炸的那个奇点之后,就是散布的宇宙/世界。作为与世界万物(包含人类本人)交互的软件,天然也必须满足分布式要求。而这种地理分布(Geo. Distribution)个性,也仅是并发在空间维度下的反映而已。 世界不可预测,软件也应该是容错的没有完满的世界:抵触,劫难随时在产生,不论在什么样的维度上。作为软件,bug,crash也是不可躲避的事实挑战。即便存在完满的没有bug的程序,运行程序的硬件也可能呈现故障。为了加强软件的容错性,代码的独立性(指一个故障不会影响到故障工作以外的其它工作)和故障检测以及故障解决是要害:这所有都须要并发,因为串行程序的容错性远远不如并发程序。 并发计划概览“七个模型”来源于Paul Butcher著的《Seven Concurrency Models in Seven Weeks》,中文译名《七周七并发模型》,概览的介绍了并发畛域的常见计划,心愿能给架构师提供一个轮廓化的分类形容。自己在其根底上增加了一些本人的拓展思考(_见下文中斜体局部_): 1.线程与锁_:线程与锁模型有很多家喻户晓的有余,但仍是其余模型的技术根底,也是很多并发软件开发的首选。— _这个计划其实是一个anti-pattern,在高并发场景下如履薄冰(bug,dead lock如影随形),让开发者和运维人员胆战心惊。__Ugly Locks to Ugly Concurrency (俊俏的锁,俊俏的并发):locks and condition variables is fundamentally flawed! 2.函数式编程_:函数式编程日渐重要的起因之一,是其对并发编程和并行编程提供了良好的反对。函数式编程打消了可变状态,所以从根本上是线程平安的,而且易于并行执行。_— 函数之美,逻辑之美!置信很多从命令式语言(Imperative Programming)转战到函数式编程语言(Functional Programminmg)的时候都会收回这样的感叹。其实这一提高恰好体现了人类在一直的进化过程中,对这个世界认知一直提炼,思维模式逐渐由具象走向形象的演进轨迹。而回到高并发的话题上,函数式编程以不可变状态这一繁难的策略,博得了完满赞美,俨然已是君临天下的明日霸主! 3.拆散标识与状态:_如果一个线程援用了长久数据结构,那么其余线程对数据结构的批改对该线程就是不可见的。因而长久数据结构对并发编程的意义非比寻 常,其拆散了标识(identity)与状态(state)。 _— 这又是一个很妙的策略,而大家熟知的version control system如git,包含比特币/区块链的机制都是这一思维领导下的具体实际,限于篇幅,本文不做进一步开展。 4.Actor Model:_一种适用性很广的并发编程模型,实用于共享内存模型和分布式内存模型,也适宜解决地理分布型问题,能提供弱小的容错性。_— 最开始接触到Actor模型就是通过Erlang语言,起初又接触到Akka(基于Scala)等基于各种语言实现的框架,也越来越领会到这一模型在高并发场景下的熟能生巧。本文后续局部会开展介绍。另外,做个招聘小广告,环信通信云研发团队正在广纳英才,欢送懂Erlang,有相干高并发开发教训的小伙伴加盟,虚位以待!点这里间接分割咱们哟! 5.CSP(Communicating Sequential Processes, CSP)_:外表上看,CSP模型与Actor Model很类似,两者都基于消息传递。不过CSP模型侧重于传递信息的通道,而Actor Model侧重于通道两端的实体,应用CSP模型的代码会带有显著不同的格调。_— 这里就是channel能够大施拳脚的天地了,go go go!限于篇幅,本文不做进一步开展。同样的,欢送懂Golang,有相干高并发开发教训的小伙伴加盟,虚位以待! 6.数据级并行:_每个笔记本电脑里都藏着一台超级计算机——GPU。GPU利用了数据级并行,不仅能够疾速进行图像处理,也能够用于更 广大的畛域。如果要进行有限元剖析、流体力学计算或其余的大量数字计算,GPU的性能将是不二抉择。_— 在过来的两年里,华人之光,黄仁勋(Jensen Huang, CEO of Nvidia),从自家的壁炉里一次又一次给大家带来了震撼世界的变革产品,让之前遥不可及的GPU飞入寻常百姓家,也带来了一次又一次的算力之争。置信在不久的未来,有了GPU算力加持和人工智能算法的普惠应用,会有有数的AI利用层出不穷的涌现,它们会从云端落地到边缘,人类可能会比本人设想的更早的进入前途未卜的人机争霸时代。 7.Lambda架构:_Lambda架构综合了MapReduce和流式解决的特点,是一种能够解决多种大数据问题的架构。_— Lambda架构也是采纳了数据并行处理技术,然而它把并行算力的宏观场景放大到了一个更大的尺度:将数据和计算散布到成千上万台机器组成的集群上进行,将并发,散布个性整合到一套计划中,通过两层(批处理层-Batch Layer,减速层-Speed Layer/Streaming Process)的组合,实现了高计算效率和低提早的“鱼与熊掌兼得”。 ...

March 12, 2021 · 1 min · jiezi

关于高并发:从根上理解高性能高并发三深入操作系统彻底理解IO多路复用

1、系列文章引言1.1 文章目标作为即时通讯技术的开发者来说,高性能、高并发相干的技术概念早就了然与胸,什么线程池、零拷贝、多路复用、事件驱动、epoll等等名词信手拈来,又或者你对具备这些技术特色的技术框架比方:Java的Netty、Php的workman、Go的nget等熟练掌握。但真正到了面视或者技术实际过程中遇到无奈释怀的纳闷时,方知自已所把握的不过是皮毛。 返璞归真、回归实质,这些技术特色背地的底层原理到底是什么?如何能通俗易懂、毫不费力真正透彻了解这些技术背地的原理,正是《从根上了解高性能、高并发》系列文章所要分享的。 1.2 文章源起我整顿了相当多无关IM、音讯推送等即时通讯技术相干的资源和文章,从最开始的开源IM框架MobileIMSDK,到网络编程经典巨著《TCP/IP详解》的在线版本,再到IM开发纲领性文章《新手入门一篇就够:从零开发挪动端IM》,以及网络编程由浅到深的《网络编程懒人入门》、《脑残式网络编程入门》、《高性能网络编程》、《鲜为人知的网络编程》系列文章。 越往常识的深处走,越感觉对即时通讯技术理解的太少。于是起初,为了让开发者门更好地从根底电信技术的角度了解网络(尤其挪动网络)个性,我跨专业收集整理了《IM开发者的零根底通信技术入门》系列高阶文章。这系列文章未然是一般即时通讯开发者的网络通信技术常识边界,加上之前这些网络编程材料,解决网络通信方面的常识盲点根本够用了。 对于即时通讯IM这种零碎的开发来说,网络通信常识的确十分重要,但回归到技术实质,实现网络通信自身的这些技术特色:包含下面提到的线程池、零拷贝、多路复用、事件驱动等等,它们的实质是什么?底层原理又是怎么?这就是整顿本系列文章的目标,心愿对你有用。 1.3 文章目录《从根上了解高性能、高并发(一):深刻计算机底层,了解线程与线程池》《从根上了解高性能、高并发(二):深刻操作系统,了解I/O与零拷贝技术》《从根上了解高性能、高并发(三):深刻操作系统,彻底了解I/O多路复用》(* 本文)《从根上了解高性能、高并发(四):深刻操作系统,彻底了解同步与异步 (稍后公布..)》《从根上了解高性能、高并发(五):高并发高性能服务器到底是如何实现的 (稍后公布..)》1.4 本篇概述接上篇《深刻操作系统,了解I/O与零拷贝技术》,本篇是高性能、高并发系列的第3篇文章,上篇里咱们讲到了I/O技术,本篇将以更具象的文件这个话题动手,带你一步步了解高性能、高并发服务端编程时无奈回避的I/O多路复用及相干技术。 本文已同步公布于“即时通讯技术圈”公众号,欢送关注。公众号上的链接是:点此进入。 2、本文作者应作者要求,不提供真名,也不提供集体照片。 本文作者次要技术方向为互联网后端、高并发高性能服务器、检索引擎技术,网名是“码农的荒岛求生”,公众号“码农的荒岛求生”。感激作者的自私分享。 3、什么是文件?在正式开展本文的内容之前,咱们须要先预习一下文件以及文件描述符的概念。 程序员应用I/O最终都逃不过文件这个概念。 在Linux世界中文件是一个很简略的概念,作为程序员咱们只须要将其了解为一个N byte的序列就能够了: b1, b2, b3, b4, ....... bN实际上所有的I/O设施都被形象为了文件这个概念,所有皆文件(Everything is File),磁盘、网络数据、终端,甚至过程间通信工具管道pipe等都被当做文件看待。 所有的I/O操作也都能够通过文件读写来实现,这一十分优雅的形象能够让程序员应用一套接口就能对所有外设I/O操作。 罕用的I/O操作接口个别有以下几类: 1)关上文件,open;2)扭转读写地位,seek;3)文件读写,read、write;4)敞开文件,close。程序员通过这几个接口简直能够实现所有I/O操作,这就是文件这个概念的弱小之处。 4、什么是文件描述符?在上一篇《深刻操作系统,了解I/O与零拷贝技术》中咱们讲到:要想进行I/O读操作,像磁盘数据,咱们须要指定一个buff用来装入数据。 个别都是这样写的: read(buff);然而这里咱们疏忽了一个关键问题:那就是,尽管咱们指定了往哪里写数据,然而咱们该从哪里读数据呢? 从上一节中咱们晓得,通过文件这个概念咱们能实现简直所有I/O操作,因而这里少的一个配角就是文件。 那么咱们个别都怎么应用文件呢? 举个例子:如果周末你去比拟火的餐厅吃饭应该会有领会,个别周末人气高的餐厅都会排队,而后服务员会给你一个排队序号,通过这个序号服务员就能找到你,这里的益处就是服务员无需记住你是谁、你的名字是什么、来自哪里、爱好是什么、是不是保护环境爱护小动物等等,这里的关键点就是:服务员对你无所不知,但仍然能够通过一个号码就能找到你。 同样的:在Linux世界要想应用文件,咱们也须要借助一个号码,依据“弄不懂准则”,这个号码就被称为了文件描述符(file descriptors),在Linux世界中鼎鼎大名,其情理和下面那个排队号码一样。 因而:文件形容仅仅就是一个数字而已,然而通过这个数字咱们能够操作一个关上的文件,这一点要记住。 有了文件描述符,过程能够对文件无所不知,比方文件在磁盘的什么地位、加载到内存中又是怎么治理的等等,这些信息通通交由操作系统打理,过程无需关怀,操作系统只须要给过程一个文件描述符就足够了。 因而咱们来欠缺上述程序: int fd = open(file_name); // 获取文件描述符read(fd, buff);怎么样,是不是非常简单。 5、文件描述符太多了怎么办?通过了这么多的铺垫,终于要到高性能、高并发这一主题了。 从前几节咱们晓得,所有I/O操作都能够通过文件样的概念来进行,这当然包含网络通信。 如果你有一个IM服务器,当三次握手倡议长连贯胜利当前,咱们会调用accept来获取一个链接,调用该函数咱们同样会失去一个文件描述符,通过这个文件描述符就能够解决客户端发送的聊天音讯并且把音讯转发给接收者。 也就是说,通过这个描述符咱们就能够和客户端进行通信了: // 通过accept获取客户端的文件描述符int conn_fd = accept(...);Server端的解决逻辑通常是接管客户端音讯数据,而后执行转发(给接收者)逻辑: if(read(conn_fd, msg_buff) > 0) {do_transfer(msg_buff);}是不是非常简单,然而世界终归是简单的,当然也不是这么简略的。 接下来就是比较复杂的了。 ...

January 5, 2021 · 1 min · jiezi

关于高并发:并发编程中一种经典的分而治之的思想

写在后面在JDK中,提供了这样一种性能:它可能将简单的逻辑拆分成一个个简略的逻辑来并行执行,待每个并行执行的逻辑执行实现后,再将各个后果进行汇总,得出最终的后果数据。有点像Hadoop中的MapReduce。ForkJoin是由JDK1.7之后提供的多线程并发解决框架。ForkJoin框架的根本思维是分而治之。什么是分而治之?分而治之就是将一个简单的计算,依照设定的阈值分解成多个计算,而后将各个计算结果进行汇总。相应的,ForkJoin将简单的计算当做一个工作,而合成的多个计算则是当做一个个子工作来并行执行。 注:文章已同步收录到:https://github.com/sunshinely... 和 https://gitee.com/binghe001/t... 。如果文件对你有点帮忙,别忘记给个Star哦!如果小伙伴们有任何疑难,都能够加我微信【sun_shine_lyz】进行交换哦! Java并发编程的倒退对于Java语言来说,生来就反对多线程并发编程,在并发编程畛域也是在一直倒退的。Java在其倒退过程中对并发编程的反对越来越欠缺也正好印证了这一点。 Java 1 反对thread,synchronized。Java 5 引入了 thread pools, blocking queues, concurrent collections,locks, condition queues。Java 7 退出了fork-join库。Java 8 退出了 parallel streams。并发与并行并发和并行在实质上还是有所区别的。 并发并发指的是在同一时刻,只有一个线程可能获取到CPU执行工作,而多个线程被疾速的轮换执行,这就使得在宏观上具备多个线程同时执行的成果,并发不是真正的同时执行,并发能够应用下图示意。 并行并行指的是无论何时,多个线程都是在多个CPU外围上同时执行的,是真正的同时执行。 分治法根本思维把一个规模大的问题划分为规模较小的子问题,而后分而治之,最初合并子问题的解失去原问题的解。步骤①宰割原问题; ②求解子问题; ③合并子问题的解为原问题的解。 咱们能够应用如下伪代码来示意这个步骤。 if(工作很小){ 间接计算失去后果}else{ 分拆成N个子工作 调用子工作的fork()进行计算 调用子工作的join()合并计算结果}在分治法中,子问题个别是互相独立的,因而,常常通过递归调用算法来求解子问题。 典型利用二分搜寻大整数乘法Strassen矩阵乘法棋盘笼罩合并排序疾速排序线性工夫抉择汉诺塔ForkJoin并行处理框架ForkJoin框架概述Java 1.7 引入了一种新的并发框架—— Fork/Join Framework,次要用于实现“分而治之”的算法,特地是分治之后递归调用的函数。 ForkJoin框架的实质是一个用于并行执行工作的框架, 可能把一个大工作宰割成若干个小工作,最终汇总每个小工作后果后失去大工作的计算结果。在Java中,ForkJoin框架与ThreadPool共存,并不是要替换ThreadPool 其实,在Java 8中引入的并行流计算,外部就是采纳的ForkJoinPool来实现的。例如,上面应用并行流实现打印数组元组的程序。 public class SumArray { public static void main(String[] args){ List<Integer> numberList = Arrays.asList(1,2,3,4,5,6,7,8,9); numberList.parallelStream().forEach(System.out::println); }}这段代码的背地就应用到了ForkJoinPool。 说到这里,可能有读者会问:能够应用线程池的ThreadPoolExecutor来实现啊?为什么要应用ForkJoinPool啊?ForkJoinPool是个什么鬼啊?! 接下来,咱们就来答复这个问题。 ForkJoin框架原理ForkJoin框架是从jdk1.7中引入的新个性,它同ThreadPoolExecutor一样,也实现了Executor和ExecutorService接口。它应用了一个有限队列来保留须要执行的工作,而线程的数量则是通过构造函数传入,如果没有向构造函数中传入指定的线程数量,那么以后计算机可用的CPU数量会被设置为线程数量作为默认值。 ForkJoinPool次要应用分治法(Divide-and-Conquer Algorithm)来解决问题。典型的利用比方疾速排序算法。这里的要点在于,ForkJoinPool可能应用绝对较少的线程来解决大量的工作。比方要对1000万个数据进行排序,那么会将这个工作宰割成两个500万的排序工作和一个针对这两组500万数据的合并工作。以此类推,对于500万的数据也会做出同样的宰割解决,到最初会设置一个阈值来规定当数据规模到多少时,进行这样的宰割解决。比方,当元素的数量小于10时,会进行宰割,转而应用插入排序对它们进行排序。那么到最初,所有的工作加起来会有大略200万+个。问题的关键在于,对于一个工作而言,只有当它所有的子工作实现之后,它才可能被执行。 ...

December 15, 2020 · 2 min · jiezi

关于高并发:接下来冰河要有大动作了

写在后面置信看到这个题目后,不少小伙伴会想:题目党,能有啥大动作?不过,我要说的是:持续往下看,起码最近的一段时间我要调整下公众号的更新了,为啥?大家持续往下看吧。 注:文章已同步收录到:https://github.com/sunshinelyz/technology-binghe 和 https://gitee.com/binghe001/technology-binghe 。如果文件对你有点帮忙,别忘记给个Star哦!如果小伙伴们有任何疑难,都能够加我微信【sun_shine_lyz】进行交换哦! 出版实体书首先,往年出版了两本实体书,一本是《海量数据处理与大数据技术实战》。 一本是《MySQL技术大全:开发、优化与运维实战》两本书都是超硬核的技术干货。 两本书都是超硬核的技术干货,目前在天猫、京东和当当均已上架。 原创PDF电子书通过一直的积攒和输入,冰河整顿出8本原创的PDF,其中,《深刻了解高并发编程(第1版)》电子书,作为全网最牛逼的收费开源的高并发编程PDF,自开源以来,已累计全网下载6W+。目前,这个数字仍在上涨。小伙伴们能够通过如下形式收费支付这些PDF电子书,每一本都是超硬核的技术干货。而且,每一本电子书的内容后续都会一直迭代和更新,始终保持最新、最硬核的技术。 关注 冰河技术 微信公众号: 回复 “并发编程” 支付《深刻了解高并发编程(第1版)》PDF文档。 回复 “并发源码” 支付《并发编程外围常识(源码剖析篇 第1版)》PDF文档。 回复 ”限流“ 支付《亿级流量下的分布式解决方案》PDF文档。 回复 “设计模式” 支付《深入浅出Java23种设计模式》PDF文档。 回复 “Java8新个性” 支付 《Java8新个性教程》PDF文档。 回复 “分布式存储” 支付《跟冰河学习分布式存储技术》 PDF文档。 回复 “Nginx” 支付《跟冰河学习Nginx技术》PDF文档。 回复 “互联网工程” 支付《跟冰河学习互联网工程技术》PDF文档。 我的开源我的项目除了写书、写公众号、整顿原创PDF之外,我还在保护着本人的开源我的项目,什么?你没看错,都是集体开源的我的项目,有些曾经在某些公司的理论生产环境中应用。这些开源我的项目中,典型的有如下几个: mykit-serial全网首个齐全开源的分布式全局有序序列号(分布式ID生成器)服务mykit-serial,反对嵌入式(Jar包)、RPC(Dubbo)、Restful API形式公布服务。开源地址: GitHub: https://github.com/sunshinelyz/mykit-serial Gitee: https://gitee.com/binghe001/mykit-serial mykit-transaction-message基于可靠消息最终一致性的分布式事务框架mykit-transaction-message开源地址: GitHub: https://github.com/sunshinelyz/mykit-transaction-message Gitee: https://gitee.com/binghe001/mykit-transaction-message mykit-delay精准定时工作和提早队列框架mykit-delay开源地址: GitHub: https://github.com/sunshinelyz/mykit-delay Gitee: https://gitee.com/binghe001/mykit-delay technology-binghe次要收录冰河技术微信公众号的文章。 Github: https://github.com/sunshinelyz/technology-binghe Gitee: https://gitee.com/binghe001/technology-binghe 以上开源我的项目,我会重点保护,其余的开源我的项目,小伙伴们能够到我的Github上查看,根本以mykit结尾的我的项目都是我集体开源的。这里,我也心愿可能有更多的小伙伴退出,咱们一起开发和保护这些开源我的项目。 重点来了说了这么多,重点来了,冰河接下来要干什么呢? ...

December 13, 2020 · 1 min · jiezi

关于高并发:高并发系统设计

在业务量越来越大的时候,零碎访问量同时大了起来,这个时候就要思考零碎如果解决高并发的申请。 性能性能的话分为两个,一个是利用,一个是数据库。单个利用的性能晋升下来了,那集群的整体性能晋升作用会更大。利用就是咱们的代码优化,比方算法的优化,代码的设计形式,jvm的优化。数据库就是sql的优化,比方表构造怎么建,索引怎么建,sql语句怎么写等方面。这些标准能够参考阿里巴巴Java开发手册 拆分架构演进之路和数据库演进之路提到了为了进步零碎并发解决能力,对利用和数据库进行了程度拆分和垂直拆分。 应用层对利用的拆分会有以下几个问题: 分布式事务:在单机利用中,咱们的订单服务和库存服务是一起的,通过数据库的ACID来保障事务,然而拆分后,就没方法通过数据库的ACID来了,所以要如何保障分布式事务?罕用的有2PC/3PC、TCC、Saga分布式锁:在分布式系统下,java提供的各自锁曾经没方法解决这些共享资源的并发问题,所以要如何保障分布式锁呢?罕用的有数据库加锁、zookeeper加锁、redis加锁、etcd加锁。分布式作业调度:一个定时工作部署多份,比方ABC,如何保障他们的定时工作不反复执行?比方罕用的有elastic-job、xxl。数据库对数据库拆分会有以下几个问题: 读写拆散:如何保证数据的一致性。分库分表:分布式下的主键是怎么生成的、分库分表后怎么跨库分页、分库分表是怎么做的?分库分表的中间件有哪些(mycat、sharding-jdbc)。负载平衡在高可用中,咱们提到了冗余,然而仅仅只是当master挂了slave顶上去用,那这个资源就很节约了,所以咱们就想,通过负载平衡让多个服务同时启用,既达到了高可用的目标,也用于解决高并发的申请。但并不是多个服务一起用他就等于能够解决高并发的,比方mysql的主从,因为是异步更新的,所以salve的数据总是提早于master的,如果强一致性要求高的话,就不能用了。如果强一致性没什么要求的话能够用,相似的reidis也一样。所以无状态对于高并发来说,就很重要了。当申请量一上来,咱们就做多个节点就好了。比方咱们用nginx做负载平衡,压力上来了,就多加几个tomcat退出集群就好了,只是咱们要思考到,在这种状况下,session要如何解决?负载平衡罕用的硬件和软件如下: 硬件:F5软件:nginx、apache、lvs、haproxy平衡策略(见dubbo)如下: Random LoadBalance:随机,按权重设置随机概率。RoundRobin LoadBalance:* 轮询,按公约后的权重设置轮询比率。LeastActive LoadBalance:起码沉闷调用数,雷同沉闷数的随机,沉闷数指调用前后计数差。ConsistentHash LoadBalance: 一致性 Hash,雷同参数的申请总是发到同一提供者。缓存缓存对于读服务来说,是抗流量的银弹。然而如何用好缓存,也是很重要的。比方咱们引入了redis,咱们必须保障redis是高可用(redis - 哨兵(高可用)、redis - 集群(一))的,不然reidis挂了怎么办。咱们同样也要保障redis的高并发,要让他扛得住流量(redis - 主从(高性能))。咱们要保障reids挂了能够疾速复原(redis - 长久化)。引入redis,咱们要思考数据库和reids的数据一致性(缓存的数据一致性)。咱们要思考到缓存雪崩了怎么办,缓存穿透了怎么办。 音讯队列音讯队列的次要几个场景有异步、解耦、流量削峰。跟redis一样,咱们同样也要保障音讯队列的高可用,比方ActiveMQ - MasterSlave、RabbitMQ集群、RabbitMQ故障转移。ActiveMQ - 音讯可靠性、RabbitMQ - 发送方的可靠性、RabbitMQ - 音讯确认为了保障音讯的可靠性,发送方或者第三方中间件会反复发送音讯,咱们要保障接管方的幂等性,这个幂等性能够参考接口幂等设计。

November 18, 2020 · 1 min · jiezi

关于高并发:高并发下如何缩短响应时间

定义网站响应工夫是指系统对申请作出响应的工夫。艰深来讲就是咱们把网址输出进浏览器而后敲回车键开始始终到浏览器把网站的内容出现给用户的这段时间。网站响应工夫是越短越好,因为网站页面关上速度越快,就意味着咱们的用户能够更快的拜访站点或者咱们的服务器。个别咱们网站的响应工夫放弃在100~1000ms即可。1m=1000ms,关上速度越快对用户体验度越好。据说响应工夫还会影响到网站SEO成果(请行业专家留言通知我)。 响应工夫并不能间接反映网站性能的高下,然而在肯定水平上反馈了网站零碎的解决能力,也是给用户最直观上的感触。如果网站的响应工夫过长,比方10秒以上,用户的流失率会大大增加,所以把响应工夫管制在肯定范畴内是进步用户体验度的第一因素。 解决方案当用户申请一个网站数据的时候,实际上是发送了一个http申请,在宏观上能够分为两个局部: http申请达到指标网站服务器之前http申请达到指标网站服务器之后如果疏忽其中硬件局部和局部细节,申请一个网站数据的大体过程如下图所示(其中CDN和缓存局部能够省略): 咱们要想缩短一个网站的响应工夫,实质上是进步数据的返回速度,说的直白一点就是要把申请数据过程中的各个步骤进步速度,这样整体下来响应工夫就会缩短。 把数据放在离用户越近的中央响应工夫越快客户端客户端是发动一个网站申请的源头,其实这个源头能够施加肯定的策略来大大缩短某些数据的获取工夫。其中最为罕用的就是缓存,一些罕用的,很少变动的资源缓存在客户端,岂但能缩短获取资源的工夫,而且在很大水平上能加重服务端的压力。比方一些图片,css,js文件,甚至一些接口的数据或者整个网页内容都能够在客户端做缓存。另外http申请的合并也能够缩小对服务端的申请次数,在肯定水平上能够缩短申请的响应工夫。 DNS个别网站的拜访形式都采纳域名的形式(很少见IP形式),既然是域名就波及到DNS解析速度的问题,如果DNS服务解析的速度比较慢,整体过程的响应工夫也会加长,不过这个过程其实很少呈现慢的问题(不是说没有)。 DNS的解析过程能够查看这篇文章 网络客户端获取到网站IP之后通过网卡把Http申请发送进来,指标地址为相应的网站服务器。在这个过程当中如果客户端和服务器端有一方带宽比拟小的话,就会加大响应工夫。我司已经就因为服务器带宽过小导致客户端响应工夫很长的状况,过后排查了很长时间才发现。 当然网络是不牢靠的,这个过程的响应工夫其实取决于很多因素,比方路由器的路由策略是否最优,整个过程通过的网关数据量等。所以有很多网站其实是多地区多机房部署的,目标就是为了让用户通过很短的网络门路就能达到网站(其实这个过程运营商的抉择也有影响)。 网站当一个申请达到网站服务器,服务器便开始解决申请,个别会有专门解决业务申请的一个业务层,有的体现为rpc协定的微服务,有的体现为简略的一个代码分层。最终申请的数据会通过查询数据库来返回。其实这个过程和车站购票流程一样,每个窗口的解决能力是无限的,对应到服务器解决能力。因为这个起因,所以诞生了负载平衡的策略,核心思想就是:分。一台服务器不够,那就两台,三台,四台..... 直到并发的所有申请的响应工夫都在可控范畴之内。 数据库的状况相似,一个数据库扛不住压力,就加到N个数据库扩散压力。一个表扛不住压力,就把这个表拆离开,拆分成多个表,甚至拆分到多个不同服务器数据库,这就是咱们罕用的拆表策略。有的时候在同一个数据库中进行表拆分,性能的晋升并非最大化,因为一台服务器的磁盘IO是有下限的,就算拆成100个表,还是在同一个物理磁盘上,当然这样可缓解锁单表的状况。 当初有很多的场景采纳NOsql代替关系型数据库来缩短响应工夫,在失常状况下,因为关系型数据库的自身因素在特定场景下的读写速度比Nosql要慢很多,所以零碎设计初期,能够思考采纳关系型数据库和Nosql混用的计划。 缓存当并发的申请达到肯定水平,瓶颈大部分状况下产生在DB层面,甚至DB无论怎么优化总有下限。为了防止频繁查询数据库产生瓶颈,诞生了缓存。在拜访数据库之前退出了缓存层,当然这里的缓存采纳的计划在数据的响应工夫上要比数据库小很多,比方罕用的redis,Memcache,然而这些第三方的缓存组件还是要走网络,比起过程内的缓存还是要慢的多。 详情请参考以前文章 当初个别风行的设计在网站层和服务层都有缓存策略,只不过缓存的数据和策略有所不同,然而最终目标都是为了放慢申请的响应。当然加了缓存之后,数据的一致性须要认真设计才能够,如果产生数据不统一的状况,程序员可能要背锅了。 缓解数据库压力并不是引入缓存的惟一因素CDN减速一些小厂可能用不到cdn,然而cdn带来的减速还是很主观的。cdn依附部署在各地的边缘服务器,通过核心平台的负载平衡、内容散发、调度等功能模块,使用户就近获取所需内容,升高网络拥塞,进步用户拜访响应速度和命中率。CDN就是把离用户最近的数据返回给用户。 写在最初程序异步化其实并不能缩短响应工夫,然而对进步吞吐量有很大作用。更多精彩文章 分布式大并发系列架构设计系列趣学算法和数据结构系列设计模式系列

September 26, 2020 · 1 min · jiezi

关于高并发:分布式高并发下Actor模型如此优秀

写在开始一般来说有两种策略用来在并发线程中进行通信:共享数据和消息传递。应用共享数据形式的并发编程面临的最大的一个问题就是数据条件竞争。解决各种锁的问题是让人非常头痛的一件事。 传统少数风行的语言并发是基于多线程之间的共享内存,应用同步办法避免写抢夺,Actors应用音讯模型,每个Actor在同一时间解决最多一个音讯,能够发送音讯给其余Actor,保障了独自写准则。从而奇妙防止了多线程写抢夺。和共享数据形式相比,消息传递机制最大的长处就是不会产生数据竞争状态。实现消息传递有两种常见的类型:基于channel(golang为典型代表)的消息传递和基于Actor(erlang为代表)的消息传递。 Actor简介Actor模型(Actor model)首先是由Carl Hewitt在1973定义, 由Erlang OTP 推广,其 消息传递更加合乎面向对象的原始用意。Actor属于并发组件模型,通过组件形式定义并发编程范式的高级阶段,防止使用者间接接触多线程并发或线程池等根底概念。Actor模型=数据+行为+音讯。 Actor模型是一个通用的并发编程模型,而非某个语言或框架所有,简直能够用在任何一门编程语言中,其中最典型的是erlang,在语言层面就提供了Actor模型的反对,杀手锏利用RabbitMQ 就是基于erlang开发的。 更加面向对象Actor相似面向对象编程(OO)中的对象,每个Actor实例封装了本人相干的状态,并且和其余Actor处于物理隔离状态。举个游戏玩家的例子,每个玩家在Actor零碎中是Player 这个Actor的一个实例,每个player都有本人的属性,比方Id,昵称,攻击力等,体现到代码级别其实和咱们OO的代码并无多大区别,在零碎内存级别也是呈现了多个OO的实例 class PlayerActor { public int Id { get; set; } public string Name { get; set; } }无锁在应用Java/C# 等语言进行并发编程时须要特地的关注锁和内存原子性等一系列线程问题,而Actor模型外部的状态由它本人保护即它外部数据只能由它本人批改(通过消息传递来进行状态批改),所以应用Actors模型进行并发编程能够很好地防止这些问题。Actor外部是以单线程的模式来执行的,相似于redis,所以Actor齐全能够实现分布式锁相似的利用。 异步每个Actor都有一个专用的MailBox来接管音讯,这也是Actor实现异步的根底。当一个Actor实例向另外一个Actor发消息的时候,并非间接调用Actor的办法,而是把消息传递到对应的MailBox里,就如同邮递员,并不是把邮件间接送到收信人手里,而是放进每家的邮箱,这样邮递员就能够疾速的进行下一项工作。所以在Actor零碎里,Actor发送一条音讯是十分快的。 这样的设计次要劣势就是解耦了Actor,数万个Actor并发的运行,每个actor都以本人的步调运行,且发送音讯,接管音讯都不会被阻塞。 隔离每个Actor的实例都保护这本人的状态,与其余Actor实例处于物理隔离状态,并非像 多线程+锁 模式那样基于共享数据。Actor通过音讯的模式与其余Actor进行通信,与OO式的消息传递形式不同,Actor之间音讯的传递是真正物理上的消息传递。 天生分布式每个Actor实例的地位通明,无论Actor地址是在本地还是在近程机器上对于代码来说都是一样的。每个Actor的实例十分小,最多几百字节,所以单机几十万的Actor的实例很轻松。如果你写过golang代码,就会发现其实Actor在重量级上很像Goroutine。因为地位透明性,所以Actor零碎能够随便的横向扩大来应答并发,对于调用者来说,调用的Actor的地位就在本地,当然这也得益于Actor零碎弱小的路由零碎。 生命周期每个Actor实例都有本人的生命周期,就像C# java 中的GC机制一样,对于须要淘汰的Actor,零碎会销毁而后开释内存等资源来保证系统的持续性。其实在Actor零碎中,Actor的销毁齐全能够手动干涉,或者做到零碎自动化销毁。 容错说到Actor的容错,不得不说还是挺令人意外的。传统的编程形式都是在未来可能出现异常的中央去捕捉异样来保证系统的稳定性,这就是所谓的进攻式编程。然而进攻式编程也有本人的毛病,相似于事实,进攻的一方永远不能100%的进攻住所有未来可能呈现代码缺点的中央。比方在java代码中很多中央充斥着判断变量是否为nil,这些就属于进攻式编码最典型的案例。然而Actor模型的程序并不进行进攻式编程,而是遵循“任其解体”的哲学,让Actor的管理者们来解决这些解体问题。比方一个Actor解体之后,管理者能够抉择创立新的实例或者记录日志。每个Actor的解体或者异样信息都能够反馈到管理者那里,这就保障了Actor零碎在治理每个Actor实例的灵活性。 劣势天下无完满的语言,框架/模型亦是如此。Actor作为分布式下并发模型的一种,也有其劣势。 因为同一类型的Actor对象是扩散在多个宿主之中,所以取多个Actor的汇合是个软肋。比方在电商零碎中,商品作为一类Actor,查问一个商品的列表在少数状况下通过以下过程:首先依据查问条件筛选出一系列商品id,依据商品id别离取商品Actor列表(很可能会产生一个商品搜寻的服务,无论是用es或者其余搜索引擎)。如果量十分大的话,有产生网络风暴的危险(尽管几率十分小)。在实时性要求不是太高的状况下,其实也能够独立进去商品Actor的列表,利用MQ接管商品信息批改的信号来解决数据一致性的问题。在很多状况下基于Actor模型的分布式系统,缓存很有可能是过程内缓存,也就是说每个Actor其实都在过程内保留了本人的状态信息,业内通常把这种服务成为有状态服务。然而每个Actor又有本人的生命周期,会产生问题吗?呵呵,兴许吧。想想一下,还是拿商品作为例子, 如果环境是非Actor并发模型,商品的缓存能够利用LRU策略来淘汰非沉闷的商品缓存,来保障内存不会应用适量,如果是基于Actor模型的过程内缓存呢,每个actor其实就是缓存自身,就不那么容易利用LRU策略来保障内存使用量了,因为Actor的沉闷状态对于你来说是未知的。分布式事物问题,其实这是所有分布式模型都面临的问题,非因为Actor而存在。还是以商品Actor为例,增加一个商品的时候,商品Actor和统计商品的Actor(很多状况下的确被设计为两类Actor服务)须要保障事物的完整性,数据的一致性。在很多的状况下能够就义实时一致性用最终一致性来保障。每个Actor的mailBox有可能会呈现沉积或者满的状况,当这种状况产生,新音讯的解决形式是被摈弃还是期待呢,所以当设计一个Actor零碎的时候mailBox的设计须要留神。升华一下通过以上介绍,既然Actor对于地位是通明的,任何Actor对于其余Actor就如同在本地一样。基于这个个性咱们能够做很多事件了,以前传统的分布式系统,A服务器如果想和B服务器通信,要么RPC的调用(http调用不太罕用),要么通过MQ零碎。然而在Actor零碎中,服务器之间的通信都变的很优雅了,尽管实质上也属于RPC调用,然而对于编码者来说就如同在调用本地函数一样。其实当初比拟时髦的是Streaming形式。因为Actor零碎的执行模型是单线程,并且异步,所以但凡有资源竞争的相似性能都非常适合Actor模型,比方秒杀流动。基于以上的介绍,Actor模型在设计层面天生就反对了负载平衡,而且对于程度扩容反对的十分好。当然Actor的分布式系统也是须要服务注册核心的。尽管Actor是单线程执行模型,并不意味着每个Actor都须要占用一个线程,其实Actor上执行的工作就像Golang的goroutine一样,齐全能够是一个轻量级的货色,而且一个宿主上所有的Actor能够共享一个线程池,这就保障了在应用起码线程资源的状况下,最大量化业务代码。更多精彩文章 分布式大并发系列架构设计系列趣学算法和数据结构系列设计模式系列

September 22, 2020 · 1 min · jiezi

关于高并发:硬核干货抗住百万高并发的-6-个关键技术

作者:阿凡卢出处:http://www.cnblogs.com/luxiao... 一、什么是高并发 高并发(High Concurrency)是互联网分布式系统架构设计中必须思考的因素之一,它通常是指,通过设计保证系统可能同时并行处理很多申请。 高并发相干罕用的一些指标有响应工夫(Response Time),吞吐量(Throughput),每秒查问率QPS(Query Per Second),每秒事务处理量TPS(Transaction Per Second),并发用户数等。 响应工夫:系统对申请做出响应的工夫。 吞吐量:单位工夫内解决的申请数量。 QPS:每秒响应查问申请数。 TPS:每秒响应事务申请数。 并发用户数:同时承载失常应用零碎性能的用户数量。 二、晋升零碎的并发能力 互联网分布式架构设计,进步零碎并发能力的形式,方法论上次要有两种:垂直扩大(Scale Up)与程度扩大(Scale Out)。 (1)垂直扩大:晋升单机解决能力。垂直扩大的形式又有两种: 1)加强单机硬件性能,例如:减少CPU核数如32核,降级更好的网卡如万兆,降级更好的硬盘如SSD,裁减硬盘容量如2T,裁减零碎内存如128G; 2)晋升单机架构性能,例如:应用Cache来缩小IO次数,应用异步来减少单服务吞吐量,应用无锁数据结构来缩小响应工夫; (2)程度扩大:只有减少服务器数量,就能线性裁减零碎性能。程度扩大对系统架构设计是有要求的,如何在架构各层进行可程度扩大的设计是本文重点探讨的内容。 1、零碎集群化部署+负载平衡 (1)增加负载平衡层,将申请平均打到零碎层。 (2)零碎层采纳集群化多活部署,扛住初步的并发压力。 2、数据库分库分表+读写拆散+分布式数据库 (1)分库分表:程度拆分、垂直拆分(弊病太多如关联查问)。 (2)读写拆散:主库写,从库读(数据同步提早)。 (3)分布式数据库:TiDB(HTAP、兼容MySQL协定、程度扩大、分布式事务) 3、缓存 (1)本地缓存:本地磁盘或内存。 (2)分布式缓存:用缓存集群抗住大量的读申请。 (3)预缓存,多级缓存。 4、消息中间件 (1)零碎解耦,数据同步。 (2)申请异步化解决,实现削峰填谷的成果。 5、利用拆分(微服务) (1)按业务拆分、缩小耦合。 (2)分级部署,扩容缩容。 (3)利用资源隔离。 6、CDN(内容散发网络) (1)尽可能避开互联网上有可能影响数据传输速度和稳定性的瓶颈和环节, 使内容传输的更快更稳固。 (2)CDN可能实时地依据网络流量和各节点的链接,负载情况以及到用户的间隔和响应工夫等综合信息将用户的申请从新导向离用户最近的服务节点上。

September 9, 2020 · 1 min · jiezi

关于高并发:如何模拟超过-5-万的并发用户

作者:blazemeter起源:t.cn/ES7KBkW 步骤1 : 编写你的脚本步骤2 : 应用JMeter进行本地测试步骤3 : BlazeMeter沙箱测试步骤4 : 应用1个控制台和1个引擎来设置每个引擎用户的数量步骤5 : 装置并测试集群步骤6 : 应用 Master / Slave 个性来达成你的最大CC指标本文将从负载测试的角度,形容了做一次晦涩的5万用户并发测试须要做的事件. 你能够在本文的结尾局部看到探讨的记录. 疾速的步骤概要 编写你的脚本应用JMeter进行本地测试BlazeMeter沙箱测试应用一个控制台和一个引擎设置Users-per-Engine的数量设置并测试你的汇合 (1个控制台和10-14 引擎)应用 Master / Slave 个性来达成你的最大CC指标 步骤1 : 编写你的脚本开始之前,请确定从JMeter的Apache社区jmeter.apache.org 取得了最新的版本. 你也会要下载这些附加的插件 ,因为它们能够让你的工作更轻松. 有许多办法能够取得脚本: 应用 BlazeMeter 的 Chrome 扩大 来记录你的计划应用 JMeter HTTP(S) 测试脚本记录器 来设置一个代理,那样你就能够运行你的测试并记录下所有的货色从头开始全副手工构建(可能是性能/QA测试)如果你的脚本是一份记录的后果(像步骤1&2), 请牢记: 你须要扭转诸如Username & Password这样的特定参数,或者你兴许会想要设置一个CSV文件,有了外面的值每个用户就能够是不同的.为了实现诸如“增加到购物车”,“登录”还有其它这样的申请,你兴许要应用正则表达式,JSON门路提取器,XPath提取器,来提取诸如Token字符串,表单构建ID还有其它因素放弃你的脚本参数化,并应用配置元素,诸如默认HTTP申请,来使得在环境之间切换时你的工作更轻松.步骤2 : 应用JMeter进行本地测试在1个线程的1个迭代中应用查看后果树因素,调试样本,虚构样本还有关上的日志查看器(一些JMeter的谬误会在外面报告),来调试你的脚本. 遍历所有的场景(包含True 或者 False的回应) 来确保脚本行为确如预期… 在胜利应用一个线程测试之后——将其进步到10分钟10到20个线程持续测试: 如果你想要每个用户独立——是那样的么?有没有收到谬误?如果你在做一个注册过程,那就看看你的后盾 - 账户是不是照你的模板创立好了? 它们是不是独立的呢?从总结报告中,你能够看到对测试的统计 - 它们有点用么? (均匀响应工夫, 谬误, 每秒命中率)一旦你筹备好了脚本: 通过移除任何调试和虚构样本来清理脚本,并删除你的脚本侦听器如果你应用了侦听器(诸如 "将响应保留到一个文件"),请确保你没有应用任何门路! , 而如果他是一个侦听器或者一个CSV数据集配置——请确保你没有应用你在本地应用的门路 - 而只有文件名(就如同跟你的脚本在同一个文件夹)如果你应用了本人专有的JAR文件,请确保它也被上传了.如果你应用了超过一个线程组(不是默认的那个) - 请确保在将其上传到BlazeMeter之前设置了这个值.步骤3 : BlazeMeter沙箱测试如果那时你的第一个测试——你应该复习一下 这篇 无关如何在BlazeMeter中创立测试的文章. ...

August 28, 2020 · 2 min · jiezi

关于高并发:高并发的应对方案

高并发的应答计划 MQ消息中间件 高并发会用到的基础知识去深刻理解JUC 并多线程并发测试 怎么查看数据库同一时间最大的连贯数量 技术选型 docker装置

August 22, 2020 · 1 min · jiezi

关于高并发:记一次线上商城系统高并发的优化

起源:https://urlify.cn/jyYny2 对于线上零碎调优,它自身是个技术活,不仅须要很强的技术实战能力,很强的问题定位,问题辨认,问题排查能力,还须要很丰盛的调优能力。 本篇文章从实战角度,从问题辨认,问题定位,问题剖析,提出解决方案,施行解决方案,监控调优后的解决方案和调优后的察看等角度来与大家一起交换分享本次线上高并发调优整个闭环过程。 一、我的项目简要状况概述 该我的项目为基于SSM架构的商城类单体架构我的项目,其中有一个秒杀重磅模块,如下为当火线上环境的简要架构部署图,大抵形容一下: (1)我的项目为SSM架构 (2)服务器类别:1台负载平衡服务器(F5),3台使用程序服务器,1台计时器服务器,1台redis服务器,1台图片服服务器和1台基于Pass架构的Mysql主从服务器(微软云) (3)调用逻辑:下图为简要调用逻辑 二、何为单体架构我的项目 从架构倒退角度,软件我的项目经验了如下阶段的倒退: 1.单体架构:可了解为传统的前后端未分离的架构 2.垂直架构:可了解为前后端拆散架构 3.SOA架构:可了解为按服务类别,业务流量,服务间依赖关系等服务化的架构,如以前的单体架构ERP我的项目,划分为订单服务,洽购服务,物料服务和销售服务等 4.微服务:可了解为一个个小型的我的项目,如之前的ERP大型项目,划分为订单服务(订单我的项目),洽购服务(洽购我的项目),物料服务(物料我的项目)和销售服务(销售我的项目),以及服务之间调用 三、本SSM我的项目引发的线上问题 1.当秒杀的时候,cpu暴增 该零碎每天秒杀分为三个工夫端:10点,13点和20点,如下为秒杀的简要页面 图1 图2 图3 2.单台使用服务器cpu 3.单台使用服务器申请数 4.rdis连接数(info clients) 这个未保留截图,记得是600左右 connected_clients:600 5.mysql申请截图 四、排查过程及剖析 (一)排查思路 依据服务部署和我的项目架构,从如下几个方面排查: (1)使用服务器:排查内存,cpu,申请数等; (2)文件图片服务器:排查内存,cpu,申请数等; (3)计时器服务器:排查内存,cpu,申请数等; (4)redis服务器:排查内存,cpu,连接数等; (5)db服务器:排查内存,cpu,连接数等; (二)排查过程 在秒杀后30分钟内, 1.使用程序服务器cpu暴增,内存暴增,造成cpu和内存暴增的根本原因是申请数过高,单台使用服务器达到3000多; 2.redis申请超时 3.jdbc连贯超时 4.通过gc查看,发现24小时内,FullGC产生了152次 5.再看看堆栈,发现有一些线程阻塞和死锁 jstat -l pid,也能够通过VisualVM剖析 6.发现有2000多个线程申请有效资源 (三)造成本次零碎异样次要因素剖析 (1)在秒杀时,申请量过高,导致使用服务器负载过高; (2)redis连接池满,获取不到连贯,connot get a connection from thread pool ...

August 3, 2020 · 1 min · jiezi