安庆大理运城常德铜陵江西
投稿投诉
江西南阳
嘉兴昆明
铜陵滨州
广东西昌
常德梅州
兰州阳江
运城金华
广西萍乡
大理重庆
诸暨泉州
安庆南充
武汉辽宁

RocketMQ源码之DLedger存储实现DLedgerM

10月22日 血海塔投稿
  头条创作挑战赛一、前言
  前文我们分析了RocketMQ源码之broker高可用CommitLog管理组件DLedgerCommitLog,本文我们分析DLedgerCommitLog中的mmap内存映射文件存储组件:DLedgerMmapFileS二、源码分析DLedgerMmapFileStore抽象父类DLedgerSDLedgerMmapFileStore成员变量;DLedgerMmapFileStore构造函数;flush数据服务线程;清理空间服务线程;文件内存映射存储实现启动;追加数据;对数据文件进行截断;以follower身份追加数据;根据索引去查询一个数据条目;数据存储格式及编码;1、DLedgerMmapFileStore抽象父类DLedgerStore存储组件抽象类publicabstractclassDLedgerStore{获取到当前server的成员状态publicMemberStategetMemberState(){}作为leader把一个entry追加到磁盘里去publicabstractDLedgerEntryappendAsLeader(DLedgerEntryentry);作为follower把一个entry追加到磁盘里去再追加的时候,我是需要知道是哪个leader同步了这个entry给我的paramentry日志条目paramleaderTermleader选举周期paramleaderIdleaderidreturnpublicabstractDLedgerEntryappendAsFollower(DLedgerEntryentry,longleaderTerm,StringleaderId);根据索引获取日志entrypublicabstractDLedgerEntryget(Longindex);获取已经提交的index索引publicabstractlonggetCommittedIndex();在一轮term里更新已经提交index索引publicvoidupdateCommittedIndex(longterm,longcommittedIndex){}获取结尾termpublicabstractlonggetLedgerEndTerm();获取结尾indexpublicabstractlonggetLedgerEndIndex();获取开始indexpublicabstractlonggetLedgerBeginIndex();更新结尾index和termprotectedvoidupdateLedgerEndIndexAndTerm(){if(getMemberState()!null){getMemberState()。updateLedgerIndexAndTerm(getLedgerEndIndex(),getLedgerEndTerm());}}在存储组件里发起一次flush操作publicvoidflush(){}对指定的leaderterm和id发起一个entry的截断,truncatepubliclongtruncate(DLedgerEntryentry,longleaderTerm,StringleaderId){return1;}存储组件启动publicvoidstartup(){}存储组件停止publicvoidshutdown(){}}2、DLedgerMmapFileStore成员变量基于mmap内存映射文件的存储组件实现,是我们需要重点研究的publicclassDLedgerMmapFileStoreextendsDLedgerStore{publicstaticfinalStringCHECKPOINTFILEpublicstaticfinalStringENDINDEXKEYendIpublicstaticfinalStringCOMMITTEDINDEXKEYcommittedIpublicstaticfinalintMAGIC11;publicstaticfinalintCURRENTMAGICMAGIC1;publicstaticfinalintINDEXUNITSIZE32;privatestaticLoggerloggerLoggerFactory。getLogger(DLedgerMmapFileStore。class);追加entries钩子publicListappendHooksnewArrayList();开始index索引privatelongledgerBeginIndex1;结束index索引privatelongledgerEndIndex1;已经提交的index索引privatelongcommittedIndex1;已经提交的pos位置privatelongcommittedPos1;结束term条目privatelongledgerEndTdledger核心配置组件privateDLedgerConfigdLedgerCserver节点成员状态privateMemberStatememberSmmap内存映射数据文件listprivateMmapFileListdataFileLmmap内存映射索引文件listprivateMmapFileListindexFileL线程本地副本里面的entry缓冲组件privateThreadLocalByteBufferlocalEntryB线程本地副本里面的index缓冲组件privateThreadLocalByteBufferlocalIndexBflush数据服务组件privateFlushDataServiceflushDataS清理空间服务组件privateCleanSpaceServicecleanSpaceS磁盘是否已经满了标识privatevolatilebooleanisDiskF最近一次检查点时间戳privatelonglastCheckPointTimeMsSystem。currentTimeMillis();是否已经加载过的boolean标识privateAtomicBooleanhasLoadednewAtomicBoolean(false);是否已经完成恢复的boolean标识privateAtomicBooleanhasRecoverednewAtomicBoolean(false);完整存储路径setprivatevolatileSetStringfullStorePathsCollections。emptySet();}3、DLedgerMmapFileStore构造函数publicDLedgerMmapFileStore(DLedgerConfigdLedgerConfig,MemberStatememberState){赋值一个dledger配置组件this。dLedgerConfigdLedgerC赋值一个server成员状态组件this。memberStatememberS我们的dledger数据存储路径里面如果说包含有多路径分隔符if(dLedgerConfig。getDataStorePath()。contains(DLedgerConfig。MULTIPATHSPLITTER)){把数据文件list封装为一个多路径mmap内存映射文件listthis。dataFileListnewMultiPathMmapFileList(dLedgerConfig,dLedgerConfig。getMappedFileSizeForEntryData(),this::getFullStorePaths);}else{把数据文件list封装为一个mmap文件listthis。dataFileListnewMmapFileList(dLedgerConfig。getDataStorePath(),dLedgerConfig。getMappedFileSizeForEntryData());}把索引文件list封装成一个mmap内存映射文件listthis。indexFileListnewMmapFileList(dLedgerConfig。getIndexStorePath(),dLedgerConfig。getMappedFileSizeForEntryIndex());线程副本的内存分配,localentry的内存分配,4mblocalEntryBufferThreadLocal。withInitial(()ByteBuffer。allocate(410241024));线程副本的内存分配,localindex的内存分配,一个索引单元大小(32个字节)2localIndexBufferThreadLocal。withInitial(()ByteBuffer。allocate(INDEXUNITSIZE2));构建从内存里flush数据到磁盘文件里的服务组件flushDataServicenewFlushDataService(DLedgerFlushDataService,logger);构建清理空间服务组件cleanSpaceServicenewCleanSpaceService(DLedgerCleanSpaceService,logger);}4、flush数据服务线程分析
  实际flush动作会调用MmapFileListflush方法,RocketMQ源码分析之文件内存映射对象层MappedFile核心方法分析过,不再赘叙;flush数据服务classFlushDataServiceextendsShutdownAbleThread{publicFlushDataService(Stringname,Loggerlogger){super(name,logger);}他会不断的周期性的运行,但是支持关闭他OverridepublicvoiddoWork(){try{longstartSystem。currentTimeMillis();他会周期性的去触发数据文件的flush动作DLedgerMmapFileStore。this。dataFileList。flush(0);他会周期性的去触发索引文件的flush动作DLedgerMmapFileStore。this。indexFileList。flush(0);if((elapsedDLedgerUtils。elapsed(start))500){logger。info(Flushdatacost{}ms,elapsed);}如果说超过了一个检查点时间间隔,还需要去发起一次检查点持久化if(DLedgerUtils。elapsed(lastCheckPointTimeMs)dLedgerConfig。getCheckPointInterval()){persistCheckPoint();lastCheckPointTimeMsSystem。currentTimeMillis();}休眠flush间隔时间waitForRunning(dLedgerConfig。getFlushFileInterval());}catch(Throwablet){logger。info(Errorin{},getName(),t);DLedgerUtils。sleep(200);}}}5、清理空间服务线程清理空间服务线程classCleanSpaceServiceextendsShutdownAbleThread{获取到磁盘空间已经使用比例doublestoreBaseRatioDLedgerUtils。getDiskPartitionSpaceUsedPercent(dLedgerConfig。getStoreBaseDir());数据存储路径里物理占用比例doubledataRatiocalcDataStorePathPhysicRatio();publicCleanSpaceService(Stringname,Loggerlogger){super(name,logger);}OverridepublicvoiddoWork(){try{storeBaseRatioDLedgerUtils。getDiskPartitionSpaceUsedPercent(dLedgerConfig。getStoreBaseDir());dataRatiocalcDataStorePathPhysicRatio();longhourOfMs3600L1000L;longfileReservedTimeMsdLedgerConfig。getFileReservedHours()hourOfMs;if(fileReservedTimeMshourOfMs){logger。warn(ThefileReservedTimeMs{}issmallerthanhourOfMs{},fileReservedTimeMs,hourOfMs);fileReservedTimeMshourOfMs;}Ifthediskisfull,shouldpreventmoredatatogetinDLedgerMmapFileStore。this。isDiskFullisNeedForbiddenWrite();booleantimeUpisTimeToDelete();booleancheckExpiredisNeedCheckExpired();booleanforceCleanisNeedForceClean();booleanenableForceCleandLedgerConfig。isEnableDiskForceClean();intintervalForcibly1201000;if(timeUpcheckExpired){intcountgetDataFileList()。deleteExpiredFileByTime(fileReservedTimeMs,100,intervalForcibly,forceCleanenableForceClean);if(count0(forceCleanenableForceClean)isDiskFull){logger。info(Cleanspacecount{}timeUp{}checkExpired{}forceClean{}enableForceClean{}diskFull{}storeBaseRatio{}dataRatio{},count,timeUp,checkExpired,forceClean,enableForceClean,isDiskFull,storeBaseRatio,dataRatio);}if(count0){DLedgerMmapFileStore。this。reviseLedgerBeginIndex();}}getDataFileList()。retryDeleteFirstFile(intervalForcibly);waitForRunning(100);}catch(Throwablet){logger。info(Errorin{},getName(),t);DLedgerUtils。sleep(200);}}privatebooleanisTimeToDelete(){StringwhenDLedgerMmapFileStore。this。dLedgerConfig。getDeleteWhen();if(DLedgerUtils。isItTimeToDo(when)){}}privatebooleanisNeedCheckExpired(){if(storeBaseRatiodLedgerConfig。getDiskSpaceRatioToCheckExpired()dataRatiodLedgerConfig。getDiskSpaceRatioToCheckExpired()){}}privatebooleanisNeedForceClean(){if(storeBaseRatiodLedgerConfig。getDiskSpaceRatioToForceClean()dataRatiodLedgerConfig。getDiskSpaceRatioToForceClean()){}}privatebooleanisNeedForbiddenWrite(){if(storeBaseRatiodLedgerConfig。getDiskFullRatio()dataRatiodLedgerConfig。getDiskFullRatio()){}}计算数据存储路径物理比例publicdoublecalcDataStorePathPhysicRatio(){SetStringfullStorePathnewHashSet();StringstorePathdLedgerConfig。getDataStorePath();String〔〕pathsstorePath。trim()。split(DLedgerConfig。MULTIPATHSPLITTER);doubleminPhysicRatio100;遍历每一个path路径for(Stringpath:paths){doublephysicRatioDLedgerUtils。isPathExists(path)?DLedgerUtils。getDiskPartitionSpaceUsedPercent(path):1;minPhysicRatioMath。min(minPhysicRatio,physicRatio);if(physicRatiodLedgerConfig。getDiskSpaceRatioToForceClean()){fullStorePath。add(path);}}DLedgerMmapFileStore。this。setFullStorePaths(fullStorePath);returnminPhysicR}}6、文件内存映射存储实现启动对存储组件可以去执行startup启动函数Overridepublicvoidstartup(){数据文件和索引文件加载load();数据恢复recover();flush数据服务组件启动flushDataService。start();清理空间服务组件cleanSpaceService。start();}publicvoidload(){if(!hasLoaded。compareAndSet(false,true)){}mmap内存映射数据文件加载和mmap内存映射索引文件加载if(!this。dataFileList。load()!this。indexFileList。load()){logger。error(Loadfilefailed,thisusuallyindicatesfatalerror,youshouldcheckitmanually);System。exit(1);}}7、追加数据我们可以把一条数据entry追加到我们的存储组件里来OverridepublicDLedgerEntryappendAsLeader(DLedgerEntryentry){当前节点的状态是否是Leader,如果不是,则抛出异常PreConditions。check(memberState。isLeader(),DLedgerResponseCode。NOTLEADER);当前磁盘是否已满,其判断依据是DLedger的根目录或数据文件目录的使用率超过了允许使用的最大值,默认值为85PreConditions。check(!isDiskFull,DLedgerResponseCode。DISKFULL);从线程本地副本里获取到一个自己当前线程的数据缓冲区和索引缓冲区ByteBufferdataBufferlocalEntryBuffer。get();ByteBufferindexBufferlocalIndexBuffer。get();把entry数据编码到数据缓冲区里去DLedgerEntryCoder。encode(entry,dataBuffer);通过数据缓冲区里面的remaining可以获取到entry大小intentrySizedataBuffer。remaining();对server成员状态加锁synchronized(memberState){PreConditions。check(memberState。isLeader(),DLedgerResponseCode。NOTLEADER,null);PreConditions。check(memberState。getTransferee()null,DLedgerResponseCode。LEADERTRANSFERRING,null);所以说endindex1了以后,从1到0,随着追加数据累加的索引值longnextIndexledgerEndIndex1;设置一下索引值entry。setIndex(nextIndex);通过server成员状态获取到term第几轮entry。setTerm(memberState。currTerm());设置魔数entry。setMagic(CURRENTMAGIC);把累加索引、当前term、魔数,写入到了数据缓冲区里去DLedgerEntryCoder。setIndexTerm(dataBuffer,nextIndex,memberState。currTerm(),CURRENTMAGIC);我准备把这条数据预追加到我们的数据文件mmapfiles里去longprePosdataFileList。preAppend(dataBuffer。remaining());entry。setPos(prePos);PreConditions。check(prePos!1,DLedgerResponseCode。DISKERROR,null);DLedgerEntryCoder。setPos(dataBuffer,prePos);在正式写入数据之前可以回调我们的追加hook钩子for(AppendHookwriteHook:appendHooks){writeHook。doHook(entry,dataBuffer。slice(),DLedgerEntry。BODYOFFSET);}数据文件mmapfiles追加对应的数据longdataPosdataFileList。append(dataBuffer。array(),0,dataBuffer。remaining());PreConditions。check(dataPos!1,DLedgerResponseCode。DISKERROR,null);PreConditions。check(dataPosprePos,DLedgerResponseCode。DISKERROR,null);关于dledger索引追加写入DLedgerEntryCoder。encodeIndex(dataPos,entrySize,CURRENTMAGIC,nextIndex,memberState。currTerm(),indexBuffer);索引文件mmapfiles追加一条索引进文件longindexPosindexFileList。append(indexBuffer。array(),0,indexBuffer。remaining(),false);PreConditions。check(indexPosentry。getIndex()INDEXUNITSIZE,DLedgerResponseCode。DISKERROR,null);if(logger。isDebugEnabled()){logger。info(〔{}〕AppendasLeader{}{},memberState。getSelfId(),entry。getIndex(),entry。getBody()。length);}每次追加一条数据写入,写入完了以后endIndex就会累加ledgerEndIledgerEndTermmemberState。currTerm();拿到成员状态的当前termif(ledgerBeginIndex1){ledgerBeginIndexledgerEndI}updateLedgerEndIndexAndTerm();}}8、对数据文件进行截断对数据文件做一个截断,有一部分数据就直接不要了Overridepubliclongtruncate(DLedgerEntryentry,longleaderTerm,StringleaderId){PreConditions。check(memberState。isFollower(),DLedgerResponseCode。NOTFOLLOWER,null);获取到线程本地副本里的数据缓冲区和索引缓冲区ByteBufferdataBufferlocalEntryBuffer。get();ByteBufferindexBufferlocalIndexBuffer。get();DLedgerEntryCoder。encode(entry,dataBuffer);intentrySizedataBuffer。remaining();synchronized(memberState){PreConditions。check(memberState。isFollower(),DLedgerResponseCode。NOTFOLLOWER,roles,memberState。getRole());PreConditions。check(leaderTermmemberState。currTerm(),DLedgerResponseCode。INCONSISTENTTERM,termd!d,leaderTerm,memberState。currTerm());PreConditions。check(leaderId。equals(memberState。getLeaderId()),DLedgerResponseCode。INCONSISTENTLEADER,leaderIds!s,leaderId,memberState。getLeaderId());直接去根据索引读取一条数据出来booleanexistedEtry{DLedgerEntrytmpget(entry。getIndex());existedEntryentry。equals(tmp);}catch(Throwableignored){existedE}longtruncatePosexistedEntry?entry。getPos()entry。getSize():entry。getPos();if(truncatePos!dataFileList。getMaxWrotePosition()){logger。warn(〔TRUNCATE〕leaderId{}index{}truncatePos{}!maxPos{},thisisusuallyhappenedontheoldleader,leaderId,entry。getIndex(),truncatePos,dataFileList。getMaxWrotePosition());}对这个位置开始的数据发起一个截断dataFileList。truncateOffset(truncatePos);if(dataFileList。getMaxWrotePosition()!truncatePos){logger。warn(〔TRUNCATE〕rebuildfordatawrotePos:{}!truncatePos:{},dataFileList。getMaxWrotePosition(),truncatePos);PreConditions。check(dataFileList。rebuildWithPos(truncatePos),DLedgerResponseCode。DISKERROR,rebuilddatatruncatePosd,truncatePos);}修订数据文件mmapfiles的已经flush位置reviseDataFileListFlushedWhere(truncatePos);if(!existedEntry){longdataPosdataFileList。append(dataBuffer。array(),0,dataBuffer。remaining());PreConditions。check(dataPosentry。getPos(),DLedgerResponseCode。DISKERROR,d!d,dataPos,entry。getPos());}数据文件做了一个截断,索引文件也需要做一个截断longtruncateIndexOffsetentry。getIndex()INDEXUNITSIZE;indexFileList。truncateOffset(truncateIndexOffset);if(indexFileList。getMaxWrotePosition()!truncateIndexOffset){logger。warn(〔TRUNCATE〕rebuildforindexwrotePos:{}!truncatePos:{},indexFileList。getMaxWrotePosition(),truncateIndexOffset);PreConditions。check(indexFileList。rebuildWithPos(truncateIndexOffset),DLedgerResponseCode。DISKERROR,rebuildindextruncatePosd,truncateIndexOffset);}reviseIndexFileListFlushedWhere(truncateIndexOffset);DLedgerEntryCoder。encodeIndex(entry。getPos(),entrySize,entry。getMagic(),entry。getIndex(),entry。getTerm(),indexBuffer);longindexPosindexFileList。append(indexBuffer。array(),0,indexBuffer。remaining(),false);PreConditions。check(indexPosentry。getIndex()INDEXUNITSIZE,DLedgerResponseCode。DISKERROR,null);ledgerEndTermentry。getTerm();ledgerEndIndexentry。getIndex();reviseLedgerBeginIndex();updateLedgerEndIndexAndTerm();returnentry。getIndex();}}9、以follower身份追加数据以follower身份追加数据OverridepublicDLedgerEntryappendAsFollower(DLedgerEntryentry,longleaderTerm,StringleaderId){PreConditions。check(memberState。isFollower(),DLedgerResponseCode。NOTFOLLOWER,roles,memberState。getRole());PreConditions。check(!isDiskFull,DLedgerResponseCode。DISKFULL);数据缓冲区和索引缓冲区ByteBufferdataBufferlocalEntryBuffer。get();ByteBufferindexBufferlocalIndexBuffer。get();DLedgerEntryCoder。encode(entry,dataBuffer);intentrySizedataBuffer。remaining();synchronized(memberState){PreConditions。check(memberState。isFollower(),DLedgerResponseCode。NOTFOLLOWER,roles,memberState。getRole());longnextIndexledgerEndIndex1;PreConditions。check(nextIndexentry。getIndex(),DLedgerResponseCode。INCONSISTENTINDEX,null);PreConditions。check(leaderTermmemberState。currTerm(),DLedgerResponseCode。INCONSISTENTTERM,null);PreConditions。check(leaderId。equals(memberState。getLeaderId()),DLedgerResponseCode。INCONSISTENTLEADER,null);在指定位置里追加数据进去longdataPosdataFileList。append(dataBuffer。array(),0,dataBuffer。remaining());PreConditions。check(dataPosentry。getPos(),DLedgerResponseCode。DISKERROR,d!d,dataPos,entry。getPos());DLedgerEntryCoder。encodeIndex(dataPos,entrySize,entry。getMagic(),entry。getIndex(),entry。getTerm(),indexBuffer);追加索引数据longindexPosindexFileList。append(indexBuffer。array(),0,indexBuffer。remaining(),false);PreConditions。check(indexPosentry。getIndex()INDEXUNITSIZE,DLedgerResponseCode。DISKERROR,null);ledgerEndTermentry。getTerm();ledgerEndIndexentry。getIndex();if(ledgerBeginIndex1){ledgerBeginIndexledgerEndI}更新结尾index和termupdateLedgerEndIndexAndTerm();}}10、根据索引去查询一个数据条目根据索引去查询一个数据条目OverridepublicDLedgerEntryget(Longindex){indexCheck(index);定义好索引内存缓冲片段和数据内存缓冲片段SelectMmapBufferResultindexSSelectMmapBufferResultdataStry{直接通过索引文件mmapfiles去查询数据index本身其实第几条索引,每一条索引可以是一个单元是有自己大小,所以定位索引的偏移量indexunitsize,从那个位置开始读取unitsize大小的一条数据indexSbrindexFileList。getData(indexINDEXUNITSIZE,INDEXUNITSIZE);PreConditions。check(indexSbr!nullindexSbr。getByteBuffer()!null,DLedgerResponseCode。DISKERROR,Getnullindexford,index);indexSbr。getByteBuffer()。getInt();magiclongposindexSbr。getByteBuffer()。getLong();intsizeindexSbr。getByteBuffer()。getInt();根据数据位置和大小,再次从数据文件mmapfiles里面读取出来一条数据就可以了dataSbrdataFileList。getData(pos,size);PreConditions。check(dataSbr!nulldataSbr。getByteBuffer()!null,DLedgerResponseCode。DISKERROR,Getnulldataford,index);把这个数据做一个解码DLedgerEntrydLedgerEntryDLedgerEntryCoder。decode(dataSbr。getByteBuffer());PreConditions。check(posdLedgerEntry。getPos(),DLedgerResponseCode。DISKERROR,d!d,pos,dLedgerEntry。getPos());returndLedgerE}finally{把之前读取的索引和数据的缓冲片段做一个释放SelectMmapBufferResult。release(indexSbr);SelectMmapBufferResult。release(dataSbr);}}11、数据存储格式及编码
  日志条目
  DLedgerEntryCoderencode()编码paramentry日志条目parambyteBuffer缓冲区publicstaticvoidencode(DLedgerEntryentry,ByteBufferbyteBuffer){byteBuffer。clear();intsizeentry。computeSizeInBytes();alwaysputmagiconthefirstposition魔数,4字节byteBuffer。putInt(entry。getMagic());条目总长度,包含Header(协议头)消息体,占4字节byteBuffer。putInt(size);当前条目的index,占8字节byteBuffer。putLong(entry。getIndex());当前条目所属的投票轮次,占8字节byteBuffer。putLong(entry。getTerm());该条目的物理偏移量,类似于commitlog文件的物理偏移量,占8字节byteBuffer。putLong(entry。getPos());保留字段,当前版本未使用,占4字节byteBuffer。putInt(entry。getChannel());当前版本未使用,占4字节byteBuffer。putInt(entry。getChainCrc());body的CRC校验和,用来区分数据是否损坏,占4字节。byteBuffer。putInt(entry。getBodyCrc());用来存储body的长度,占4个字节。byteBuffer。putInt(entry。getBody()。length);具体消息的内容。byteBuffer。put(entry。getBody());byteBuffer。flip();}
  日志索引
  DLedgerEntryCoderencodeIndex()日志索引编码parampos日志条目在文件的偏移量paramsize条目大小parammagic魔数paramindex索引paramterm投票轮次parambyteBuffer缓冲区publicstaticvoidencodeIndex(longpos,intsize,intmagic,longindex,longterm,ByteBufferbyteBuffer){byteBuffer。clear();魔数,4字节byteBuffer。putInt(magic);日志条目在文件的偏移量,8字节byteBuffer。putLong(pos);条目大小,4字节byteBuffer。putInt(size);日志条目索引,8字节byteBuffer。putLong(index);投票轮次,8字节byteBuffer。putLong(term);byteBuffer。flip();}
投诉 评论 转载

乾隆死前告诉儿子不要杀和珅,嘉庆却不听,15年后才懂乾隆的苦经过康熙、雍正、乾隆几代帝王的努力,由他们所缔造的康乾盛世已为大清帝国累积下了不少的财富和国力。然而乾隆中后期,随着皇帝频而不绝的纵情享乐以及以大贪官和珅为代表的臣子的一……5年前买了国产车的朋友们,感觉怎么样?这题我会,我来。口说无凭,先上证据,也就是行驶证。我这车,是一台五菱宝骏的宝骏560,当初发布的时候非常火,跟哈弗H6,传祺GS4同台竞争,是当年最火的车。当初我买……408小时野外求生!甘宇能活下来,是我最大的幸运健康时报记者王艾冰高瑞瑞孔天骄阅读提要:地震过后,我们商量还是要爬上大坝,要拉闸,如果我们不回去拉闸的话,大坝里的水长时间流不出来就会溃坝,下边的村庄、田地可能都会面临被……大一当兵,能考军校吗?本人曾在军队负责过士兵考学的相关工作,现在作为高校从事国防教育的老师非常高兴为你解答此问题,希望对你这个大一新生有所帮助。大学生参军入伍后具备报考军校的初步条件为什……孩子是如何变成讨债的?4个需求阶段,若忽略了就很难补回来文兰妈谈育儿有一次聚会,我的谈古说今,让全场气氛开怀大笑一位朋友就问我:你这么开朗的性格,是源自于你的父母影响吗我沉吟了片刻回答算是这样吧朋友突然开始惆……RocketMQ源码之DLedger存储实现DLedgerM头条创作挑战赛一、前言前文我们分析了RocketMQ源码之broker高可用CommitLog管理组件DLedgerCommitLog,本文我们分析DLedgerComm……扫黑风暴中的李成阳是不是英雄?这几天,各大电视台热播的电视剧《扫黑风暴》深受大家的关注,尤其剧中人物性格独特,有着钢铁男儿的李成阳,很受电视观众的喜爱,他不惧强暴、嫉恶如仇、是非鲜明,是扫黑的英雄,也是我们……入职三个月,总觉得自己笨手笨脚的,不讨领导喜欢,咋办?工作是每个成年人享受生活,必需经历的过程。不论从事何种工作,初入行均有一个熟悉本职工作的时间段,在此阶段要认真了解自己的工作环境,工作性质,工作程序,工作要求及目的。只有明白了……广东江门打造世界一流轨道交通产业基地视频加载中。。。白色的主体上一条条亮橙色线条贯穿车身,强烈的现代设计感扑面而来;进入其中,全自动无人驾驶技术与随处可见的新材料设计,顿觉科技感拉满深圳轨道交通13号线首列……最震撼你的毛主席诗词是哪一首?最振撼我的毛主席诗词是:《沁园春。雪》毛主席诗词是中国革命的史诗,是中华诗词海洋中的一朵奇葩,《沁园春。雪》更是经典之作。诗词情感真挚,寓意深远,哲理精辟,被中国无数大文……人心不足蛇吞象究竟为何意?人心不足蛇吞象,蛇怎么能吞下大象呢?其实这个象啊,不是大象的象,而是宰相的相。真实的历史典故是这样说的,相传在北宋年间,有一名书生叫王震,在进京赶考的路上发现了一条小蛇,……1985年梁兴初去世,妻子任桂兰提出唯一请求,中央立刻批示同如果您喜欢这篇作品,欢迎点击右上方关注。感谢您的鼓励与支持,希望能给您带来舒适的阅读体验。1985年9月,梁兴初因突发心脏病,抢救无效后遗憾离世。在他去世后,他的妻子任桂……
理财产品业绩展示测评丨8家股份制银行谁更合规?重庆打造城乡融合新范例兵马俑中一张无法被解释的脸,让人疑惑,如今被禁止出国展览央行银保监会外汇局开会,释放股债汇房重磅信息黄晶果在漳州引种表现及栽培技术要点上下班路上两边停满汽车,电动车都经常堵在路上,如何解决此难题为什么有些公司的试用期为三个月?西安石油大学怎么样?以实际行动彰显胸怀天下的大国担当国际社会这样评价中国非凡十年袁隆平的稻路传奇2023年投资展望丨大类资产篇经济内强外弱,配置内外有别想问一下在京东买手机靠谱吗?屁话太多有智慧的父母,从不当着孩子面做这5件事2018年新春贺词短信那些你以为很好,其实并不健康的生活习惯电热地膜舒适度怎么查不经常用的微信聊天记录(如何查看别人微信的聊天记录)如何申诉撤销交通违章又开学了小学作文200字十五岁叛逆的青春一天中的4个危险时刻,老年人尤其注意更大的舞台正在搭建,优秀的你想成为主角吗嫁给周鹏,安置体育局的女篮美女刘美发展如何?年薪多少?

友情链接:中准网聚热点快百科快传网快生活快软网快好知文好找七猫云易事利