互联网发展对计算机及其应用的影响

news/2024/9/22 11:25:35

先来说一个问题,就是zookeeper leader选举问题

  直接说结论,通过逻辑时钟(zxid)来保证事件发生的因果关系,因果最新的节点优先被选为主,其他小弟跟着同步,如果大家因果相同那就用server id决断作为兜底方案。解释下什么逻辑上时钟?通过数值来记录事件的因果关系,比如a去银行取了100块,然后把钱借给b了。这里b得到钱的果就是先于a取钱这个果的,也就是通过因果来界定时间的先后顺序,但是逻辑时钟不保证实际时间的先后顺序存在因果关系,如果需要可能需要向量时钟才能解决。

  知道上面这些后,就可以回答zookeeper的选举过程及原理了,这种解决问题的思路是:在特定的时间里只存在特定的数据版本,或者说通过更细的维度来区分事件发生的先后顺序以此来解决数据冲突所带来的一致性问题,zk更关注的数据的一致性,以及通过减少不一致性(如选举机制)来间接达到服务的高可用性,因为分布式系统里面注定要面对CAP理论里面的Paration网络分区所带来的数据一致性和服务可用性选择的问题。

  类似的原理应用还有原子类里面CAS的ABA问题解决方案,加入版本号来区分数据,只不过它适用的是多线程环境共享数据更新问题,还Mysql里面的MVCC多版本控制,根据各个事物开始时间的节点,在redo log中看到的数据版本不一致,来解决数据可以重复读取问题,能解决部分幻地问题但无法完全解决,会不会幻读取决于当前事物操作的数据是否有早于它的事务也进行了操作,如果是就能看到不算幻读,如果不是就是幻读,注意这里的操作指的是修改,而不是读取,幻读转指对数据的“修改”,于是就出现了锁,这个是多进程或线程间通信绕不开的永恒话题,mysql管它叫next key锁(间隙锁+行锁),这个锁也不是随便加的,而是根据查询数据的范围和查询列的索引情况来综合分析加多大,比如唯一索引a,值为10,20,30,那你现在修改10这条数据,那只会加10的行锁,由于唯一索引不会重复,所以就只加10这条数据,rr级别下读这条10也不会幻读,如果修改的是>20,那为了防止有其他事务对20后的数据改动,会加(20,0)所有的锁,这个是锁与索引的关系。还有Git的版本控制,每次提交都代表了代码库的一个版本。Git通过SHA-1哈希作为每次提交的唯一标识,用户可以基于这些提交点来合并分支、回退错误和理解开发历史,每个提交点都保持了代码在那一刻的完整视图。

  这些都是通过时间或版本来定义先后顺序,以保证事件发生的顺序,在并发环境下保证了事件的顺序就对数据的一致性多了一种保证。

      说到一致性就不得不聊为啥会出现一致性这种问题,那要说到人们为追求性能,在计算机领域做出的很多尝试和应用,但也带来了很多问题,同时为了解决冲突想出了很多办法,在计算机里面,从硬件到操作系统到软件,比如人们为了解决计算机的处理能力,不断的改进cpu的制成工艺,能耗,散热等,当单核cpu到达物理瓶颈时,类似的理论有摩尔定律,每18月cpu性能翻一番,除了工艺改进,还有其他手段比如叠buff一样,加入多核cpu,又为每一核引入超线程技术,从1971年第一颗商用cpu Intel 4004仅有约0.092 MIPS(百万指令每秒)的处理能力,到现在的intel 14900k随便每秒百亿条处理指令的能力,可以说性能的提升在这50多年里提升可以说是指数级别的增长了,cpu上去了,但其他也要跟上,为了解决cpu性能和硬盘间的巨大差距,又引入了内存,是的,你没说错,一开的电脑是没存的,早期的计算机系统主要使用磁带或者卡片等介质来存储程序和数据,而不是像今天的内存那样直接存储在芯片上,当硬件上去了,基于硬件的软件,包括操作系统,应用程序等就需要来适应这种情况,就像经济基础决定上层建筑。

  说到这里就还有个问题就是进程间是如何通信的?使用的IPC机制,目前常用的有System V IPC和POSIX IPC机制,后者对前者进行了改良优化,改良啥了呢,比如支持了队列异步通知,还有支持映射文件或匿名内存到进程的地址空间,这两个太重要了,比如在IO界很有名的异步非堵塞的AIO、还有被kafka用的如火纯青的零拷贝用到的就是mmap,不过它高性能原因还有其他的因素,像数据压缩、批量发送、多队列、顺序写入等等。当然零拷贝有很多种实现方式比如sendfile/spelice/vmsplice等等,有兴趣的同学可以自行去研究,这里就不一一介绍了。接下来我大概说下这两种技术的运行原理。

正常调用linux的read/write操作文件的步骤,里外里倒腾需要4次copy,可以见cpu内核参与程度

,参与过程还不能干啥事,就得整个线程专门干这事。

用mmap零拷贝技术,直接让系统把数据拷贝到物理内存,完了告诉用mmap映射这部分数据到用户进程,用户进程直接

就能操作数据,操作完了由系统负责刷脏页,直接2次搞定,而这copy文件操作cpu初始化个dma(一种硬件功能)让它干这个活

它自个去干其他的,这就是零拷贝,这个零说的就是用户空间级别不存在拷贝数据,用户操作数据就完了,其它刷脏页让系统干,这个

刷脏在分布式系统中间件非常常见,比如mysql的redo log日志,redis的数据备份rdb和aof。

 

 

还有一个就是AIO模型用的epoll,常见的IO模型有BIO/NIO/AIO,堵塞/非堵塞/异步IO,这里碍于篇幅就不说概念了,直接看图

这是BIO的模式,使用IO多路复用,内核出一个线程,为了找出哪些FD状态发生变化,一直遍历所有FD(文件描述符),哪怕只有几个FD

变化了,也会返回所有FD列表,让用户线程去遍历这100W条数据,线程调用系统内核api就用的select,这api特点是一次传所有要监听的FD,而且每次调用

select一次就要传所有的FD,返回也是返回所有FD,所以无论用户线程还是内核两头不吃好,数据量小还好,一旦大起来,性能将严重影响。

 

而AIO的epoll就不同了,无论从最开始的用户调用系统内核的epoll,每个线程可以只注册自己感兴趣的事件,而且只要线程后续不去修改

这些事件,后面就不用再注册了,每次来了事件都会回调通知线程,做到了一次注册,多次使用,在内核这边也只遍历epoll里面特定的事件

不是去遍历所有,返回时也只返回之前注册过的FD事件,性能与前面的select模式完全不一样,数据越大这个差距越明显。

 

    ok说完了IPC机制的改进点,我们再接着说下进程间这些通信的方式,队列,内存共享、信号量。

在unix系统里面最开始用的就是管道进行通信,同时它也是进程间特有的通信方式,使用场景单一,传输数据量有限,流向单一,通常用于父子进程通信比如linux系统一启动会创建一个主进程,后续所有进程都是其子进程,还有redis当中做rdb备份用的bgsave指令,会fork一个子进程进行通信,用的就是管道,还有网络socket套接字,用的也是管道,为了实现双向通信,会建立两个管道一个request,一个response,从某种程度讲更像一个简单的捆绑式的生存和消费者模型;

而队列更像是改良版的管道,无形一对一和单向也不需要绑定生产和消费者,可以同时面对多个进程进行数据通信共享,但它强调数据的顺序性FIFO,同时进程要拿到数据需要从队列里调用系统内核api copy到自己的进程空间,这也会影响共享的效率。内存共享则是把管道和队列的一些限制都放开,直接就共享一大片内存段,这里用户进程获取共享内存的数据有两种方式,一种是直接复制一份到自己的虚拟空间也就是正常调用read/write APi接口,而另一种是用mmap做映射也是上面说的零拷贝,用户进程不用多绕一层系统内核的copy直接就操作数据;

而信号量我认为它是一种对内存共享并发读的控制,限制共享的范围或协调多个进程的工作,它本质是基于cpu硬件级别的原子指令操作,可以指定资源的数量来控制来访问的进程数量,而锁本质是基于cpu硬件级别的内存屏蔽指令实现的,个人认为它和信号量区别就是它更强调对资源独占性,通过独占性在某一个时间精度内与其它进程区隔开来达到多线程间在逻辑时间上的先后顺序,所以信号量和锁是同步机制,而队列和内存共享是进程共享方式,管道也是一种共享方式。

 

  随着时代的发展互联网也在发展,各种跨国宽带,各个国家都加入WTO,越来越多的人开始使用互联网,尤其是智能手机带动的移动互联网,带起了一大波应用,人们对应用性能的要求越来越高,一个应用几千万甚至上亿的人在使用,单节点的问题也越发明显,比如受限于计算机硬件发展水平,性能已经成为瓶颈,人们日益增长的需求无法简单的通过堆叠硬件来解决,同时应用功能也越做越大,所有功能都耦合在一起,开发和运维成本直线上升,一个小发生问题,整个系统宕机,严重影响业务连续性和可用性,急需一种扩展性强,能单节点性能问题,把耦合的应用解耦的方案。

  这个方案就是分布式系统,把一个大应用拆分成多个小应用,分开部署,这种从空间维度把整体把应用和数据都被拆分,要扩容非常简单加节点就可以,可伸缩性高,也容易维护,但数据被分成多个节点了,而这些节点间数据的同步通过套接字来进行传输,一知道传输就需要时间,前面说了一个数据版本的确定需要通过一个时间范围来界定,当节点间时间相差过大会导致各节点间数据出现多版本可能性越高,到不是怕多版本,怕的是为了解决这些数据在各节点不一致的问题,需要进行一致性和可用性的割舍。

  说到这就不得不说CAP里面,Consistency/Availability/Partition tolerance,在分布式系统中,分区容忍性通常是必需的,因为网络故障是不可避免的。这就导致系统设计者需要在一致性和可用性之间做出选择,这也和物理学中,熵是系统混乱程度的量度,系统总是倾向于状态更加混乱(熵增)。在分布式系统中,数据和服务的分散(分区)增加了系统的复杂性和不确定性(类似于熵增),而系统设计的目标之一是通过增加冗余、同步等手段,尽量降低这种“熵增”,维持系统的一致性和稳定性。冗余可以降低因单点故障所导致的不确定性和不确定性,间接提高系统可用性,同步则是保持各副本间的一种手段,常见的分布式系统都有容易,比如kafka多副本,rocketmq的多个broker,mysql集群的主从,redis cluster主从等等,为的就是通过冗余来提高系统的鲁棒性、稳定性和容错能力。

  今天先写到这里,后面有机会再写写分布式系统中间件常见的问题以及解决方案,以及设计一个好的中间件需要具备哪些条件,业界一些通用套路又是啥,拜拜!

  

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.ryyt.cn/news/31439.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

第十一周实验

Pixso特点实时协作——让所有人聚焦同一个目标 当面对一个复杂的设计项目时,通过链接邀请团队成员,进行多人云端协作设计,实时同步字号、边框、颜色等各种细节。 智能UI设计工具——快速上手专业技能 传统产品,往往要多个工具协作才能预期效果。而Pixso自带组件变体、自动布…

m5stack

m5stack cardcomputer+m5stack c3 首先,感谢得捷社区,本次参与奖我选取的是m5stack cardcomputer+m5stack c3,m5stack被乐鑫已经收购了,他们的产品我觉得精致小巧,正好m5stack cardcomputer他拥有usb有线连接和蓝牙连接的键盘功能,对于开发板的一些输入指令什么可以就使用…

性能测试工具--如何有效度量前端性能

转自:https://testerhome.com/topics/35529 目标:从用户角度明确前端 Web、H5 性能测试需要重点关注的内容; 根据关注内容明确性能测试过程中的性能评判指标和建议的阈值范围; 整理性能测试过程中各性能评价指标的收集方法; 明确性能测试完毕后的测试结果展现形式; 本文来…

基于MATLAB手搓人工神经网络

神经网络 基本概念 ​ 神经网络,模拟生物神经网络,节点称为神经元。神经网络分层命名,直接接收输入数据的是输入层,输出结果的是输出层,输入层与输出层之间的是隐藏层。 ​ 前向传播:数据从输入层开始,逐层向前传播计算,直到输出层得到输出结果。 ​ 反向传播:将输出层…

drawcall优化 - 无限滚动容器

这是一个前端项目常见的一个问题dc优化。比如一个复杂的背包容器500个元素,如果使用粗暴的实例化500个元素进去,最终的dc无疑会是灾难的。在内存管理和性能角度上讲也是铺张浪费的。 看见效果如下 dc 1091 但实际上500个元素itemCell,在一个屏幕视界内能看到和交互的也就6~…

java所有集合的相互关系是什么

Java集合框架是一个设计精良、功能强大的工具集,用于存储和操作对象集合。它大致分为以下几类,并且各类之间存在一定的层级关系和功能差异:### 顶级接口(根接口)1. **Collection**: 是最基础的集合接口,所有集合类都直接或间接实现了这个接口。它定义了基本的集合操作,如…

mysql 锁

1,介绍锁是计算机协调多个进程或线程并发访问某一资源的机制。在数据库中,除传统的计算资源(CPU、RAM、I/O)的争用以外,数据也是一种供许多用户共享的资源。如何保证数据并发访问的一致性、有效性是所有数据库必须解决的一个问题,锁冲突也是影响数据库并发访问性能的一个…

Windows系统安装Jmeter教程

1、进入官网https://jmeter.apache.org/download_jmeter.cgi 选择与Jdk适配的版本下载:2、解压压缩包3、配置环境变量 进入到系统配置环境变量的界面:在下方的系统变量那里,新建变量:变量名为:JMETER_HOME 变量地址:Jmeter的安装路径 如图所示:4、运行JMETER 在JMeter的…