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

Redis的底层实现原理

  总览
  数据结构简单,对数据操作也简单,具体方便:基于内存实现,读写速度快;Redis是单线程的,避免了不必要的上下文切换和竞争条件,也不存在多进程或者多线程导致的切换而消耗CPU,不用去考虑各种锁的问题,不存在加锁释放锁操作,没有因为可能出现死锁而导致的性能消耗;使用IO多路复用模型:Redis利用epoll来实现IO多路复用,可以处理并发的连接,将连接信息和事件放到队列中,依次放到文件事件分派器,事件分派器将事件分发给事件处理器;简单的自定义协议:rest协议(Redis客户端与Redis服务器通讯的协议)。高效的数据结构
  Redis的底层数据结构一共有六种,分别是:
  dict(字典)
  dict是一个用于维护key和value映射关系的数据结构,与很多语言中的Map或dictionary类似。Redis的一个database中所有key到value的映射,就是使用一个dict来维护的。dict本质上是为了解决算法中的查找问题(Searching)。1。一般查找问题的解法分为两个大类一个是基于各种平衡树,一个是基于哈希表,平常使用的各种Map或dictionary,大都是基于哈希表实现的。
  2。dict的算法实现dict也是一个基于哈希表的算法,跟java中的hashMap类似,dict采用某个哈希函数从key计算得到在哈希表中的位置,采用头插法解决冲突,并在装载因子(loadfactor)超过预定值时自动扩展内存,引发重哈希(rehashing)。
  dict的数据结构定义typedefstructdict{dictTypetype;直线dictType结构,dictType结构中包含自定义的函数,这些函数使得key和value能够存储任何类型的数据voidprivdata;私有数据,保存着dictType结构中函数的参数dicththt〔2〕;两张哈希表longrehashidx;rehash的标记,rehashidx1,表示没有进行rehashintitreators;正在迭代的迭代器数量}dict;
  为了能更清楚地展示dict的数据结构定义,用一张结构图来表示dict(字典)的构成。如下图:
  上图就是Redis的dict(字典)数据结构,一个dict需要注意几点:dict采用哈希函数对key取哈希值,得到在哈希表中的位置(桶的位置),再采用头插法解决hash冲突。两个哈希表(ht〔2〕):只有在重哈希的过程中,ht〔0〕和ht〔1〕才都有效。而在平常情况下,只有ht〔0〕有效,ht〔1〕里面没有任何数据。上图表示的就是重哈希进行到中间某一步时的情况。重哈希过程:跟HashMap一样,当装载因子(loadfactor)超过预定值时就会进行rehash。dict进行重hash扩容是将ht〔0〕上某一个bucket(即一个dictEntry链表)上的每一个dictEntry移动到扩容后的ht〔1〕上,更触发rehash的操作有查询、插入和删除元素。每次移动一个链表(即渐进式rehash)原因是为了防止redis长时间的堵塞导致不可用。dict添加操作:如果正在重哈希中,会把数据插入到ht〔1〕;否则插入到ht〔0〕。dict查询操作:先在第一个哈希表ht〔0〕上进行查找,再判断当前是否在重哈希,如果没有,那么在ht〔0〕上的查找结果就是最终结果。否则,再在ht〔1〕上进行查找。查询时会先根据key计算出桶的位置,在到桶里的链表上寻找key。dict删除操作:判断当前是不是在重哈希过程中,如果是只在ht〔0〕中查找要删除的key;否则ht〔0〕和ht〔1〕它都要查找删除。
  sds(简单动态字符串)
  Redis的String底层数据结构实现并没有直接使用C语言中的字符串,Redis中为了实现方便的扩展,考虑到安全和性能,自己定义了一个结构用来存储字符串,这个数据结构就是:简单动态字符串(SimpleDynamicString简称sds),并将SDS用作Redis的默认字符串。
  SDS的数据结构定义redis中保存字符串对象的结构structsdshdr{用于记录buf数组中使用的字节的数目,和SDS存储的字符串的长度相等intlen;用于记录buf数组中没有使用的字节的数目intfree;字节数组,用于储存字符串charbuf〔〕;buf的大小等于lenfree1,其中多余的1个字节是用来存储’’的};
  例如:当free0时,表示当前sds的buf〔〕没有任何未使用的数据空间,结构如下图1;free5和len5,表示带有5个未使用空间的SDS,结构如下图:
  SDS和C字符串的区别获取字符串长度
  由于C字符串没有记录自身的长度信息,所以获取C字符串长度的时候,必须遍历整个字符串,其时间复杂度是O(n),而SDS中有len属性,所以在获取其长度时,时间复杂度为O(1)。内存分配释放策略
  对于C字符串而言,不管是字符串拼接,还是字符串缩短,都要扩展底层的char数组的空间大小,再将旧char数据拷贝过来。
  SDS的内存分配策略就不一样,可以概括为预分配惰性释放。1。SDS内存分配策略:预分配
  (1)如果对SDS字符串修改后,len的值小于1MB,那么程序会分配和len同样大小的空间给free,此时len和free的值是相同。例如:如果SDS的字符串长度修改为15字节,那么会分配15字节空间给free,SDS的buf属性长度为15(len)15(free)1(空字符)31字节。
  (2)如果SDS字符串修改后,len大于等于1MB,那么程序会分配1MB的空间给free。例如:SDS字符串长度修改为50MB那么程序会分配1MB的未使用空间给free,SDS的buf属性长度为50MB(len)1MB(free)1byte(空字符)。
  2。SDS内存释放策略:惰性释放当需要缩短SDS字符串时,程序并不立刻将内存释放,而是使用free属性将这些空间记录下来,实际的buf大小不会变,以备将来使用。缓冲区溢出问题
  SDS的字符串的内存预分配策略能有效避免缓冲区溢出问题;C字符串每次操作增加长度时,都要分配足够长度的内存空间,否则就会产生缓冲区溢出(bufferoverflow)。二进制安全
  (1)C字符串的编码是ASCII编码,在字符串的末尾是以结束,也就是空字符,所以在字符串中不能包含空字符,要不然会让程序误以为结束,这也限制了C字符串只能保存文本数据,不能保存图片,音频,视频等二进制数据。
  (2)SDS以二进制存储数据的,可以存储任意数据。因此不管buf保存什么格式的数据,都是存入什么数据,读取就什么数据,二进制安全。SDS兼容部分C字符串函数
  SDS总会在buf〔〕数组分配空间时,多分配一个字节来存储空字符(’’),便于重用C中的函数。
  intset(整数集合)
  intset是Redis集合的底层实现之一,当存储整数集合并且数据量较小的情况下Redis会使用intset作为set的底层实现,当数据量较大或者集合元素为字符串时则会使用dict实现set。
  (1)intset的数据结构定义typedefstructintset{uint32tencoding;intset的类型编码uint32tlength;集合包含的元素数量int8tcontents〔〕;保存元素的数组}
  (2)inset数据集合具有以下特点:所有的元素都保存在contents数组中,且按照从小到大的顺序排列,并且不包含任何重复项。intset将整数元素按顺序存储在数组里,并通过二分法降低查找元素的时间复杂度。虽然contents数组申明成了int8t类型,但contents数组中具体存储什么类型完全取决于encoding变量的值,类似于继承。它可以保存具体类型为int16t、int32t或者int64t的整数值。
  (3)元素升级
  当新增的元素类型比原集合元素类型的长度要大时(比如:原来是int16t,现在新增一个int64t的元素),需要对整数集合进行升级,才能将新元素放入整数集合中。具体步骤:根据新元素类型,扩展整数集合底层数组的大小,并为新元素分配空间。将底层数组现有的所有元素都转成与新元素相同类型的元素,并将转换后的元素放到正确的位置,放置过程中,维持整个元素顺序都是有序的。将新元素添加到整数集合中(保证有序)
  注意:升级能极大地节省内存;整数集合不支持降级操作,一旦对数组进行了升级,编码就会一直保持升级后的状态。
  skiplist(跳表)
  skiplist查找效率很高,堪比优化过的二叉平衡树(红黑树),且比平衡树的实现简单,查找单个key,skiplist和平衡树的时间复杂度都为O(logn)。平衡树的插入和删除操作可能引发树的旋转调整,逻辑复杂,而skiplist的插入和删除只需要修改相邻节点的指针,操作简单又快速。
  skiplist首先它是一个list。实际上,它是在有序链表的基础上发展起来的。先来看一个有序链表,如下图(最左侧的灰色节点表示一个空的头结点):
  这样种链表中,如果要查找某个数据,需要从头开始逐个进行比较,直到找到等于或大于(没找到)给定数据为止,时间复杂度为O(n)。同样,当插入新数据的时候,也要经历同样的查找过程,从而确定插入位置。
  有了上面出现的问题后进一步优化,假如我们这样来设计,在每相邻两个节点增加一个指针,让指针指向下下个节点,如下图:
  这样所有新增加的指针连成了一个新的链表,但它包含的节点个数只有原来的一半(上图中是7,19,26)。现在当查找数据的时候,可以先沿着这个新链表(第一层链表)进行查找。当碰到比待查数据大的节点时,再回到第二层链表进行查找。
  比如,要查找23,查找的路径是沿着下图中标红的指针所指向的方向进行的:整个查询路线如红色箭头。
  先在第一层链表上查询,23首先和7比较,再和19比较,比它们都大,继续向后比较。但23和26比较的时候,比26要小,因此回到下面的链表(原链表),与22比较。
  再在第二层链表上查询,23比22要大,沿下面的指针继续向后和26比较。23比26小,说明待查数据23在原链表中不存在,而且它的插入位置应该在22和26之间。
  在这个查找过程中,由于新增加的指针,不再需要向原链表一样,每个节点都逐个进行比较。需要比较的节点数大概只有原来的一半。利用同样的方式,可以在上层新产生的链表上,继续为每相邻的两个节点增加一个指针,从而产生第三层链表。如下图:
  在这个新的三层链表结构上,如果还是查找23,那么沿着最上层链表首先要比较的是19,发现23比19大,接下来我们就知道只需要到19的后面去继续查找,从而一下子跳过了19前面的所有节点。可以想象,当链表足够长的时候,这种多层链表的查找方式能让我们跳过很多下层节点,大大加快查找的速度。
  skiplist正是受这种多层链表的想法的启发而设计出来的,实际上,按照上面生成链表的方式,上面每一层链表的节点个数,是下面一层的节点个数的一半,这样查找过程就非常类似于一个二分查找,使得查找的时间复杂度可以降低到O(logn)。但是,这种方法在插入数据的时候有很大的问题。新插入一个节点之后,就会打乱上下相邻两层链表上节点个数严格的2:1的对应关系。如果要维持这种对应关系,就必须把新插入的节点后面的所有节点(也包括新插入的节点)重新进行调整,这会让时间复杂度重新蜕化成O(n)。删除数据也有同样的问题。
  skiplist为了避免这一问题,它不要求上下相邻两层链表之间的节点个数有严格的对应关系,而是为每个节点随机出一个层数(level)。比如:一个节点随机出的层数是3,那么就把它链入到第1层到第3层这三层链表中。
  skiplist中一个节点的层数(level)是随机出来的,而且新插入一个节点不会影响其它节点的层数。因此,插入操作只需要修改插入节点前后的指针,而不需要对很多节点都进行调整。这就降低了插入操作的复杂度。而节点的层数(level)也不全是没有规则随机的,而是按照节点平均指针数目计算出来的。如下图各个节点层数(level)是随机出来的一个skiplist,我们依然查找23,查找路径如图:
  skiplist与平衡树、哈希表的比较skiplist和各种平衡树(如AVL、红黑树等)的元素是有序排列的,而哈希表不是有序的。因此,在哈希表上只能做单个key的查找,不适宜做范围查找。平衡树的插入和删除操作可能引发树的旋转调整,逻辑复杂,而skiplist的插入和删除只需要修改相邻节点的指针,操作简单又快速。查找单个key,skiplist和平衡树的时间复杂度都为O(logn),大体相当;而哈希表在保持较低的哈希值冲突概率的前提下,查找时间复杂度接近O(1),性能更高一些。从内存占用上来说,skiplist比平衡树更灵活一些。平衡树一般每个节点包含2个指针,而skiplist每个节点包含的指针数目平均为1(1p),具体取决于一个概率参数p。如果像Redis里的实现一样,取p14,那么平均每个节点包含1。33个指针,比平衡树更有优势。
  ziplist(压缩表)
  ziplist是一个经过特殊编码的双向链表,它的设计目标就是为了提高存储效率。ziplist可以用于存储字符串或整数,其中整数是按真正的二进制表示进行编码的,而不是编码成字符串序列。
  Redis对外暴露的hash数据类型,在field比较少,各个value值也比较小的时候,hash采用ziplist来实现;而随着field增多和value值增大,hash可能会变成dict来实现。当hash底层变成dict来实现的时候,它的存储效率就没法跟那些序列化方式相比了。ziplist的数据结构
  ziplist在内存中的结构大致如下:。。。
  1。结构说明:
  (1)zlbytes:表示整个ziplist占用的字节总数。
  (2)zltail:表示ziplist表中最后一项(entry)在ziplist中的偏移字节数。
  (3)zllen:16bit,表示ziplist中数据项(entry)的个数。当ziplist里数据大于2161后,再获取元素个数时,ziplist从头到尾遍历。
  (4)entry:表示真正存放数据的数据项,长度不定,采用变长编码(对于大的数据,就多用一些字节来存储,而对于小的数据,就少用一些字节来存储)。
  (5)zlend:ziplist最后1个字节,是一个结束标记,值固定等于255。
  2。entry的内部结构:
  (1)prevrawlen:表示前一个数据项占用的总字节数。作用是为了让ziplist能够从后向前遍历(从后一项的位置,只需向前偏移prevrawlen个字节,就找到了前一项),这个字段采用变长编码。
  (2)len:表示当前数据项的数据长度(即部分的长度)。也采用变长编码。
  (3)data:存储的数据。blockquote
  注意:ziplist虽然是个特殊编码的双向链表,但为了提高存储效率,内存地址空间是连续的,更像是一个list,只是比list多了一个链表的首尾操作而已。ziplist(压缩表)的特点
  (1)内存空间连续:ziplist为了提高存储效率,从存储结构上看ziplist更像是一个表(list),但不是一个链表(linkedlist)。ziplist将每一项数据存放在前后连续的地址空间内,一个ziplist整体占用一大块内存。而普通的双向链表每一项都占用独立的一块内存,各项之间用指针连接,这样会带来大量内存碎片,而且指针也会占用额外内存。
  (2)查询元素:查找指定的数据项就会性能变得很低,需要进行遍历整个zipList。
  (3)插入和修改:每次插入或修改引发的重新分配内存(realloc)操作会有更大的概率造成内存拷贝,从而降低性能。跟list一样,一旦发生内存拷贝,内存拷贝的成本也相应增加,因为要拷贝更大的一块数据。
  ziplist提高了存储效率,是内存紧缩的列表,多个数据在一起的连续空间,不擅长修改,在两端pop,push快。hash为什么要转为dict
  (1)ziplist的数据发生改动(插入或修改),会引发内存realloc(内存重新分配),可能导致内存拷贝。
  (2)ziplist里查找数据时需要进行遍历(跟双向链表一样),数据项过多会变慢。
  总之,ziplist本来就设计为各个数据项挨在一起组成连续的内存空间,虽然高存储效率高了,但这种结构并不擅长做修改操作。一旦数据发生改动,就会引发内存realloc,可能导致内存拷贝。
  quicklist(快速列表)
  Redis对外暴露的list数据类型,它底层实现所依赖的内部数据结构就是quicklist。先来看看Redis对外暴露的list数据类型操作特点:1。Redis对外暴露的上层list数据类型,它支持的一些修改操作如下:
  (1)lpush:在左侧(即列表头部)插入数据。
  (2)rpop:在右侧(即列表尾部)删除数据。
  (3)rpush:在右侧(即列表尾部)插入数据。
  (4)lpop:在左侧(即列表头部)删除数据。
  2。list也支持在任意中间位置的存取操作,比如lindex和linsert,但它们都需要对list进行遍历,所以时间复杂度较高,为O(N)。
  3。list具有的特点:list的内部实现quicklist正是一个双向链表。它是一个能维持数据项先后顺序的列表(各个数据项的先后顺序由插入位置决定),便于在表的两端追加和删除数据,而对于中间位置的存取具有O(N)的时间复杂度。这正是一个双向链表所具有的特点。
  quicklist(快速表)的结构
  quicklist确实是一个双向链表,而且是一个ziplist的双向链表。即quicklist双向链表是由多个节点(Node)组成,而quicklist的每个节点又是一个ziplist。结构如下图:
  quicklist的结构为什么这样设计呢?总结起来,大概又是一个空间和时间的折中:
  双向链表便于在表的进行插入和删除节点操作,但是它的内存开销比较大。首先,它在每个节点上除了要保存数据之外,还要额外保存两个指针;其次,双向链表的各个节点是单独的内存块,地址不连续,节点多了容易产生内存碎片。
  ziplist由于是一整块连续内存,所以存储效率很高。但是,它不利于修改操作,每次数据变动都会引发一次内存的内存重新分配(realloc)。特别是当ziplist长度很长的时候,一次realloc可能会导致大批量的数据拷贝,进一步降低性能。
  可见,一个quicklist节点上的ziplist要保持一个合理的长度。那到底多长合理呢?这可能取决于具体应用场景。实际上,Redis提供了一个配置参数listmaxziplistsize,就是为了让使用者可以来根据自己的情况进行调整。
  可以取正值,也可以取负值
  listmaxziplistsize2
  当取正值的时候,表示按照数据项个数来限定每个quicklist节点上的ziplist长度。比如,当这个参数配置成5的时候,表示每个quicklist节点的ziplist最多包含5个数据项。
  当取负值的时候,表示按照占用字节数来限定每个quicklist节点上的ziplist长度。这时,它只能取1到5这五个值。每个值得含义如下
  每个值含义如下:5:每个quicklist节点上的ziplist大小不能超过64Kb。(注:1kb1024bytes)
  4:每个quicklist节点上的ziplist大小不能超过32Kb。
  3:每个quicklist节点上的ziplist大小不能超过16Kb。
  2:每个quicklist节点上的ziplist大小不能超过8Kb。(2是Redis给出的默认值)
  1:每个quicklist节点上的ziplist大小不能超过4Kb。
  另外,list的设计目标是能够用来存储很长的数据列表的。当列表很长的时候,最容易被访问的很可能是两端的数据,中间的数据被访问的频率比较低(访问起来性能也很低)。如果应用场景符合这个特点,那么list还提供了一个选项,能够把中间的数据节点进行压缩,从而进一步节省内存空间。Redis的配置参数listcompressdepth就是用来完成这个设置的。这个参数表示一个quicklist两端不被压缩的节点个数。参数表示一个quicklist两端不被压缩的节点个数listcompressdepth0
  参数listcompressdepth的取值含义如下:
  0:是个特殊值,表示都不压缩。这是Redis的默认值。
  1:表示quicklist两端各有1个节点不压缩,中间的节点压缩。
  2:表示quicklist两端各有2个节点不压缩,中间的节点压缩。
  3:表示quicklist两端各有3个节点不压缩,中间的节点压缩。
  依此类推
  注:这里的节点个数是指quicklist双向链表的节点个数,而不是指ziplist里面的数据项个数。实际上,如果一个quicklist节点如果被压缩,那么ziplist就是整体被压缩了。
  总结:quicklist将双向链表插入和修改元素不需要移动节点的优点和ziplist的存储效率很高优点(一整块连续内存)结合在一起,同时将各自的缺点进行一个折中的处理。所以没有完美的数据结构,只有更合适业务的设置。基于内存
  内存直接由CPU控制,也就是CPU内部集成的内存控制器,所以说内存是直接与CPU对接,享受与CPU通信的最优带宽。
  Redis将数据存储在内存中,读写操作不会因为磁盘的IO速度限制。
  CPU不是Redis的瓶颈,Redis的瓶颈最有可能是机器内存的大小或者网络带宽。
  在计算机的世界中,CPU的速度是远大于内存的速度的,同时内存的速度也是远大于硬盘的速度。Redis的操作都是基于内存的,绝大部分请求是纯粹的内存操作,非常迅速。
  单线程
  Redis是单线程的,避免了不必要的上下文切换和竞争条件,也不存在多进程或者多线程导致的切换而消耗CPU,不用去考虑各种锁的问题,不存在加锁释放锁操作,没有因为可能出现死锁而导致的性能消耗。
  Redis的单线程主要是指Redis的网络IO和键值对读写是由一个线程来完成的,即一个线程处理所有网络请求,这也是Redis对外提供键值存储服务的主要流程。但Redis的其他功能,比如持久化、异步删除、集群数据同步等,其实是由额外的线程执行的。IO多路复用程序
  Redis利用epoll来实现IO多路复用,可以处理并发的连接,将连接信息和事件放到队列中,依次放到文件事件分派器,事件分派器将事件分发给事件处理器。
  非阻塞IO内部实现采用epoll,采用了epoll自己实现的简单的事件框架。epoll中的读、写、关闭、连接都转化成了事件,然后利用epoll的多路复用特性,绝不在IO上浪费一点时间。Redis的自定义协议
  Redis客户端使用RESP(Redis的序列化协议)协议与Redis的服务器端进行通信。它实现简单,解析快速并且人类可读。
  RESP支持以下数据类型:简单字符串、错误、整数、批量字符串和数组。
  RESP在Redis中用作请求响应协议的方式如下:
  客户端将命令作为批量字符串的RESP数组发送到Redis服务器。
  服务器根据命令实现以其中一种RESP类型进行回复。
  在RESP中,某些数据的类型取决于第一个字节:
  对于简单字符串,回复的第一个字节是
  对于错误,回复的第一个字节是
  对于整数,回复的第一个字节是:
  对于批量字符串,回复的第一个字节是
  对于数组,回复的第一个字节是
  此外,RESP能够使用稍后指定的批量字符串或数组的特殊变体来表示Null值。在RESP中,协议的不同部分总是以r(CRLF)终止。Redis的一些常见问题
  为什么不采用多进程或多线程处理?
  多线程处理可能涉及到锁。
  多线程处理会涉及到线程切换而消耗CPU。
  单线程处理的缺点?
  耗时的命令会导致并发的下降,不只是读并发,写并发也会下降。
  如:keys全量遍历键,用来列出所有满足特定正则字符串规则的key,当redis数据量比较大时,性能比较差,要避免使用,无法发挥多核CPU性能,不过可以通过在单机开多个Redis实例来完善。
  Redis不存在线程安全问题?
  Redis采用了线程封闭的方式,把任务封闭在一个线程,自然避免了线程安全问题,不过对于需要依赖多个Redis操作(即多个Redis操作命令)的复合操作来说,依然需要锁,而且有可能是分布式锁。
  高性能的服务器一定是多线程的?多线程一定比单线程效率高?
  Redis将所有的数据全部放在内存中,使用单线程去操作效率比较高,对于多线程,CPU会有上下文切换,这种操作耗时,对于内存系统来说,没有上下文切换,效率相对是高的。
  Redis使用单进程的模式来处理客户端的请求,对大部分事件的响应都是通过epoll函数的加强封装,Redis的实际处理速度依靠主进程的执行效率,epoll可以显著提高程序在大量并发连接中系统的CPU利用率。

刘亦菲学历风波越演越烈,北电官微关闭评论,网友开始实名举报万万没想到,随着梦华录火热播出,有关刘亦菲的学历年龄再次成为网友关注的点,而此次掀起舆论争议后,事件愈演愈烈,北电官微沦陷后设置关闭了评论,网友又开始实名举报。在这个瓜热度逐渐上升霍启刚一家五口庆祝父亲节!吃黄标牛排,三个儿女同框制作土豆泥再有不到半个月的时间,霍启刚将正式开启另外一段人生,所以趁着这段时间,他要好好享受家庭的乐趣。恰逢父亲节,霍启刚便返回家中,与三个儿女以及妻子郭晶晶一同度过。6月19号,霍启刚于社极限挑战第八季发布全家福海报,两人退出,王迅终于站上C位极限挑战作为如今的国民综艺之一,本来也是唯一可以跟跑男相抗衡的上星节目,但是,随着严敏导演在第四季之后的离职,导致男人帮时期的嘉宾们先后退出,尽管如此,凭借曾经他们打下的基础,这档刘德华庆AWC成立34周年,总结一年电影计划,3部杀青1部在拍6月18日,天王巨星刘德华再次公开直播。自入驻某视频平台以来,刘天王开过几次直播,观众人数都在千万级。这次直播意义非凡,是为庆祝AWC成立34周年举办的小型歌友会。AWC是Andy唐山被打女孩伤情曝光,同时也有6个疑点和6个疑问唐山被群殴受伤的4名女子,为何好像是凭空消失了一样,一定要看到文章后面,文章虽短,但字字珠玑。唐山这打人事件,已经过几天了,没有半点信息透露出来。目前大家只知道。唐山两名被群殴的女80天肿瘤消失,国产质子治疗临床试验成功,未来普通人也能用得起太痛苦了。耗费将近千万,李宗伟抗癌成功,但是谈起患癌之后的感受,他首先形容的就是痛苦。2018年9月,羽坛名将李宗伟查出了早期的鼻咽癌,为了获得更好的治疗效果回归赛场,他使用了世界iOS15。6b3是今年最好的系统?iPhoneXSM升级后续航有点无敌,必升iOS15。6已经进入到了第3个测试版了,目前系统逐渐趋于完美了,对比iOS15。5正式版来说,在续航流畅度信号方面都有了明显的进步了,对比更早的iOS14系统来说,各方面更是可以河南银保监局河南省地方金融监管局个别村镇银行线上交易系统被河南新财富集团操控和利用的犯罪事实已初步查明欧阳剑环中国证券报中证网中证网讯(记者欧阳剑环)针对近期个别村镇银行线上服务渠道关闭问题,河南银保监局河南省地方金融监管局有关负责人6月18日表示,各级金融管理部门密切配合公安机关超人霸王龙蜘蛛侠打唐山的坏蛋在唐山的晚上,几个坏蛋突然发疯打女人,这时有人呼叫超人来帮忙打那几个坏人,超人来了他带着霸王龙和蜘蛛侠来了,霸王龙一看那坏蛋就咬起来下嘴了,他说好吃好吃,蜘蛛侠也吃了一个坏蛋,也说孟晚舟朋友圈发文挺姚安娜,她们在各自的领域优秀着近日,孟晚舟在朋友圈发文鼓励姚安娜,从小到大,不常夸你努力,却时常被你惊喜。从来不是第一个祝贺你,不过,美好总能慢慢沉淀,芳华总会静静开启人生充满种种可能,那就慨然以赴吧!孟晚舟的直播画面出现违规物品?半只狐狸1000万粉丝账号,遭平台封禁近期关注短视频平台的网友,对半只狐狸这个昵称一定不会陌生。半只狐狸之所以能在互联网上爆火,就是因为他的视频和直播中所呈现出来的内容,是我们这些普通人很难接触和了解到的东西。比如直播
刘亦菲干爹陈金飞疑似离婚,不再捧场杨采钰,转而与昔日情人合作去年梦华录大火之后,有网友曝光称女主刘亦菲在之后可能要受到自己干爹陈金飞的力捧,最令人震惊的是,爆料还称他现在已经和杨采钰私下离婚。这件事情在当时引起了很高的热度,不少人都说是因为被誉为英伦玫瑰的她,却曾因微胖遭受霸凌近日,由导演詹姆斯卡梅隆执导的阿凡达水之道(AvatarTheWayofWater)毫无疑问成为了全球影迷们的话题中心,前不久更是拿下了2022年度单片全球票房的年度冠军,成绩可以13号星期五杀手谜题即将下架停止销售前8章免费游玩今天(2023年1月13日),13号星期五杀手谜题开发商在Steam发布新博文表示,由于他们无法与许可方续签许可协议,所以被要求在本月晚些时候结束游戏的销售工作,已购买游戏的玩家不12月出海榜PUBGMobile累收近255亿IM30三款SLG冲入TOP151月13日,SensorTower公布了去年12月中国手游产品在海外市场收入及下载量排行榜,详细榜单变化如下。0112月出海手游收入榜在世界杯ArcticWolfCompanion小骨,你我皆是英雄游戏新春创作纪这两年出了很多好玩的像素风游戏,开发成本低,游戏内容丰富,我最近就痴迷上了一款像素风的横版过关肉鸽游戏小骨英雄杀手这款游戏里我们将扮演一个弱小的小骨头,他的技能是把自这家成都游戏公司做起了抗衰老饮料,下一个元气森林?tap4fun筹划进军饮料界至少有一年时间了。许多从业者对这家成都公司的印象,还停留在早年中国本土游戏公司出海的成功典范。它曾于20122014年连续入选AppAnnie全球52家觅长生公布未来更新计划澄清手游觅仙途修仙开放世界RPG觅长生与1月13日脱离了抢先体验,正式在Steam上发售,开发者在发布了一篇博文对发售后的更新计划作出了解释。觅长生开发者表示正式版发售后他们仍会继续保持更新,在死亡空间重制版总监称原版主角不说话不合实际死亡空间重制版即将发售,本作执行总监JoelMacMillan在InsideDeadSpace的播客节目中表示,他认为死亡空间原版主角不说话有些不合实际。如果你玩过死亡空间原版,就原神阿凡的任务,一次几十原石,每天都能过来拿原石,还有成就前排提示任务里的隔天明天是任务触发时间,不是我们隔天明天一定要上线做,不会有不上线就需要我们重新开始或者完不成任务这种情况,这不是连续强制上线完成的任务。先到阿如村找流放者赛芭领取望梅止渴,吃梅滋阴,推荐2款乌梅食方,润燥养肺有一个大家都很熟悉的典故望梅止渴。说的是三国时期,曹操有一次带大军出征,时间是在夏天,路途上天气炎热,士兵喝完带的水,又找不到水源,口渴难耐,士气严重受到影响,曹操便想出一个办法,长寿是抠出来的!3个抠门习惯,让你活得比同龄人更久在生活中,被人家说抠,通常都不是件让人愉快的事。但你知道吗?如果抠对了地方,对健康是非常有益的,甚至还能让人活得比同龄人更久。具体要怎么个抠法呢?咱们接着往下看这3个抠门习惯,坚持
友情链接:快好找快生活快百科快传网中准网文好找聚热点快软网