最新要闻
- 今日聚焦!锐龙7000无缘单条48GB DDR5内存!点亮后却无法启动
- 每日热门:卖断货!湖北最强汽车补贴火了 有人“从业十年没见过”
- 每日热门:4.5级后广东河源再次发生3.4级地震:官方科普地震来了怎么办
- 全球观察:全年出货量仅2.6亿 PC电脑透心凉:复苏要等Win12
- 全球通讯!ChatGPT版佛祖爆火出圈:施主、说出你的烦恼
- 全球速看:平板电脑怎么连接wifi
- 8元保号没了!中国移动广东出手:最便宜4G套餐撤掉 同步下架5G全家享套餐
- 319元 小米米家智能直流变频塔扇2上市:吹一夏天电费仅0.65元
- 快看点丨燃油、纯电、混动:买轻卡你会选择谁?
- 柳宗元最著名的十首诗是什么?柳宗元在柳州的故事
- 天天通讯!基德谈欧文末节独砍17分:这就是他 他喜欢帮助他的球队赢球
- 韩国西江大学留学条件和费用是什么?韩国西江大学怎么样?
- 代课老师的养老保险什么时候启动?代课教师养老保险政策有哪些?
- 焦点热门:可抵抖音干半年!TVB淘宝直播间首播销售额达2350万
- 全球看点:一年脱轨1000次!美国俄亥俄州再发生铁路事故 卡车撞上火车
- 满满正能量!小学生拾得价值16万黄金后续:物归原主、获助学礼包
手机
iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?
警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案
- iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?
- 警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案
- 男子被关545天申国赔:获赔18万多 驳回精神抚慰金
- 3天内26名本土感染者,辽宁确诊人数已超安徽
- 广西柳州一男子因纠纷杀害三人后自首
- 洱海坠机4名机组人员被批准为烈士 数千干部群众悼念
家电
环球头条:Paxos算法理解与java实现
Paxos在分布式环境下应用非常广泛,是一致性算法里面优越的代表。Google的粗粒度锁服务Chubby的设计开发者Burrows曾经说过:所有一致性协议本质上要么是Paxos要么是其变体。
一、Paxos概念
Paxos算法是基于消息传递且具有高度容错特性的一致性算法,是目前公认的解决分布式一致性问题最有效的算法之一。
(资料图片)
Paxos算法是Lamport宗师提出的一种基于消息传递的分布式一致性算法,使其获得2013年图灵奖。
自Paxos问世以来就持续垄断了分布式一致性算法,Paxos这个名词几乎等同于分布式一致性。
Google的很多大型分布式系统都采用了Paxos算法来解决分布式一致性问题,如Chubby、Megastore以及Spanner等。开源的ZooKeeper,以及MySQL 5.7推出的用来取代传统的主从复制的MySQL Group Replication等纷纷采用Paxos算法解决分布式一致性问题。
但是它也有两个明显的缺点:
- 难以理解
- 在工程是实现上比较复杂。
二、问题产生的背景
1、系统异常情况
在常见的分布式系统中,总会发生诸如机器宕机或网络异常(包括消息的延迟、丢失、重复、乱序,还有网络分区)等情况。
Paxos算法需要解决的问题就是如何在一个可能发生上述异常的分布式系统中,快速且正确地在集群内部对某个数据的值达成一致,并且保证不论发生以上任何异常,都不会破坏整个系统的一致性。
这里某个数据的值并不只是狭义上的某个数,它可以是一条日志,也可以是一条命令(command)。根据应用场景不同,某个数据的值有不同的含义。
2、相关概念
在Paxos算法中,有三种角色:
- Proposer (提案者)
- Acceptor (人大代表)
- Learners (广大群众)
需要注意的是,在具体的算法实现过程中,并不是一个进程只能担任其中一种角色,它有可能会同时充当多个。比如一个进程既是Proposer又是Acceptor还是Learner。
还有一个很重要的概念叫提案(Proposal)。最终要达成一致的value就在提案里。
这个提案包括什么呢?是仅仅包括一个信息数值吗? 目前咱们先认为仅仅是一个普普通通的value。
Paxos算法过程和我国的立法过程是极其相似的(法律案的提出、法律案的审议、法律案的表决、法律的公布四个阶段),所谓的提案就是新颁布法律。
Proposer (提案者)可以提出(propose)提案;Accoptor可以接受(accept)提案;如果某个提案被选定(chosen),那么该提案里的value就被选定了。
回到刚刚说的『对某个数据的值达成一致』,指的是Proposer、Acceptor、Learner都认为同一个value被选定(chosen)。那么,Proposer、Acceptor、Learner分别在什么情况下才能认为某个value被选定呢?
- Proposer:只要Proposer发的提案被Acceptor接受(刚开始先认为只需要一个Acceptor接受即可,在推导过程中会发现需要半数以上的Acceptor同意才行),Proposer就认为该提案里的value被选定了。
- Acceptor:只要Acceptor接受了某个提案,Acceptor就认为该提案里的value被选定了。
- Learner:作为一个学习者,Acceptor告诉Learner哪个value被选定,Learner就认为那个value被选定。
3、问题产生
假设有一组可以提出(propose)value的进程集合(提案者团队),一个一致性算法需要保证提出的这么多value中,仅仅只有一个相同的value被选定(chosen)。也就是说要么没有value被提出,只要提出了value并且被选定,那么大家最终学习到的value必须是一致的。对于一致性算法,安全性(safaty)要求如下:
- 只有被提出的value才能被选定。
- 只有一个value被选定。
- 如果某个进程认为某个value被选定了,那么这个value必须是真的被选定的那个。
“Paxos的目标:保证最终有一个value会被选定,当value被选定后,进程最终也能获取到被选定的value。”
如果假设不同角色之间可以通过发送消息来进行通信,那么:
- 每个角色以各自任意的速度进行通信执行,在这个过程中可能会因为各种原因出错而导致执行停止或重启。当一个value被选定之后,因为故障原因才恢复正常的角色因为失去了某些重要的信息,导致它们无法确定被选定的值。
- 消息在传递过程中可能出现任意时长的延迟,可能会重复,也可能丢失。但是消息不会被损坏,即消息内容不会被篡改(拜占庭将军问题)。
以上都是可能会遇到的问题,要怎么解决???
二、推导过程
1、最简单的方案——只有一个Acceptor
假设只有一个Acceptor(可以有多个Proposer),只要Acceptor接受它收到的第一个提案,则该提案被选定,该提案里的value就是被选定的value。这样就保证只有一个value会被选定。
但是,如果这个唯一的Acceptor宕机了,那么整个系统就无法工作了!
因此,一个Acceptor是不可行的,必须要有多个Acceptor!
如下图 只有一全Acceptor
2、多个Acceptor
当有多个Acceptor的时候,如何保证在多个Proposer和多个Acceptor的情况下选定一个value呢?
大家可以自己先进行思考。
首先,我们的最终目标是无论有多少Proposer提出提案,有且仅有一个value被选定。
那么,我们可以先定义一个约束:
“P1:一个Acceptor必须接受它收到的第一个提案。”
但是,这样又会出现其它的问题:如果每个Proposer所提出的提案value是不同的,并且将提案发送给不同的Acceptor。根据P1约束,每个Acceptor都接受它收到的第一个提案,就会出现不同value被选定的情况,出现了不一致。
刚刚是因为『一个提案只要被一个Acceptor接受,则该提案的value就被选定了』才导致了出现上面不一致的问题。因此,我们需要加一个规定:
“规定:一个提案被选定需要被半数以上的Acceptor接受”
一个提案被半数以上接受,说明『一个Acceptor必须能够接受不止一个提案!』,不然可能导致最终没有value被选定。比如上图的情况。v1、v2、v3都没有被选定,因为它们都只被一个Acceptor的接受,并没有被超过半数以上的Acceptor接受。
最开始将【提案= value】已经无法满足现在的需求,因为当一个Proposer发送多个提案到一个Acceptor的时候,需要使用一个编号来区分被提出的顺序。现在【提案=提案编号+value】。
虽然允许多个提案被选定,但必须保证所有被选定的提案都具有相同的value值。否则又会出现不一致。
“P2:如果某个value为v的提案被选定了,那么每个编号更高的被选定提案的value必须也是v。”
一个提案只有被Acceptor接受才可能被选定,因此我们可以把P2约束改写成对Acceptor接受的提案的约束P2a。
“P2a:如果某个value为v的提案被选定了,那么每个编号更高的被Acceptor接受的提案的value必须也是v。”
只要满足了P2a,就能满足P2。
但是,考虑如下的情况:以立法过程为背景,假设总的有5个人大代表(Acceptor)。
人民法院(Proposer2)提出[M1,V1]的提案,人大代表2-5号(半数以上)均接受了该提案,于是对于人大代表2-5号和人民法院来讲,它们都认为V1提案是被选定的。此时,人大代表1在办完其它事务之后也参与到其中(之前人大代表1没有收到过任何提案),此时最高人民检察院(另一个提案者Proposer1)向人大代表1发送了[M2,V2]的提案(V2≠V1且M2>M1),对于人大代表1来讲,这是它收到的第一个提案。根据P1(一个Acceptor必须接受它收到的第一个提案。),人大代表1必须接受该提案!同时人大代表1认为V2被选定。这就出现了两个问题:
- 人大代表1认为V2被选定,人大代表2-5和人民法院认为V1被选定。出现了不一致。
- V1被选定了,但是编号更高的被人大代表1接受的提案[M2,V2]的value为V2,且V2≠V1。这就跟P2a(如果某个value为v的提案被选定了,那么每个编号更高的被Acceptor接受的提案的value必须也是v)矛盾了。
所以,我们要对P2a约束进行加强!
P2a是对Acceptor接受的提案约束,但其实提案是Proposer提出来的,所有我们可以对Proposer提出的提案进行约束。得到P2b:
“P2b:如果某个value为v的提案被选定了,那么之后任何Proposer提出的编号更高的提案的value必须也是v。”
那么,如何确保在某个value为v的提案被选定后,Proposer提出的编号更高的提案的value都是v呢?
只要满足P2c即可:
“P2c:对于任意的N和V,如果提案[N, V]被提出,那么存在一个半数以上的Acceptor组成的集合S,满足以下两个条件中的任意一个:
- S中每个Acceptor都没有接受过编号小于N的提案。
- S中Acceptor接受过的最大编号的提案的value为V。”
3、Proposer生成提案
为了满足P2b,这里有个比较重要的思想:Proposer生成提案之前,应该先去『学习』已经被选定或者可能被选定的value,然后以该value作为自己提出的提案的value。如果没有value被选定,Proposer才可以自己决定value的值。这样才能达成一致。这个学习的阶段是通过一个『Prepare请求』实现的。
于是我们得到了如下的提案生成算法:
- Proposer选择一个新的提案编号N,然后向某个Acceptor集合(半数以上)发送请求,要求该集合中的每个Acceptor做出如下响应(response)。
(a) 向Proposer承诺保证不再接受任何编号小于N的提案。
(b) 如果Acceptor已经接受过提案,那么就向Proposer响应已经接受过的编号小于N的最大编号的提案。
我们将该请求称为编号为N的Prepare请求。
- 如果Proposer收到了半数以上的Acceptor的响应,那么它就可以生成编号为N,Value为V的提案[N,V]。
- 这里的V是所有的响应中编号最大的提案的Value。
- 如果所有的响应中都没有提案,那 么此时V就可以由Proposer自己选择(一般为当前提案)。
- 生成提案后,Proposer将该提案发送给半数以上的Acceptor集合,并期望这些Acceptor能接受该提案。我们称该请求为Accept请求。(注意:此时接受Accept请求的Acceptor集合不一定是之前响应Prepare请求的Acceptor集合)
4、Acceptor接受提案
Acceptor可以忽略任何请求(包括Prepare请求和Accept请求)而不用担心破坏算法的安全性。因此,我们这里要讨论的是什么时候Acceptor可以响应一个请求。
我们对Acceptor接受提案给出如下约束:
“P1a:一个Acceptor只要尚未响应过任何编号大于N的Prepare请求,那么他就可以接受这个编号为N的提案。”
如果Acceptor收到一个编号为N的Prepare请求,在此之前它已经响应过编号大于N的Prepare请求。根据P1a,该Acceptor不可能接受编号为N的提案。因此,该Acceptor可以忽略编号为N的Prepare请求。当然,也可以回复一个error,让Proposer尽早知道自己的提案不会被接受。
因此,一个Acceptor只需记住:
1. 已接受的编号最大的提案
2. 已响应的请求的最大编号。
三、Paxos算法描述
经过上面的推导,我们总结下Paxos算法的流程。
Paxos算法分为两个阶段。具体如下:
1、阶段一:
- Proposer选择一个提案编号N,然后向半数以上的Acceptor发送编号为N的Prepare请求。
- 如果一个Acceptor收到一个编号为N的Prepare请求,且N大于该Acceptor已经响应过的所有Prepare请求的编号,那么它就会将它已经接受过的编号最大的提案(如果有的话)作为响应反馈给Proposer,同时该Acceptor承诺不再接受任何编号小于N的提案。
2、阶段二:
- 如果Proposer收到半数以上Acceptor对其发出的编号为N的Prepare请求的响应,那么它就会发送一个针对[N,V]提案的Accept请求给半数以上的Acceptor(和之前的Acceptor不一定相同)。注意:V就是收到的响应中编号最大的提案的value,如果响应中不包含任何提案,那么V就由Proposer自己决定。
- 如果Acceptor收到一个针对编号为N的提案的Accept请求,只要该Acceptor没有对编号大于N的Prepare请求做出过响应,它就接受该提案。
3、算法实现流程
(1)提议者发出提案,发起一次投票,发现者接收到投票请求,将提案转发给参与者; (2)参与者接收到投票请求后,会对提案进行投票,投票正确时发送投票确认消息; (3)发起者收到参与者发回的投票确认消息,如果收到的投票确认消息超过半数,则发起者发出accept消息,将提案接受; (4)参与者接收到accept消息后,如果投票正确,则发送accept确认消息; (5)发起者收到accept确认消息后,如果收到的accept确认消息超过半数,则发起者发出commit消息,将提案接受,并执行操作; (6)参与者接收到commit消息后,如果投票正确,则发送commit确认消息; (7)发起者收到commit确认消息后,如果收到的commit确认消息超过半数,则发起者发出ack消息,将提案接受,并将操作结果返回给发起者; (8)参与者接收到ack消息后,如果投票正确,则发送ack确认消息; (9)发起者收到ack确认消息后,如果收到的ack确认消息超过半数,则发起者发出完成消息,将提案接受,并将操作结果返回给发起者,完成Paxos算法。
四、java代码实现
注:代码不完整,不可用于实际项目,仅是对算法梳理流程,以便有于大家易于理解算法思想,后续抽空写一个完全的代码项目工程。
查看代码
import java.util.*;public class Paxos {// proposerpublic static class Proposer {private int id;private int value;private int maxValue;private int vNumber;private int aNumber;public Proposer(int id, int value, int maxValue) {this.id = id;this.value = value;this.maxValue = maxValue;this.vNumber = 0;this.aNumber = 0;}// 第一阶段:建议阶段public void prepare() {System.out.println("Proposer " + id + ": Suggesting...");vNumber = maxValue + 1;System.out.println("Proposer " + id + ": Suggested VNumber: " + vNumber);}// 第二阶段:接受阶段public void accept() {System.out.println("Proposer " + id + ": Accepting...");aNumber = vNumber;System.out.println("Proposer " + id + ": Accepted ANumber: " + aNumber);}// 第三阶段:承诺阶段public void commit() {System.out.println("Proposer " + id + ": Committing...");System.out.println("Proposer " + id + ": Committed Value: " + value);}public int getId() {return id;}public int getValue() {return value;}public int getVNumber() {return vNumber;}public int getANumber() {return aNumber;}}// acceptorpublic static class Acceptor {private int id;private int vNumber;private int aNumber;private int value;public Acceptor(int id) {this.id = id;this.vNumber = 0;this.aNumber = 0;this.value = 0;}// 接受来自proposer的prepare消息public void receivePrepare(int vNumber) {System.out.println("Acceptor " + id + ": Receiving prepare message...");if (vNumber > this.vNumber) {this.vNumber = vNumber;System.out.println("Acceptor " + id + ": Accepted VNumber: " + vNumber);} else {System.out.println("Acceptor " + id + ": Rejected VNumber: " + vNumber);}}// 接受来自proposer的accept消息public void receiveAccept(int aNumber, int value) {System.out.println("Acceptor " + id + ": Receiving accept message...");if (aNumber >= this.vNumber) {this.aNumber = aNumber;this.value = value;System.out.println("Acceptor " + id + ": Accepted ANumber: " + aNumber);System.out.println("Acceptor " + id + ": Accepted Value: " + value);} else {System.out.println("Acceptor " + id + ": Rejected ANumber: " + aNumber);}}public int getId() {return id;}public int getVNumber() {return vNumber;}public int getANumber() {return aNumber;}public int getValue() {return value;}}// learnerpublic static class Learner {private int id;private int value;public Learner(int id) {this.id = id;this.value = 0;}public void learn(int value) {this.value = value;System.out.println("Learner " + id + ": Learnt Value: " + value);}public int getId() {return id;}public int getValue() {return value;}}// 测试用例public static void testPaxos() {// 创建proposerProposer proposer = new Proposer(1, 100, 200);// 创建acceptorList acceptors = new ArrayList<>();acceptors.add(new Acceptor(1));acceptors.add(new Acceptor(2));acceptors.add(new Acceptor(3));// 创建learnerLearner learner = new Learner(1);// 开始协商proposer.prepare();for (Acceptor acceptor : acceptors) {acceptor.receivePrepare(proposer.getVNumber());}proposer.accept();for (Acceptor acceptor : acceptors) {acceptor.receiveAccept(proposer.getANumber(), proposer.getValue());}proposer.commit();learner.learn(proposer.getValue());// 输出结果System.out.println("Learner 1: Final Value: " + learner.getValue());}public static void main(String[] args) {testPaxos();}}
五、存在问题讨论
1、Learner学习者是如何被选定的value?
Learner学习(获取)被选定的value有如下三种方案:
方案一
Acceptor接受到一个提案,就将该提案发送给所有Learners.
- 优点:Learner能够快速获取被选定的value
- 缺点:通信次数为M*N(M为提案数,N为Learner数)
方案二
Acceptor接受一个提案,就将提案发送给主Learner,主Learner再通知其它Learner
- 优点:通信次数减少(M+N-1)(M为提案数,N为Learner数,M个提案发送给主Learner,然后主Learner通知N-1个Learner)
- 缺点:单点故障问题(主Learner可能出现故障)
方案三
Acceptor接受一个提案,就将提案发送给Learner团,Learner团再通知其它Learner
- 优点:解决了方案二单点故障问题,可靠性好
- 缺点:实现复杂,网络通信复杂度高
2、如何保证Paxos算法的活性?
通过选取主Proposer,就可以保证Paxos算法的活性。通过选取主Proposer,并规定只有主Proposer才能提出议案。这样一来只要主Proposer和过半的Acceptor能够正常进行网络通信,那么但凡主Proposer提出一个编号更高的提案,该提案终将会被批准,这样通过选择一个主Proposer,整套Paxos算法就能够保持活性。至此,我们得到一个既能保证安全性,又能保证活性的分布式一致性算法——Paxos算法。
插图说明。。。
六、总结
通过对Paxos算法解读分析、它的特性以及算法的具体推导过程做了详细的阐述。Paxos算法是现在很多一致性算法的变体,在互联网时代分布式环境应用非常广泛,非常值得我们学习。
关键词:
热推荐:前端设计模式——观察者模式
热消息:代码审计之旅之百家CMS
环球头条:Paxos算法理解与java实现
环球消息!5、Redis慢日志和key有效期
今日聚焦!锐龙7000无缘单条48GB DDR5内存!点亮后却无法启动
每日热门:卖断货!湖北最强汽车补贴火了 有人“从业十年没见过”
每日热门:4.5级后广东河源再次发生3.4级地震:官方科普地震来了怎么办
全球观察:全年出货量仅2.6亿 PC电脑透心凉:复苏要等Win12
全球通讯!ChatGPT版佛祖爆火出圈:施主、说出你的烦恼
GO语言学习笔记-数据篇 Study for Go ! Chapter four - Data
全球速读:Go 数据结构
精彩看点:如何搞定MySQL锁(全局锁、表级锁、行级锁)?这篇文章告诉你答案!太TMD详细了!!!
最新资讯:vue组件更新引起组件更新的原因,如何引发组件的更新
播报:【JavaScript UI库和框架】上海道宁与Webix为您提供用于跨平台Web应用程序开发的JS框架及UI小部件
全球速看:平板电脑怎么连接wifi
8元保号没了!中国移动广东出手:最便宜4G套餐撤掉 同步下架5G全家享套餐
319元 小米米家智能直流变频塔扇2上市:吹一夏天电费仅0.65元
快看点丨燃油、纯电、混动:买轻卡你会选择谁?
柳宗元最著名的十首诗是什么?柳宗元在柳州的故事
天天通讯!基德谈欧文末节独砍17分:这就是他 他喜欢帮助他的球队赢球
天天微速讯:3张思维导图读懂 《钢铁是怎样炼成的》
VUE定时器任务(每天12点执行)
信息:mysql invalid conn排查
全球观速讯丨CNStack 多集群服务:基于 OCM 打造完善的集群管理能力
即时看!关于docker中-容器的管理操作-删除
韩国西江大学留学条件和费用是什么?韩国西江大学怎么样?
代课老师的养老保险什么时候启动?代课教师养老保险政策有哪些?
焦点热门:可抵抖音干半年!TVB淘宝直播间首播销售额达2350万
全球看点:一年脱轨1000次!美国俄亥俄州再发生铁路事故 卡车撞上火车
满满正能量!小学生拾得价值16万黄金后续:物归原主、获助学礼包
向残疾熊猫福菀泼水3游客身份未确定:初步断定为3女娃
一键开盖 耐热抗摔:哈尔斯Tritan材质单手开盖水杯15.9元发车
光棍节的由来和含义是什么?光棍节活动策划书
办公室副主任是什么级别?办公室副主任年度述职报告
手机厂商钟情的黄色配色 原来诺基亚十年前就有了
大小仅3.7GB:大佬基于Win10魔改经典WinXP系统
每日快报!为眼睛降低ISO感光度!万新偏光太阳镜大促:39.4到手 原价139元
焦点速递!跑车底盘+大电池!开了两天哪吒S 想把我的油车卖了
行走的27寸超大平板!小度推出添添闺蜜机 首发4999元
win7电脑怎么开启telnet命令?telnet命令的作用是什么?
暖暖环游世界怎么看收集度?暖暖环游世界兑换码2023
Win10系统怎么安装杜比音效驱动?杜比音效和普通音效有什么区别
中兴天机7哪个版本音质最好?中兴天机7手机参数
iphone怎么设置勿扰模式?iphone灵动岛怎么养宠物?
Liunx Vim常用命令
天天看点:C++笔记--控制语句
Windows 11提示“无法枚举容器中的对象。”
环球速读:A股异动 | 上海电影涨7% 拟收购上影元文化51%股权 拓展IP运营业务
视讯!国产CPU龙芯3A6000上半年流片明年出货 已评估7nm工艺
泰国电动车市场被国产车包了!2月销量哪吒、比亚迪双霸榜
5499元 华硕无畏15i轻薄本开卖:12核i5、2.8K 120Hz OLED好屏
不得杀疯了?曝比亚迪海鸥4月上市:仅6.58万起
世界快消息!苹果等级森严:标准版iPhone 15将不支持全天候显示功能
【世界速看料】无穷大符号
Spring Boot + MybatisX = 王炸!!
每日消息!(数据库系统概论|王珊)第十章数据库恢复技术:习题
焦点速读:前端设计模式——发布订阅模式
微资讯!《寂静岭2:重制版》新版护士形象曝光!身材依旧火辣
今热点:苹果、谷歌抢市场 Windows份额创美国史低:绝对垄断没了
NVIDIA紧急推送531.26修复补丁:解决N卡CPU占用异常问题
2月销量3863台 长安马自达CX-50本月下线:还能救市吗?
24岁高颜值女孩回应大学毕业养猪:父母支持 年薪10万
世界热讯:一次惨痛教训让我写了个Windows定期备份文件脚本
天天微速讯:模块简介、模块的两种导入语句、导入文件的补充、判断文件类型、模块的查找顺序
全球热点!自动化离线交付在云原生的应用和思考
今日要闻!Python常见面试题009. 元组和列表有什么区别
每日速递:地图标准先行 自动驾驶识途
大疆发布Ronin 4D Flex分体拓展系统:手持重量仅1/3 实现运镜自由
环球速看:你真离不开苹果!全球最畅销手机Top 10:iPhone无敌 安卓阵营被摩擦
全球热讯:落后中国几十年!H3运载火箭发射失败自毁 日本首相社交平台谢罪
环球新消息丨妇女节快乐!《中国妇女报》:妇女节不是什么女神节 不放假有加班费吗?
当前消息!12万就有自动上电 埃安AION Y Younger上市:续航430km
世界看热讯:江苏一男子醉驾用脚刹车 竟然“刹”住了
世界速读:苹果推出黄色款iPhone 14:对比小米13飓风黄 哪个好看?
15万特斯拉要来了!马斯克自曝新车:成本降50% 自动驾驶
成人教育大专
焦点短讯!读Java性能权威指南(第2版)笔记10_原生内存
我国多地取消中考男女生长跑 800米对健康不利:教育部喊话不得停止体育教学
强烈建议收藏,python库大全
js数据类型判断、unll和undefined
全球通讯!女足来了!FIFA23将加入15个女足联赛
李杰:一加最擅长做旗舰 同等价格段我们能提供最优秀产品
景区回应瀑布源头是水管放水:看破不说破 不要在意细节
全球速递!《阿凡达2》宣布3月28日上线数字平台:收录3小时额外内容
在网上口述一生:86岁老奶奶成了年轻人的“偶像”
世界速读:埃及出土古罗马时期笑脸迷你版狮身人面像:脸颊还有酒窝
“90后”小伙画下长江泸州段!目标是画遍中国
全球热推荐:那年夏天 电影
第126篇: 异步函数(async和await)
环球速讯:思科防火墙5506-x基础
男子疑因抽烟错过高铁不停拍车门 网友:怨不得别人
热点!40岁985硕士求职被怼不招大妈 求职者:感觉是歧视
【LeetCode回溯算法#01】图解组合问题
报道:效仿微软XGP:Meta为Quest准备订阅制服务
每日短讯:健身猪一只最高能卖8万元:看完再也不配说胖得像猪了
环球百事通!联想小新Pro 16 2023酷睿独显版预售:7299元起 可选RTX4050
环球即时看!年度优秀员工评语简短(年度优秀员工评语)
[NOIP2017 普及组] 棋盘
AspNet Core MVC项目接入AdminLTE
世界动态:京东百亿补贴大杀器亮剑后 尚“无人伤亡”