专栏电商日志财经减肥爱情
投稿投诉
爱情常识
搭配分娩
减肥两性
孕期塑形
财经教案
论文美文
日志体育
养生学堂
电商科学
头戴业界
专栏星座
用品音乐

RocketMQ源码之broker高可用CommitLog管

  头条创作挑战赛一、前言
  前文RocketMQ源码分析之核心磁盘数据结构CommitLog让我们知道这个CommitLog是干什么用的,就是broker会将消息写入本地磁盘的CommitLog文件中。
  但是CommitLog采用的MasterSlave部署模式,提供了一定的高可用性。但这样的部署模式,有一定缺陷。比如故障转移方面,如果主节点挂了,还需要人为手动进行重启或者切换,无法自动将一个从节点转换为主节点。
  所以RocketMQ通过DLedgerCommitLog来实现基于raft协议的commitlog存储库,也是RocketMQ实现新的高可用多副本架构的关键。二、源码分析DLedgerCommitLog初始化时机;DLedgerCommitLog成员变量;DLedgerCommitLog构造函数;加载所有磁盘文件mappedfile的数据;数据恢复;追加消息;消息查找;1、DLedgerCommitLog初始化时机
  DefaultMessageStore构造时进行根据是否开启高可用来初始化DLedgerCommitLog还是commitLog;
  上面这行代码也就是说如果开启了高可用的话默认初始化一个DLedgerCommitLog否则就初始化原始的commitLog,我们到这里就可以想到了,这个DLedgerCommitLog和原始的CommitLog相比肯定是多了往子节点同步的部分。2、DLedgerCommitLog成员变量Storeallmetadatadowntimeforrecovery,dataprotectionreliability他是commitlog的子类,他可以去继承我么的commitlog把数据写入到本地磁盘文件里去,以及flush这样的功能对于我们的数据恢复、以及数据保护可以去做一个多副本策略,高可用架构publicclassDLedgerCommitLogextendsCommitLog{开源dledger框架的高可用同步服务器组件privatefinalDLedgerServerdLedgerServer;开源dledger框架的配置组件privatefinalDLedgerConfigdLedgerConfig;开源dledger框架的mmap内存映射文件存储组件privatefinalDLedgerMmapFileStoredLedgerFileStore;开源dledger框架的mmap内存映射文件listprivatefinalMmapFileListdLedgerFileList;Theididentifiesthebrokerrole,0meansmaster,othersmeansslaveprivatefinalintid;消息序列器privatefinalMessageSerializermessageSerializer;用于记录消息追加的时耗(日志追加所持有锁时间)privatevolatilelongbeginTimeInDledgerLock0;Thisoffsetseparatetheoldcommitlogfromdledgercommitlog记录的旧Commitlog文件中的最大偏移量,如果访问的偏移量大于它,则访问Dledger管理的文件privatelongpidedCommitlogOffset1;是否正在恢复旧的Commitlog文件privatebooleanisInrecoveringOldCommitlogfalse;privatefinalStringBuildermsgIdBuildernewStringBuilder();}
  我们可以看到DLedgerCommitLog实际上是继承了CommitLog的,那么DLedgerCommitLog的存储结构又是怎么样的呢,如何兼容CommitLog呢,其实我们根据上面的知识可以想到其实我们的主从高可用只是比普通模式的Log需要多记录一些term,channel等这些元数据信息:
  看到这里我们能想到,我们只要把commitLog的原本信息放到body里不就可以兼容commitLog了,而且改动也不大,对于历史数据也能很好的兼容,rocketmq确实是这么做的。3、DLedgerCommitLog构造函数publicDLedgerCommitLog(finalDefaultMessageStoredefaultMessageStore){调用父类的构造函数也就是说开启了主从架构也会兼容历史的消息super(defaultMessageStore);dLedgerConfignewDLedgerConfig();是否强制删除文件,取自Broker配置属性cleanFileForciblyEnable,默认为truedLedgerConfig。setEnableDiskForceClean(defaultMessageStore。getMessageStoreConfig()。isCleanFileForciblyEnable());DLedger存储类型,固定为基于文件的存储模式dLedgerConfig。setStoreType(DLedgerConfig。FILE);Leader节点的id名称,示例配置:n0,其配置要求第二个字符后必须是数字。dLedgerConfig。setSelfId(defaultMessageStore。getMessageStoreConfig()。getdLegerSelfId());DLegergroup的名称,建议与broker配置属性brokerName保持一致dLedgerConfig。setGroup(defaultMessageStore。getMessageStoreConfig()。getdLegerGroup());DLegerGroup中所有的节点信息,其配置示例n0127。0。0。1:40911;n1127。0。0。1:40912;n2127。0。0。1:40913。多个节点使用分号隔开。dLedgerConfig。setPeers(defaultMessageStore。getMessageStoreConfig()。getdLegerPeers());设置DLedger的日志文件的根目录,取自borker配件文件中的storePathRootDir,即RocketMQ的数据存储根路径。dLedgerConfig。setStoreBaseDir(defaultMessageStore。getMessageStoreConfig()。getStorePathRootDir());设置DLedger的单个日志文件的大小,取自Broker配置文件中的mapedFileSizeCommitLog,即与Commitlog文件的单个文件大小一致dLedgerConfig。setMappedFileSizeForEntryData(defaultMessageStore。getMessageStoreConfig()。getMappedFileSizeCommitLog());DLedger日志文件的删除时间,取自Broker配置文件中的deleteWhen,默认为凌晨4点dLedgerConfig。setDeleteWhen(defaultMessageStore。getMessageStoreConfig()。getDeleteWhen());DLedger日志文件保留时长,取自Broker配置文件中的fileReservedHours,默认为72hdLedgerConfig。setFileReservedHours(defaultMessageStore。getMessageStoreConfig()。getFileReservedTime()1);dLedgerConfig。setPreferredLeaderId(defaultMessageStore。getMessageStoreConfig()。getPreferredLeaderId());dLedgerConfig。setEnableBatchPush(defaultMessageStore。getMessageStoreConfig()。isEnableBatchPush());idInteger。parseInt(dLedgerConfig。getSelfId()。substring(1))1;初始化DledgerServer主要是进行主从复制以及选举使用dLedgerServernewDLedgerServer(dLedgerConfig);dLedgerFileStore(DLedgerMmapFileStore)dLedgerServer。getdLedgerStore();在dledger框架的存储层里加一个append钩子,追加数据之前需要什么定位到这条数据的一个位置然后加入进去这条数据在commitlog里面的全局物理offsetDLedgerMmapFileStore。AppendHookappendHook(entry,buffer,bodyOffset){我们上面说过其实当我们开启了主从同步之后我们追加消息的时候其实只有body是存储的原始的commitLog结构其他对于客户端都是无用的信息所以这里设置的追加消息的钩子函数就是为了返回body的offsetassertbodyOffsetDLedgerEntry。BODYOFFSET;buffer。position(buffer。position()bodyOffsetMessageDecoder。PHYPOSPOSITION);buffer。putLong(entry。getPos()bodyOffset);};dLedgerFileStore。addAppendHook(appendHook);dLedgerFileListdLedgerFileStore。getDataFileList();this。messageSerializernewMessageSerializer(defaultMessageStore。getMessageStoreConfig()。getMaxMessageSize());}
  主要流程节点:调用父类的构造函数也就是说开启了主从架构也会兼容历史的消息构建配置文件类根据DledgerConfig构建DledgerServer主要负责主从日志同步以及选举设置追加消息的钩子函数4、加载所有磁盘文件mappedfile的数据
  这里其实就是去加载commitLog中的信息为了进行历史消息的兼容publicbooleanload(){returnsuper。load();}
  最后还是调用到了父类CommitLog中的load方法,其中mappedFileQueue的load方法,前文RocketMQ源码分析之映射文件队列MappedFileQueue有进行讲解;CommitLog里面数据都是在多个磁盘文件里的,每个磁盘文件都是一个MappedFile他应该是属于把所有的磁盘文件mappedfile的数据,从磁盘里load加载到映射内存区域里来publicbooleanload(){booleanresultthis。mappedFileQueue。load();log。info(loadcommitlog(result?OK:Failed));returnresult;}5、数据恢复加载commitLog以及index文件的wrotePosition,flushedPosition,committedPosition重要的指针;如果存在dLedgerFile则恢复返回;调用commitLog的recoverNormall()进行commitLog文件的恢复;如果不存在旧的commitLog直接结束文件日志的恢复流程;如果存在则尝试找到最后一个commitLog文件,如果没找到就停止;从最后一个文件的最后写入点尝试查找写入的魔数,如果存在魔数并且等CommitLog。BLANKMAGICCODE则无需写入魔数;初始化pidedCommitlogOffset,等于最后一个文件的起始偏移量加上文件的大小,即该指针指向最后一个文件的结束位置;将最后一个文件全部写满,其方法为设置消息体的大小以及魔数;设置最后一个文件的WrotePosition,CommittedPosition,FlushedPosition表示文件已经被写满;privatevoidrecover(longmaxPhyOffsetOfConsumeQueue){主要是加载commitLog以及index文件的wrotePosition,flushedPosition,committedPosition重要的指针dLedgerFileStore。load();if(dLedgerFileList。getMappedFiles()。size()0){如果存在dLedgerFile只需要恢复dLedgerFile即可存在dLedgerFile恢复dLedgerFiledLedgerFileStore。recover();设置pidedCommitlogOffset为dLedger文件的最小offset作为和老的commitLog的分割,小于这个offset需要访问老的commitLogpidedCommitlogOffsetdLedgerFileList。getFirstMappedFile()。getFileFromOffset();MappedFilemappedFilethis。mappedFileQueue。getLastMappedFile();if(mappedFile!null){如果存在旧的commitLog则禁止删除Dledger防止出现日志断层影响查询disableDeleteDledger();}最大物理offsetlongmaxPhyOffsetdLedgerFileList。getMaxWrotePosition();ClearConsumeQueueredundantdataif(maxPhyOffsetOfConsumeQueuemaxPhyOffset){log。warn(〔TruncateCQ〕maxPhyOffsetOfConsumeQueue({})processOffset({}),truncatedirtylogicfiles,maxPhyOffsetOfConsumeQueue,maxPhyOffset);this。defaultMessageStore。truncateDirtyLogicFiles(maxPhyOffset);}return;}Indicatethat,itisthefirsttimetoloadmixedcommitlog,needtorecovertheoldcommitlogisInrecoveringOldCommitlogtrue;Noneedtheabnormalrecover调用commitLog的recoverNormall()进行commitLog文件的恢复super。recoverNormally(maxPhyOffsetOfConsumeQueue);isInrecoveringOldCommitlogfalse;如果不存在旧的commitLog直接结束文件日志的恢复流程MappedFilemappedFilethis。mappedFileQueue。getLastMappedFile();不存在旧的commitLog直接返回if(mappedFilenull){return;}ByteBufferbyteBuffermappedFile。sliceByteBuffer();byteBuffer。position(mappedFile。getWrotePosition());booleanneedWriteMagicCodetrue;1TOTALSIZEbyteBuffer。getInt();sizeintmagicCodebyteBuffer。getInt();if(magicCodeCommitLog。BLANKMAGICCODE){needWriteMagicCodefalse;}else{log。info(Recoveroldcommitlogfoundaillegalmagiccode{},magicCode);}dLedgerConfig。setEnableDiskForceClean(false);pidedCommitlogOffsetmappedFile。getFileFromOffset()mappedFile。getFileSize();log。info(RecoveroldcommitlogneedWriteMagicCode{}pos{}file{}pidedCommitlogOffset{},needWriteMagicCode,mappedFile。getFileFromOffset()mappedFile。getWrotePosition(),mappedFile。getFileName(),pidedCommitlogOffset);if(needWriteMagicCode){byteBuffer。position(mappedFile。getWrotePosition());byteBuffer。putInt(mappedFile。getFileSize()mappedFile。getWrotePosition());byteBuffer。putInt(BLANKMAGICCODE);mappedFile。flush(0);}设置最后一个文件的WrotePosition,CommittedPosition,FlushedPosition表示文件已经被写满mappedFile。setWrotePosition(mappedFile。getFileSize());mappedFile。setCommittedPosition(mappedFile。getFileSize());mappedFile。setFlushedPosition(mappedFile。getFileSize());dLedgerFileList。getLastMappedFile(pidedCommitlogOffset);log。info(Willsettheinitialcommitlogoffset{}fordledger,pidedCommitlogOffset);}6、追加消息publicCompletableFuturePutMessageResultasyncPutMessage(MessageExtBrokerInnermsg){StoreStatsServicestoreStatsServicethis。defaultMessageStore。getStoreStatsService();finalinttranTypeMessageSysFlag。getTransactionValue(msg。getSysFlag());setMessageInfo(msg,tranType);finalStringfinalTopicmsg。getTopic();BacktoResultsAppendMessageResultappendResult;AppendFuturedledgerFuture;EncodeResultencodeResult;encodeResultthis。messageSerializer。serialize(msg);if(encodeResult。status!AppendMessageStatus。PUTOK){returnCompletableFuture。completedFuture(newPutMessageResult(PutMessageStatus。MESSAGEILLEGAL,newAppendMessageResult(encodeResult。status)));}putMessageLock。lock();spinorReentrantLock,dependingonstoreconfiglongelapsedTimeInLock;longqueueOffset;try{beginTimeInDledgerLockthis。defaultMessageStore。getSystemClock()。now();queueOffsetgetQueueOffsetByKey(encodeResult。queueOffsetKey,tranType);encodeResult。setQueueOffsetKey(queueOffset,false);追加消息的时候不再写入之前的commitLog而是调用dlegerserver的handleAppend进行日志的写入子节点日志的复制(后面会详细讲解)只有超过半数以上的节点复制成功才会返回成功如果追加成功则会返回追加成功的起始偏移量即pos属性类似于commitLog中的物理偏移量AppendEntryRequestrequestnewAppendEntryRequest();request。setGroup(dLedgerConfig。getGroup());request。setRemoteId(dLedgerServer。getMemberState()。getSelfId());request。setBody(encodeResult。getData());dledgerFuture(AppendFuture)dLedgerServer。handleAppend(request);if(dledgerFuture。getPos()1){returnCompletableFuture。completedFuture(newPutMessageResult(PutMessageStatus。OSPAGECACHEBUSY,newAppendMessageResult(AppendMessageStatus。UNKNOWNERROR)));}根据dledger的起始偏移量计算真正的消息的存储offset。longwroteOffsetdledgerFuture。getPos()DLedgerEntry。BODYOFFSET;intmsgIdLength(msg。getSysFlag()MessageSysFlag。STOREHOSTADDRESSV6FLAG)0?448:1648;ByteBufferbufferByteBuffer。allocate(msgIdLength);StringmsgIdMessageDecoder。createMessageId(buffer,msg。getStoreHostBytes(),wroteOffset);elapsedTimeInLockthis。defaultMessageStore。getSystemClock()。now()beginTimeInDledgerLock;appendResultnewAppendMessageResult(AppendMessageStatus。PUTOK,wroteOffset,encodeResult。getData()。length,msgId,System。currentTimeMillis(),queueOffset,elapsedTimeInLock);switch(tranType){caseMessageSysFlag。TRANSACTIONPREPAREDTYPE:caseMessageSysFlag。TRANSACTIONROLLBACKTYPE:break;caseMessageSysFlag。TRANSACTIONNOTTYPE:caseMessageSysFlag。TRANSACTIONCOMMITTYPE:ThenextupdateConsumeQueueinformationDLedgerCommitLog。this。topicQueueTable。put(encodeResult。queueOffsetKey,queueOffset1);break;default:break;}}catch(Exceptione){log。error(Putmessageerror,e);returnCompletableFuture。completedFuture(newPutMessageResult(PutMessageStatus。UNKNOWNERROR,newAppendMessageResult(AppendMessageStatus。UNKNOWNERROR)));}finally{beginTimeInDledgerLock0;putMessageLock。unlock();}if(elapsedTimeInLock500){log。warn(〔NOTIFYME〕putMessageinlockcosttime(ms){},bodyLength{}AppendMessageResult{},elapsedTimeInLock,msg。getBody()。length,appendResult);}returndledgerFuture。thenApply(appendEntryResponse{PutMessageStatusputMessageStatusPutMessageStatus。UNKNOWNERROR;switch(DLedgerResponseCode。valueOf(appendEntryResponse。getCode())){caseSUCCESS:putMessageStatusPutMessageStatus。PUTOK;break;caseINCONSISTENTLEADER:caseNOTLEADER:caseLEADERNOTREADY:caseDISKFULL:putMessageStatusPutMessageStatus。SERVICENOTAVAILABLE;break;caseWAITQUORUMACKTIMEOUT:Donotreturnflushslavetimeouttotheclient,fortheonsclientwillignoreit。putMessageStatusPutMessageStatus。OSPAGECACHEBUSY;break;caseLEADERPENDINGFULL:putMessageStatusPutMessageStatus。OSPAGECACHEBUSY;break;}PutMessageResultputMessageResultnewPutMessageResult(putMessageStatus,appendResult);if(putMessageStatusPutMessageStatus。PUTOK){StatisticsstoreStatsService。getSinglePutMessageTopicTimesTotal(finalTopic)。add(1);storeStatsService。getSinglePutMessageTopicSizeTotal(msg。getTopic())。add(appendResult。getWroteBytes());}returnputMessageResult;});}7、消息查找
  消息的查找起始和原来还是没有什么区别的,还是使用二分查找法通过offset获取mappedFile文件,只是多了一个pidedCommitlogOffset的判断是否是老数据,如果是老数据直接走commitLog,新数据就走Dledger维护的文件列表;publicSelectMappedBufferResultgetMessage(finallongoffset,finalintsize){如果是小于pidedCommitlogOffset证明是旧数据从commitLog获取if(offsetpidedCommitlogOffset){returnsuper。getMessage(offset,size);}从dledger获取intmappedFileSizethis。dLedgerServer。getdLedgerConfig()。getMappedFileSizeForEntryData();MmapFilemappedFilethis。dLedgerFileList。findMappedFileByOffset(offset,offset0);if(mappedFile!null){intpos(int)(offsetmappedFileSize);获取文件并转换为DLedgerSelectMappedBufferResult类型returnconvertSbr(mappedFile。selectMappedBuffer(pos,size));}returnnull;}三、总结DLedger在整合时,使用DLedger条目包裹RocketMQ中的CommitLog条目,即在DLedger条目的body字段来存储整条CommitLog条目;引入pidedCommitlogOffset变量,表示物理偏移量小于该值的消息存在于旧的CommitLog文件中,实现升级DLedger集群后能访问到旧的数据;新DLedger集群启动后,会将最后一个CommitLog填充,即新的数据不会再写入到原先的CommitLog文件;消息追加到DLedger数据日志文件中,返回的偏移量不是DLedger条目的起始偏移量,而是DLedger条目中body字段的起始偏移量,即真实消息的起始偏移量,保证消息物理偏移量的语义与RocketMQCommitlog一样;

LOL猫狗大战皮肤套系回归!LOL上一次猫狗大战系列时间是2019年3月,时隔5年,该系列皮肤再次回归,英雄联盟超话LOL猫狗大战回归游戏LOL官方已经公布了猫狗大战2023皮肤预览视频,时隔5年,官方再次推有哪些让你目瞪口呆的Bug?1970年代早期的操作系统bug早期的计算机操作系统在处理时间方面存在问题,导致在某些情况下计算机会在1970年1月1日之前的时间戳上挂起或崩溃。雷神之锤游戏的人物在墙里的bug这生化4RE动画小剧场第二集里昂被碍事梨坑惨了!在前两天卡普空官方发布了生化危机4重制版动画小剧场第一集不可思议村子里的里昂,其可爱复古的画风吸引了不少玩家,但内容却十分鬼畜。今天官方很快就更新了第二集,下面让我们一起来看看吧!让电视变身大号红白机,怀念儿时游戏头条创作挑战赛前段时间给我的华为智慧屏配了一个北通的游戏手柄,就想在我的75寸大屏上玩更多的游戏。本来华为游戏中心的游戏就不多,大多数还要收费,实在没什么意思。后来研究了一下,可以160小时续航,标配无线充,雷柏双模无线充电RGB游戏鼠标上市V无线游戏技术,原相3335游戏光学引擎,续航至高160小时,带无线充电功能,支持QI无线充电协议,强劲敏捷的犀利线条,这些特点加持在一款曾承载无数玩家游戏梦想的明星产品,会重现什预算4500元如何选购游戏PC主机?DIY最大的优势就在于可以用更少的钱换来更高的配置,和更有个性化的视觉方案,尤其是在入门级市场,自己组装的主机吸引力要远高于品牌机,并且后期维护也非常方便。下面就为您推荐一套450玩家起诉微软收购动视被驳回法官称微软独占COD没好处2022年12月份时,美国地区有一群玩家提起了针对微软收购动视暴雪的反垄断诉讼,理由是此举会损害玩家利益减少相关产品市场竞争,现在据知名市场竞争分析师FlorianMueller透恭喜肖战商务价值评选登顶,手握43个代言,品牌续约率高达90肖战时装周上大杀四方,手握43个代言,品牌续约率高达90,肖战的商务价值登顶实至名归!肖战据不完全统计,肖战目前已经手握43个代言,从高奢品GucciTODS真力时奥迪,到日用品拉中华武术狮舞九天异彩纷呈桑植民俗文化旅游节,上洞街乡火了红网时刻张家界3月22日讯(通讯员陈振)日前,在桑植县首届民俗文化旅游节上洞街乡专场区域,精彩绝伦的武术表演气势磅礴的传统舞狮民族特色的土家围鼓,赢得了游客们的阵阵欢呼,为广大市民摩根大通150万美元买的镍块,清点时成了一堆石头?背后原因成谜在荷兰港口城市鹿特丹,有一座堆满金属矿产的大型仓库。坐拥这批资源的是美国金融机构摩根大通。几年前,他们在全球买下大批镍块,放进袋子封装起来。这些镍块存放在物流公司AccessWor满洲名将阿桂号称清代卫青,开拓西北百万公里,和珅屈居他之下序言阿桂(1717年1797年),章佳氏,满洲正蓝旗人,乾隆时期内阁大学士阿克敦之子,二十岁步入政坛,不到十年时间升至军机章京,跻身朝廷中枢。1748年出征大小金川时起,弃文从武,
技不如人遭遇连败,尤金复出青岛男篮不敌山西男篮半岛全媒体首席记者杜金城竞技场比拼斗志毅力甚至是运气,但决定比赛胜负的最关键因素还是实力。1月11日中午,青岛国信水产男篮在与山西男篮的正面交锋中以99114不敌对手,遭遇了联赛两谁总得分有望超自己?老詹第一个想到杜兰特,还有欧东恩字几天前,詹姆斯接受ESPN独家专访,在谈到哪位球员的生涯总得分有望超越自己,老詹直言不讳,说KD肯定是第一个浮现在我脑海中的名字,凯文杜兰特被叫EasyMoney和SlimReap人生四问,迷津未知能否发表一句今生的感悟从楼上俯瞰高速公路,车流川流不息,昼夜不停晨光熹微时分,城市早起的车辆的灯光把街市摇曳成一条亮亮的河。路边的早餐摊,摊主早已开始支起摊位,一天的辛苦忙碌即将开姆巴佩入选法甲1112月最佳球员候选,本赛季首次获提名直播吧1月11日讯法国职业球员工会(UNFP)日前宣布了1112月份的法甲最佳球员候选名单,巴黎圣日耳曼前锋姆巴佩朗斯中场赛克福法纳雷恩中场本杰明布里吉奥入选。由于11月底到12月老里谈首发阵容没有打太多ampampamp这是出色的进攻阵容我们在评估防守直播吧1月11日讯今日NBA常规赛,76人在主场147116大胜活塞。据统计,这是76人球员哈里斯塔克恩比德马克西及哈登本赛季第7次一同首发出战。赛后,主教练里弗斯在接受采访时讲道只要我愿意,我能打满48分钟,盘点NBA历史5大体力怪NBA一场比赛,常规赛时间是48分,这期间不管你是核心还是替补,都会得到休息时间。每场出战30分钟都算体力好了,35分钟更算是劳模了。但是对于有些体力怪球星来说,只要他们愿意,他们电讯报若日尼奥或将重回意甲切尔西夏窗目标为贝林厄姆和赖斯直播吧1月11日讯每日电讯报今天撰文分析了切尔西的冬窗转会情况以及球队续约事宜。切尔西需要为球队中场若日尼奥赛季结束时自由转会做好准备。同时,俱乐部对今夏合同就要到期的坎特持乐观态半年花3。45亿全欧第一!这豪门争四提前掉队,请回穆帅,他能争冠这个冬窗已经开启几天,不过现在还是静悄悄,之前切尔西一度希望引进恩佐费尔南德斯,可惜他们8500万欧元的报价没能打动本菲卡,这笔交易也胎死腹中。虽然没能拿下天才中场恩佐费尔南德斯,浩瀚体育安帅曾将加图索引荐给那不勒斯,后者篡位导致关系破裂昨天皇马主帅安切洛蒂在新闻发布会上公开提到了与昔日弟子加图索之间的矛盾,今天包括晚邮报共和报和米兰体育报在内的多家意大利都媒体详细报道了两人关系破裂的原因。米兰体育报驻西班牙记者F羽毛球大马赛首日国羽战绩不佳石宇奇何冰娇等多名主力首轮出局不愧是世界羽联最高级别的巡回赛,首日国羽部分主力队员即遭遇强敌吃到败仗而出局,大老远赶去东南亚却只能接受一轮游。北京时间1月10日晚,2023超级1000马来西亚公开赛揭幕,在32马来西亚公开赛开打凡尘组合迎来新赛季首战资料图贾一凡(左)与搭档陈清晨(右)。图新华网红网时刻新闻1月11日讯(记者周雨墨)1月10日至15日,马来西亚羽毛球公开赛将在吉隆坡进行,作为世界羽联巡回赛超级1000级别的赛事
友情链接:快好找快生活快百科快传网中准网文好找聚热点快软网