范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

自己动手实现一个RocketMQ文件存储系统

  前言
  RocketMQ作为一款优秀的开源消息中间件,很多java开发者都在使用并研究里面的源码。目前网上有很多关于RocketMQ源代码的文章,但是很多文章只是从框架开发者的的角度分析源码,没有从技术实现本质进行剖析。因此很多源码学习者在读完后还是一知半解,当自己想动手写的时候不知要用到哪种技术,无从着手。笔者基于对RocketMQ的文件存储研究,结合开发者常见的技术,自己动手实现了一个简化版本的RocketMQ文件系统,希望能抽丝剥茧,帮助开发者从本质上理解RocketMQ文件存储的原理,起到抛砖引玉,举一反三的作用。
  RocketMQ逻辑存储结构
  本文适合对RocketMQ的文件存储原理有一定的了解,熟悉java NIO,希望了解RocketMQ是如何通过java NIO实现的读者。以下代码部分:
  1.手动生成10个消息,并创建commitLog文件,consumeQueue,indexFile文件package org.apache.rocketmq.test.smoke;  import com.alibaba.fastjson.JSON; import org.apache.rocketmq.test.smoke.model.ConsumerQueueData; import org.apache.rocketmq.test.smoke.model.IndexFileHeaderData; import org.apache.rocketmq.test.smoke.model.IndexFileItemData;  import java.io.IOException; import java.net.URI; import java.nio.ByteBuffer; import java.nio.MappedByteBuffer; import java.nio.channels.FileChannel; import java.nio.charset.StandardCharsets; import java.nio.file.Paths; import java.nio.file.StandardOpenOption; import java.util.ArrayList; import java.util.List; import java.util.Random; import java.util.UUID;  public class CommitLogWriteTest {     private static Long commitLogOffset = 0L;//8byte(commitlog offset)     private static Long lastTotalSize = 0L;     private static Long currentTotalSize = 0L;     private static List consumerQueueDatas = new ArrayList<>();     private static List indexFileItemDatas = new ArrayList<>();     private static int MESSAGE_COUNT = 10;      public static void main(String[] args) throws IOException {         createCommitLog();         createConsumerQueue();         createIndexFile();     }      private static void createCommitLog() throws IOException {         FileChannel fileChannel = FileChannel.open(Paths.get(URI.create("file:/c:/123/commitLog.txt")),                 StandardOpenOption.WRITE, StandardOpenOption.READ);         MappedByteBuffer mappedByteBuffer = fileChannel.map(FileChannel.MapMode.READ_WRITE, 0, 409600);         fileChannel.close();         Random random = new Random();          int count = 0;         for (int i = 0; i < MESSAGE_COUNT; i++) {             long commitLogOffset = lastTotalSize;              String topic = "Topic-test";             String msgId = UUID.randomUUID().toString();             String msgBody = "消息内容" + "msgmsgmsgmsgmsgmsgmsgmsgmsgmsgmsgmsgmsgmsgmsgmsgmsg".substring(0, random.nextInt(48));//             long queueOffset = i;//索引偏移量             String transactionId = UUID.randomUUID().toString();            /* 数据格式,位置固定          int totalSize;//消息长度          String msgId;          String topic;          long queueOffset;//索引偏移量          long bodySize;//消息长度          byte[] body;//消息内容          String transactionId;          long commitLogOffset;//从第一个文件开始算的偏移量           */              int totalSize = 8 //totalSize长度                     + 64  //msgId长度                     + 64 //topic长度                     + 8 //索引偏移量长度                     + 8 //消息长度长度                     + msgBody.getBytes(StandardCharsets.UTF_8).length //消息内容长度                     + 64  //transactionId长度                     + 64  //commitLogOffset长度;                     ;              ByteBuffer b = ByteBuffer.allocate(totalSize);             // //如果3个消息长度分别是100,200,350,则偏移量分别是0,100,300             mappedByteBuffer.position(Integer.valueOf(commitLogOffset + ""));              b.putLong(totalSize);//totalSize             b.put(getBytes(msgId, 64));//msgId             b.put(getBytes(topic, 64));//topic,定长64             b.putLong(queueOffset);//索引偏移量             b.putLong(msgBody.getBytes(StandardCharsets.UTF_8).length);//bodySize             b.put(msgBody.getBytes(StandardCharsets.UTF_8));//body             b.put(getBytes(transactionId, 64));             b.putLong(commitLogOffset);//bodySize             b.flip();             mappedByteBuffer.put(b);              lastTotalSize = totalSize + lastTotalSize;              System.out.println("写入消息,第:" + i + "次");              System.out.println("totalSize:" + totalSize);             System.out.println("msgId:" + msgId);             System.out.println("topic:" + topic);             System.out.println("msgBody:" + msgBody);             System.out.println("transactionId:" + transactionId);             System.out.println("commitLogOffset:" + commitLogOffset);              ConsumerQueueData consumerQueueData = new ConsumerQueueData();             consumerQueueData.setOffset(commitLogOffset);             consumerQueueData.setMsgLength(totalSize);             consumerQueueData.setTagCode(100L);             //准备生成consumeQueue文件             consumerQueueDatas.add(consumerQueueData);              IndexFileItemData indexFileItemData = new IndexFileItemData();             indexFileItemData.setKeyHash(msgId.hashCode());             indexFileItemData.setMessageId(msgId);             indexFileItemData.setPhyOffset(commitLogOffset);             //准备生成indexFile文件             indexFileItemDatas.add(indexFileItemData);             mappedByteBuffer.force();             count++;         }          System.out.println("commitLog数据保存完成,totalSize:" + count);      }       public static void createConsumerQueue() throws IOException {         FileChannel fileChannel = FileChannel.open(Paths.get(URI.create("file:/c:/123/consumerQueue.txt")),                 StandardOpenOption.WRITE, StandardOpenOption.READ);         MappedByteBuffer mappedByteBuffer = fileChannel.map(FileChannel.MapMode.READ_WRITE, 0, 4096);         fileChannel.close();         int count = 0;         for (int i = 0; i < consumerQueueDatas.size(); i++) {             ConsumerQueueData consumerQueueData = consumerQueueDatas.get(i);             //指定写入位置             mappedByteBuffer.position(i * 20);             mappedByteBuffer.putLong(consumerQueueData.getOffset());//8byte(commitlog offset)             mappedByteBuffer.putInt(consumerQueueData.getMsgLength());//4byte (msgLength)             mappedByteBuffer.putLong(consumerQueueData.getTagCode());//8byte (tagCode)              count++;             System.out.println("consumerQueue数据写入完成:" + JSON.toJSONString(consumerQueueData));             mappedByteBuffer.force();          }         System.out.println("ConsumerQueue数据保存完成count:" + count);      }        public static void createIndexFile() throws IOException {         //文件场创建时间,在写第一条消息的时候创建         FileChannel fileChannel = FileChannel.open(Paths.get(URI.create("file:/c:/123/index.txt")),                 StandardOpenOption.WRITE, StandardOpenOption.READ);         MappedByteBuffer mappedByteBuffer = fileChannel.map(FileChannel.MapMode.READ_WRITE, 0, 409600);         ByteBuffer headerByteBuffer = mappedByteBuffer.slice();         long firstDataTime = System.currentTimeMillis();          fileChannel.close();          //开始写hash槽,从头部后写入         /*  已经填充有index的slot数量           (并不是每个slot槽下都挂载有index索引单元,这 里统计的是所有挂载了index索引单元的slot槽的数量,hash冲突)*/         int hashSlotCount = 0;          /* 已该indexFile中包含的索引单元个数(统计出当前indexFile中所有slot槽下挂载的所有index索引单元的数量之和),         如果没有hash冲突,hashSlotCount = indexCount*/         int indexCount = 0;          //假设建立100个槽位(总长度400)         int soltNum = 100;          for (int i = 0; i < MESSAGE_COUNT; i++) {             IndexFileItemData indexFileItemData = indexFileItemDatas.get(i);             int keyHash = indexFileItemData.getKeyHash();              //取模,计算第几个槽位             int slotPos = keyHash % 100 > 0?keyHash % 100:-1*(keyHash % 100);              // slot存放第几条数据的的位置(字节数组位置)             int absSlotPos = 40 + slotPos * 4;              // 存储实际数据的位置(字节数组位置)             int absIndexPos =                     40 + soltNum * 4                             + indexCount * 20;                //将hash槽的值设置为indexCount,建立索引,即第n条消息保存在XX位置             mappedByteBuffer.putInt(absSlotPos, indexCount);              //写入数据             mappedByteBuffer.putInt(absIndexPos,indexFileItemData.getKeyHash());//4byte msg hashcode             mappedByteBuffer.putLong(absIndexPos+4,indexFileItemData.getPhyOffset());//8byte pyhoffset             mappedByteBuffer.putInt(absIndexPos+4+8,Integer.valueOf((System.currentTimeMillis()- firstDataTime)+""));//4byte (timeDiff)             mappedByteBuffer.putInt(absIndexPos+4+8+4,0);//4byte (preIndex),暂置0,暂不考虑hash冲突的情况               //模拟最后一个文件,写入header             if (i == 0) {                 //该indexFile中第一条消息的存储时间                 headerByteBuffer.putLong(0, firstDataTime);                 //该indexFile种第一条消息在commitlog种的偏移量commitlog offset                 mappedByteBuffer.putLong(16, indexFileItemData.getPhyOffset());             }             //模拟最后一个文件,写入header             if (i == 99) {                 //该indexFile种最后一条消息存储时间                 headerByteBuffer.putLong(8, System.currentTimeMillis());                 //该indexFile中最后一条消息在commitlog中的偏移量commitlog offset                 headerByteBuffer.putLong(24, indexFileItemData.getPhyOffset());             }             //已经填充有index的slot数量             headerByteBuffer.putInt(32, hashSlotCount+1);             //该indexFile中包含的索引单元个数             headerByteBuffer.putInt(36, indexCount+1);             mappedByteBuffer.force();             System.out.println("msgId:"+indexFileItemData.getMessageId()+",keyHash:"+keyHash+",保存槽位为"+slotPos+"的数据,absSlotPos="+absSlotPos+",值index="+indexCount+",绝对位置:"+absIndexPos+",commit-phyOffset:"+indexFileItemData.getPhyOffset());              indexCount ++;             hashSlotCount++;          }      }        //将变长字符串定长byte[],方便读取     private static byte[] getBytes(String s, int length) {         int fixLength = length - s.getBytes().length;         if (s.getBytes().length < length) {             byte[] S_bytes = new byte[length];             System.arraycopy(s.getBytes(), 0, S_bytes, 0, s.getBytes().length);             for (int x = length - fixLength; x < length; x++) {                 S_bytes[x] = 0x00;             }             return S_bytes;         }         return s.getBytes(StandardCharsets.UTF_8);     }  }
  运行结果:写入消息,第:0次 totalSize:322 msgId:61b5c500-f7f5-4bfe-beb1-50a8148534c0 topic:Topic-test msgBody:消息内容msgmsgmsgmsgmsgmsgmsgmsgmsgmsg transactionId:9453ba39-3982-40e9-926d-47b51d360590 commitLogOffset:0 写入消息,第:1次 totalSize:306 msgId:d0fbf80f-223b-4721-a43e-518b152decc2 topic:Topic-test msgBody:消息内容msgmsgmsgmsgms transactionId:e2ef1652-58fa-4849-bf74-885c7e5db9e3 commitLogOffset:322 写入消息,第:2次 totalSize:307 msgId:199053e3-e616-4611-ab0d-e5c7af4549a9 topic:Topic-test msgBody:消息内容msgmsgmsgmsgmsg transactionId:33d21abe-0d8e-4c0e-9c78-f415daefd767 commitLogOffset:628 写入消息,第:3次 totalSize:339 msgId:8e799d8e-3290-4f6b-ab5d-289153446994 topic:Topic-test msgBody:消息内容msgmsgmsgmsgmsgmsgmsgmsgmsgmsgmsgmsgmsgmsgmsgms transactionId:98b46b96-cc88-4969-a56f-282d25799085 commitLogOffset:935 写入消息,第:4次 totalSize:320 msgId:8b78474f-b28a-4442-99a0-6f7883f0302b topic:Topic-test msgBody:消息内容msgmsgmsgmsgmsgmsgmsgmsgmsgm transactionId:5c0ff6fe-aea3-40c3-8647-6f4bdd797a78 commitLogOffset:1274 写入消息,第:5次 totalSize:312 msgId:b33c6f31-cc96-462b-b095-99410459082c topic:Topic-test msgBody:消息内容msgmsgmsgmsgmsgmsgms transactionId:57420047-2539-43fa-a3f2-b2f55c7b059c commitLogOffset:1594 写入消息,第:6次 totalSize:324 msgId:d0a6803f-8555-418e-988a-b3b9a70d14f0 topic:Topic-test msgBody:消息内容msgmsgmsgmsgmsgmsgmsgmsgmsgmsgms transactionId:29601335-3fcd-4193-b14f-140bbaf409a4 commitLogOffset:1906 写入消息,第:7次 totalSize:293 msgId:91151ec5-e76b-4560-90b7-ab77f9d04c9a topic:Topic-test msgBody:消息内容m transactionId:291e54de-2ebe-41b1-b974-e81a2e9f1370 commitLogOffset:2230 写入消息,第:8次 totalSize:323 msgId:eb21df35-b4dc-43aa-8604-e9a103f25a7b topic:Topic-test msgBody:消息内容msgmsgmsgmsgmsgmsgmsgmsgmsgmsgm transactionId:3005a39d-b8cb-4138-ae05-34b65fc135a2 commitLogOffset:2523 写入消息,第:9次 totalSize:296 msgId:abcda364-8fc3-4d18-ae5d-1d7a8ffd0929 topic:Topic-test msgBody:消息内容msgm transactionId:d42733b5-3911-4f0a-b1db-11eb45a30345 commitLogOffset:2846 commitLog数据保存完成,totalSize:10  创建consumerQueue文件开始 consumerQueue数据写入完成:{"msgLength":322,"offset":0,"tagCode":100} consumerQueue数据写入完成:{"msgLength":306,"offset":322,"tagCode":100} consumerQueue数据写入完成:{"msgLength":307,"offset":628,"tagCode":100} consumerQueue数据写入完成:{"msgLength":339,"offset":935,"tagCode":100} consumerQueue数据写入完成:{"msgLength":320,"offset":1274,"tagCode":100} consumerQueue数据写入完成:{"msgLength":312,"offset":1594,"tagCode":100} consumerQueue数据写入完成:{"msgLength":324,"offset":1906,"tagCode":100} consumerQueue数据写入完成:{"msgLength":293,"offset":2230,"tagCode":100} consumerQueue数据写入完成:{"msgLength":323,"offset":2523,"tagCode":100} consumerQueue数据写入完成:{"msgLength":296,"offset":2846,"tagCode":100} ConsumerQueue数据保存完成count:10  创建索引文件开始 msgId:61b5c500-f7f5-4bfe-beb1-50a8148534c0,keyHash:249765627,保存槽位为27的数据,absSlotPos=148,值index=0,绝对位置:440,commit-phyOffset:0 msgId:d0fbf80f-223b-4721-a43e-518b152decc2,keyHash:1587335015,保存槽位为15的数据,absSlotPos=100,值index=1,绝对位置:460,commit-phyOffset:322 msgId:199053e3-e616-4611-ab0d-e5c7af4549a9,keyHash:791210473,保存槽位为73的数据,absSlotPos=332,值index=2,绝对位置:480,commit-phyOffset:628 msgId:8e799d8e-3290-4f6b-ab5d-289153446994,keyHash:1460275929,保存槽位为29的数据,absSlotPos=156,值index=3,绝对位置:500,commit-phyOffset:935 msgId:8b78474f-b28a-4442-99a0-6f7883f0302b,keyHash:1174005465,保存槽位为65的数据,absSlotPos=300,值index=4,绝对位置:520,commit-phyOffset:1274 msgId:b33c6f31-cc96-462b-b095-99410459082c,keyHash:-1695757800,保存槽位为0的数据,absSlotPos=40,值index=5,绝对位置:540,commit-phyOffset:1594 msgId:d0a6803f-8555-418e-988a-b3b9a70d14f0,keyHash:1334295408,保存槽位为8的数据,absSlotPos=72,值index=6,绝对位置:560,commit-phyOffset:1906 msgId:91151ec5-e76b-4560-90b7-ab77f9d04c9a,keyHash:1287318090,保存槽位为90的数据,absSlotPos=400,值index=7,绝对位置:580,commit-phyOffset:2230 msgId:eb21df35-b4dc-43aa-8604-e9a103f25a7b,keyHash:239865974,保存槽位为74的数据,absSlotPos=336,值index=8,绝对位置:600,commit-phyOffset:2523 msgId:abcda364-8fc3-4d18-ae5d-1d7a8ffd0929,keyHash:-1173357775,保存槽位为75的数据,absSlotPos=340,值index=9,绝对位置:620,commit-phyOffset:2846
  2.读取consumeQueue文件,并根据offset从commitLog读取一条完整的消息package org.apache.rocketmq.test.smoke;  import java.io.IOException; import java.net.URI; import java.nio.ByteBuffer; import java.nio.CharBuffer; import java.nio.MappedByteBuffer; import java.nio.channels.FileChannel; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.nio.file.Paths; import java.nio.file.StandardOpenOption;  public class ConsumeQueueMessageReadTest {     public static MappedByteBuffer mappedByteBuffer = null;     private static int MESSAGE_COUNT = 10;      public static void main(String[] args) throws IOException {         FileChannel fileChannel = FileChannel.open(Paths.get(URI.create("file:/c:/123/consumerQueue.txt")),                 StandardOpenOption.WRITE, StandardOpenOption.READ);         MappedByteBuffer mappedByteBuffer = fileChannel.map(FileChannel.MapMode.READ_WRITE, 0, 4096);         fileChannel.close();         mappedByteBuffer.position(0);         //根据索引下标读取索引,实际情况是用户消费的最新点位,存在在broker的偏移量文件中         int index = 0 ;         for(int i =index;i 0?keyHash % 100:-1*(keyHash % 100);         System.out.println("messageId:"+messageId+ ",取模为:"+slotPos);          // slot在文件中的字节数组位置         int absSlotPos = 40 + slotPos * 4;         System.out.println("哈希槽的字节数组位置:(40+"+slotPos+"*4)="+absSlotPos);           //获取hash槽上存取的件索引,第几个文件         int index =indexMappedByteBuffer.getInt(absSlotPos);          //计算数据需要存储的偏移量         int absIndexPos =                 40 + 100 * 4                         + index * 20;          System.out.println("第几个文件index="+index+",实际存储数据的字节数组位置:(40 + 100 * 4+index *20)="+absIndexPos);          long keyHash1 = indexMappedByteBuffer.getInt(absIndexPos);         long pyhOffset = indexMappedByteBuffer.getLong(absIndexPos+4);         int timeDiff = indexMappedByteBuffer.getInt(absIndexPos+4+8);         int preIndexNo = indexMappedByteBuffer.getInt(absIndexPos+4+8+4);           System.out.println("从index获取到的commitLog偏移量为:"+pyhOffset);         System.out.println("");          readCommitLogByOffset((int)pyhOffset);      }       public static MappedByteBuffer initFileChannel() throws IOException {         if(mappedByteBuffer == null){           FileChannel  commitLogfileChannel = FileChannel.open(Paths.get(URI.create("file:/c:/123/commitLog.txt")),                     StandardOpenOption.WRITE, StandardOpenOption.READ);               mappedByteBuffer = commitLogfileChannel.map(FileChannel.MapMode.READ_WRITE, 0, 409600);             commitLogfileChannel.close();         }          return mappedByteBuffer;      }       /*     *     * 根据偏移量读取CcommitLog     * */     public static void readCommitLogByOffset(int offset) throws IOException {           /* 存放顺序,读时候保持顺序一致             b.putLong(totalSize);//totalSize             b.put(getBytes(msgId, 64));//msgId             b.put(getBytes(topic, 64));//topic,定长64             b.putLong(queueOffset);//索引偏移量             b.putLong(msgBody.getBytes(StandardCharsets.UTF_8).length);//bodySize             b.put(msgBody.getBytes(StandardCharsets.UTF_8));//body             b.put(getBytes(transactionId, 64));             b.putLong(commitLogOffset);//commitLogOffset         */         System.out.println("=================commitlog读取偏移量为"+offset+"的消息===================");          MappedByteBuffer  mappedByteBuffer = initFileChannel();         mappedByteBuffer.position(offset);           long totalSize = mappedByteBuffer.getLong();//消息长度          byte[] msgIdByte = new byte[64];//uuid 固定是64         mappedByteBuffer.get(msgIdByte);          byte[] topicByte = new byte[64];// 固定是64         mappedByteBuffer.get(topicByte);         long queueOffset = mappedByteBuffer.getLong();         Long bodySize = mappedByteBuffer.getLong();         int bSize = Integer.valueOf(bodySize+"");         byte[] bodyByte = new  byte[bSize];//bodySize 长度不固定         mappedByteBuffer.get(bodyByte);         byte[] transactionIdByte = new byte[64];//uuid 固定是64         mappedByteBuffer.get(transactionIdByte);         long commitLogOffset = mappedByteBuffer.getLong();//偏移量         System.out.println("totalSize:"+totalSize);         System.out.println("msgId:"+new String(msgIdByte));         System.out.println("topic:"+new String(topicByte));         System.out.println("queueOffset:"+queueOffset);         System.out.println("bodySize:"+bodySize);         System.out.println("body:"+new String(bodyByte));         System.out.println("transactionId:"+new String(transactionIdByte));         System.out.println("commitLogOffset:"+commitLogOffset);      }        public static byte[] toByteArray(long number) {         byte length = Long.BYTES;         byte[] bytes = new byte[length];          for (byte i = 0; i < length; i++) {             bytes[length - 1 - i] = (byte) number;             number >>= 8;         }          return bytes;      }  }
  运行结果:============get indexFile header=============== beginTimestampIndex:1669554286826 endTimestampIndex:1669552196010 beginPhyoffsetIndex:0 endPhyoffsetIndex:31259 hashSlotcountIndex:10 indexCountIndex:10  messageId:8b78474f-b28a-4442-99a0-6f7883f0302b,取模为:65 哈希槽的字节数组位置:(40+65*4)=300 第几个文件index=4,实际存储数据的字节数组位置:(40 + 100 * 4+index *20)=520 从index获取到的commitLog偏移量为:1274  =================commitlog读取偏移量为1274的消息=================== totalSize:320 msgId:8b78474f-b28a-4442-99a0-6f7883f0302b                             topic:Topic-test                                                       queueOffset:4 bodySize:40 body:消息内容msgmsgmsgmsgmsgmsgmsgmsgmsgm transactionId:5c0ff6fe-aea3-40c3-8647-6f4bdd797a78                             commitLogOffset:1274
  本文基于java NIO实现了RocketMQ的文件系统的最精简的实现,希望能帮助相关开发人员了解文件系统底层的实现原理。欢迎一起交流讨论,不足的地方欢迎指正。

向日葵花开乡村美向日葵花海。买买提艾力艾尼瓦尔摄眼下,正值向日葵进入花期,在新疆和田地区洛浦县拜什托格克乡和融新村一片片盛开的向日葵花迎风绽放,金色的花海令游人流连忘返。游客在和融新村向日葵田里游夏天更要出出汗春夏秋冬是自然造化,是天道运行。春暖花开夏热流火秋叶飘零冬雪纷飞,这样的四季轮回是每个人的人生旅途上必须直面的。但现在,随着风扇空调等清凉器具不断增加,不少人就习惯于一到夏天,就躲李银河想要快乐,只需做到两件事即可网上流传了一个关于孤独的等级划分第一级一个人去逛超市。第二级一个人去快餐厅。第三级一个人去咖啡厅。第四级一个人去看电影。第五级一个人吃火锅。第六级一个人去KTV。第七级一个人去看海为什么越厉害的人,越爱下笨功夫?作者瑜琳(富书专栏作者)李敖曾说笨人的可怕之处不在其笨,而在其自作聪明。愚蠢不可怕,可怕的是自以为聪明。那些真正聪明的人,都看起来有点愚钝笨拙。他们从不过分显露自己的聪明,而是懂得西班牙淘汰芬兰挺进欧锦赛四强,西班牙堪称欧洲第一强队在今日结束的欧锦赛14决赛中,西班牙10090击败芬兰,挺进欧锦赛四强。根据数据统计,这也是他们自1999年欧锦赛以来,连续第11届进入欧锦赛四强。西班牙可以说是欧洲篮坛的首席扛把欧冠杯,那不勒斯皇马保持状态表现出色,切尔西新帅首秀值得期待欧冠杯9150045乌克超2顿涅茨克矿工凯尔特人苏超1顿涅茨克矿工在首场小组赛制造冷门,41击败了莱比锡,取得开门红,第二场小组赛的对手是实力相对较弱的凯尔特人,球队当然希望能够再AC米兰客场首胜,主场迎战萨格勒布迪纳摩,红黑军团全力出击AC米兰终于收获新赛季第一场客场胜利。意甲第6轮,AC米兰客场21战胜桑普多利亚。比赛过程跌宕起伏,红黑军团早早取得领先,但莱奥被红牌罚下之后,陷入被动。随后桑普多利亚扳平比分,关为什么李景亮被判输?郭晨冬裁判要照顾主场观众的感受正所谓希望有多大失望就有多大,嘎子哥李景亮当时兴高采烈地准备领获胜奖呢,哪知道最后裁判判定罗德里格兹获胜,那一瞬间李景亮的表情晴转多云了,一脸懵的李景亮左看看又看看,当他看到了罗德中超,武汉三镇连胜势头强大有望再下一城,梅州客家近况不俗中超91419302山东泰山武汉三镇1本场比赛是联赛冠军归属的关键战,山东泰山目前积39分,落后武汉三镇4分,因此对于山东泰山而言,要想卫冕联赛冠军,本场比赛非胜不可。武汉三镇本赛超级联赛女子组战报广东思腾2238江苏吉春9月13日1500,2022中国手球超级联赛在滁州高教科创城文体中心手球馆展开第三比赛日的争夺,江苏吉春女子手球俱乐部兵不血刃,以3822轻取广东思腾女子手球俱乐部,强势拿下联赛两晚上7点,CBA广东队更新最新18人名单,新赛季目标冲第12冠军头条创作挑战赛CBA广东队新赛季的18名球员大名单已经出炉了。新赛季除了大外援。周鹏威姆斯汤杰还有苏伟离队之后,广东队的新赛季基本没有任何的变动,马尚布鲁克斯归队,正茂周新加入广东
国企让员工自己贷款发工资,兰州的艰难不可想象企业贷款发薪常有,员工贷款给自己发薪,第一次听说。这是在玩一种很新的东西。2022年9月8日,一份兰州公交集团让员工自己贷款发工资的告知书在网上流传。发放对象是兰州公交集团有限公司由兰州的公交集团欠薪问题想到的最近的新闻有报道,兰州的公交集团出现欠薪的事件,问题在于兰州的公交集团不但是欠薪,而且出现的负债已经高达39亿元人民币,由于负债过大,所以银行已经不能够给公交公司进行商业贷款。一公刘嘉玲晒山中素颜跑步照,四肢纤细似少女,56岁的状态绝了近日,刘嘉玲在社交平台上晒出一组在山中跑步的照片,彰显了其健康的生活方式。图中刘嘉玲穿着一身紧身的运动套装,四肢都非常纤细,这样的身材很难让人看出她已经56岁了。不仅身材保持得好,明星为什么不找女友,反而去嫖?可见鹿晗才是圈内清流李姓男艺人嫖娼被通报了,有人发出灵魂拷问有钱有名有颜值,什么样的女生找不到?大大方方找个女朋友不香吗?为何非要干这种违法且丢人的勾当呢?相信这是很多人都很好奇的一个问题!其实,明星靠老婆成名的男星,张杰杜江被捧成一线,果然娶个好妻旺三代娱乐圈司空见惯的是女艺人嫁入豪门,她们不择手段地挤入上流社会,为的就是当豪门太太后退出娱乐圈享福。然而有些男艺人也选择走上这条捷径之路,不过,有的靠妻子爆火后懂得感恩,依旧与妻子甜李易峰采访时说的大实话,不介意动作戏,只要不把肚子搞大就行终于知道了为什么那么多长得帅的明星不愿意结婚的原因了,他们是想自由乱爱,他们是不想受到家庭的约束,随时更换情人而已,真是可惜了一付好皮囊,给父母亲戚朋友丢脸,自毁前程,所以说做人要离婚6年,王宝强风光无限,马蓉后悔了吗?2022年8月份,节目拿手好戏开播,人们惊喜地发现节目中竟然还有王宝强。这是一档央视的节目,身为明星能参加,足以体现他的咖位。可看到如此风光的王宝强,谁又能记得他六年前的狼狈呢?2离婚4年,再看玖月奇迹王小玮和王小海的处境,夫妻差距一目了然2009年,星光大道年度总冠军的获得者,是组合玖月奇迹,两人一个唱歌,一个弹琴,配合默契,备受观众的喜爱,获奖后,两人多次登上春晚的舞台,成为家喻户晓的歌唱组合,两人是工作上的伙伴从李易峰事件聊一聊中国娼妓史嫖娼这件事前两天又有小鲜肉塌房了,为粉丝们默哀三分钟。因多次嫖娼被抓,并供认不讳嫖娼这个词我觉得带有明显的贬义,中性点来说就是性交易,什么是性交易呢,专业点来说就是以金钱,财务为媒ampampquot被夫坑惨ampampquot董璇携1465万救不忠丈夫,离婚后撩娱圈鲜肉毫不手软明明是高云翔偷吃在前凭什么安守本分的董璇却被骂惨?2018年高云翔涉嫌性侵在澳洲被捕直接将脸面丢到国外就当众人等待董璇的离婚声明时她却在微博表示相信高云翔缺德的吃瓜群众纷纷在线接龙尝新与常新1MOREAERO强叔简评喜新厌旧,一个被广泛用于贬义的词汇。但其实细致思量一下,在你我身为消费者的这一个角度而言,喜新厌旧,不是属于我们的常态么?以我所熟悉的音频领域来看,从单元结构到振膜材质,从金属种类