• 首页
  • 国产小呦泬泬99精品
  • 最近2019中文字幕在线高清
  • 免费看少妇作爱视频
  • 曰批全过程免费视频在线观看网站
  • 国色天香在线观看全集免费播放
  • 婆岳同床双飞呻吟
  • 最近2019中文字幕在线高清你的位置:三级小说 > 最近2019中文字幕在线高清 > 一文弄懂Redis为什么这样快?

    一文弄懂Redis为什么这样快?

    发布日期:2022-06-18 17:11    点击次数:95

    一文弄懂Redis为什么这样快?

    序言

    提及现时主流NoSql数据库非 Redis 莫属。因为它读写速率极快,一般用于缓存热门数据加速查询速率,全球在责任内部也战胜和 Redis 打过交道,但是对于Redis 为什么快,除了对八股文的背诵,好像都还没独特真切的了解。

    今天咱们沿途真切的了解下redis吧:

    高效的数据结构

    Redis 的底层数据结构一共有6种,分离是,简易动态字符串,双向链表,压缩列表,哈希表,跳表和整数数组,它们和数据类型的对应干系如下图所示:

    本文暂时按下不表,后续会针对以上所稀有据结构进行源码级真切分析

    单线程vs多线程

    多线程VS单线程

    在学习策画机操作系统时一定际遇过这个问题:多线程一定比单线程快吗? 信托诸位看官们一定不会像上头的傻哪吒一样落入敖丙的圈套中。

    多线程偶然候如实比单线程快,但也有好多时候莫得单线程那么快。最初用一张3岁小孩都能看懂的图讲明并发与并行的区别:

    并发(concurrency):指在吞并时代只可有一条辅导实施,但多个进程辅导被快速的轮流实施,使得在宏观上具有多个进程同期实施的收尾,但在微观上并不是同期实施的,只是把时辰分红多少段,使多个进程快速交替的实施。 并行(parallel):指在吞并时代,有多条辅导在多个处理器上同期实施。是以不管从微观仍是从宏观来看,二者都是沿途实施的。

    不难发现并发在吞并时代唯唯一条辅导实施,只不外进程(线程)在CPU中快速切换,速率极快,给人看起来便是“同期运行”的印象,履行上吞并时代唯唯一条辅导进行。但履行上若是咱们在一个应用要领中使用了多线程,线程之间的轮流以及高下文切换是需要破耗好多时辰的。

    何同学

    Talk is cheap,Show me the code

    如下代码演示了串行和并发实施并累加操作的时辰:

    public class ConcurrencyTest {     private static final long count = 1000000000;      public static void main(String[] args) {         try {             concurrency();         } catch (InterruptedException e) {             e.printStackTrace();         }         serial();     }      private static void concurrency() throws InterruptedException {         long start = System.currentTimeMillis();         Thread thread = new Thread(new Runnable() {              @Override             public void run() {                  int a = 0;                  for (long i = 0; i < count; i++)                  {                      a += 5;                  }             }         });         thread.start();         int b = 0;         for (long i = 0; i < count; i++) {             b--;         }         thread.join();         long time = System.currentTimeMillis() - start;         System.out.println("concurrency : " + time + "ms,b=" + b);     }      private static void serial() {         long start = System.currentTimeMillis();         int a = 0;         for (long i = 0; i < count; i++)         {             a += 5;         }         int b = 0;         for (long i = 0; i < count; i++) {             b--;         }         long time = System.currentTimeMillis() - start;         System.out.println("serial : " + time + "ms,b=" + b);     }  } 

    实施时辰如下表所示,不难发现,当并发实施累加操作不跳跃百万次时,速率会比串行实施累加操作要慢。

    由于线程有创建和高下文切换的支拨,导致并发实施的速率会比串行慢的情况出现。

    高下文切换

    多个线程不错实施在单核或多核CPU上,单核CPU也复旧多线程实施代码,CPU通过给每个线程分配CPU时辰片(契机)来结束这个机制。CPU为了实施多个线程,就需要不断的切换实施的线程,这样才智保证通盘的线程在一段时辰内都有被实施的契机。

    此时,CPU分配给每个线程的实施时辰段,称作它的时辰片。CPU时辰片一般为几十毫秒。CPU通落伍辰片分配算法来轮回实施任务,现时任求实施一个时辰片后切换到下一个任务。

    但是,在切换前会保存上一个任务的景色,以便下次切换回这个任务时,不错再加载这个任务的景色。是以任务从保存到再加载的过程便是一次高下文切换。

    凭证多线程的运奇迹态来证明:多线程环境中,当一个线程的景色由Runnable诊治为非Runnable(Blocked、Waiting、Timed_Waiting)时,相应线程的高下文信息(包括CPU的寄存器和要领计数器在某一时辰点的内容等)需要被保存,以便相应线程稍后再次参加Runnable景色时大约在之前的实施进程的基础上接续前进。而一个线程从非Runnable景色参加Runnable景色可能触及复原之前保存的高下文信息。这个对线程的高下文进行保存和复原的过程就被称为高下文切换。

    基于内存

    以MySQL为例,MySQL的数据和索引都是永久化保存在磁盘上的,因此当咱们使用SQL语句实施一条查询号令时,若是指标数据库的索引还没被加载到内存中,那么最初要先把索引加载到内存,再通过多少寻址定位和磁盘I/O,把数据对应的磁盘块加载到内存中,临了再读取数据。

    若是是机械硬盘,那么最初需要找到数据场所的位置,即需要读取的磁盘地址。不错望望这张暗示图:

    磁盘结构暗示图

    读取硬盘上的数据,第一步便是找到所需的磁道,磁道便是以中间轴为圆心的圆环,最初咱们需要找到所需要瞄准的磁道,并将磁头移动到对应的磁道上,这个过程叫做寻道。

    然后,咱们需要比及磁盘动掸,让磁头指向咱们需要读取的数据脱手的位置,这里消耗的时辰称为旋转延长,平时咱们说的硬盘转速快慢,主要影响的便是消耗在这里的时辰,而且这个动掸的标的是单向的,若是错过了数据的开头位置,就必须比及盘片旋转到下一圈的时候才智脱手读。

    临了,磁头脱手读取纪录着磁盘上的数据,这个旨趣其实与光盘的读取旨趣雷同,由于磁道上有一层磁性介质,当磁头扫过特定的位置,磁头感应不同位置的磁性景色就不错将磁信号诊治为电信号。

    不错看到,不管是磁头的移动仍是磁盘的动掸,实质上其实都是机械畅通,这亦然为什么这种硬盘被称为机械硬盘,而机械畅通的服从便是磁盘读写的瓶颈。

    扯得有点远了,咱们说回redis,若是像Redis这样把数据存在内存中,读写都胜利对数据库进行操作,自然地就比硬盘数据库少了到磁盘读取数据的这一步,而这一步恰正是策画机处理I/O的瓶颈场所。

    在内存中读取数据,实质上是电信号的传递,比机械畅通传递信号要快得多。

    硬盘数据库读取历程

     

     

    内存数据库读取历程

    因此,不错负累赘地说,Redis这样快诚然跟它基于内存运行有着很大的干系。但是,这还远远不是全部的原因。

    Redis FAQ

    濒临单线程的 Redis 你也许又会有疑问:敖丙,我的多核CPU发达不了作用了呀!别急,Redis 针对这个问题有利进行了解答。

     

    CPU成为Redis性能瓶颈的情况并不常见,因为Redis闲居会受到内存或网络的收尾。举例,在 Linux 系统上使用活水线 Redis 每秒以至不错提供 100 万个苦求,是以若是你的应用要领主要使用O(N)或O(log(N))号令,它险些不会占用太多的CPU。

    但是,为了最大化CPU应用率,你不错在吞并个节点中启动多个Redis实例,并将它们视为不同的Redis处事。在某些情况下,一个单独的节点可能是不够的,是以若是你想使用多个cpu,你不错脱手接洽一些更早的分片门径。

    你不错在Partitioning页面中找到更多对于使用多个Redis实例的信息。

    但是,在Redis 4.0中,咱们脱手让Redis愈加线程化。现在这仅限于在后台删除对象,以及遏止通过Redis模块结束的号令。对于明天的版块, 天天爽夜夜爽夜夜爽精品视频咱们的霸术是让Redis变得越来越多线程。

    防卫:咱们一直说的 Redis 单线程,只是在处理咱们的网络苦求的时候唯唯一个线程来处理,一个精采的Redis Server运行的时候战胜是不啻一个线程的!

    举例Redis进行永久化的时候会 fork了一个子进程 实施永久化操作

    四种IO模子

    当一个网络IO发生(假定是read)时,它会触及两个系统对象,一个是调用这个IO的进程,另一个是系统内核。

    当一个read操作发生时,它会履历两个阶段:

    ①恭候数据准备;

    ②将数据从内核拷贝到进程中。

    为了惩处网络IO中的问题,建议了4中网络IO模子:

    遏止IO模子 非遏止IO模子 多路复用IO模子 异步IO模子

    遏止和非遏止的主意描述的是用户线程调用内核IO操作的样子:遏止时指IO操作需要透顶完成后才复返到用户空间;而非遏止是指IO操作被调用后立即复返给用户一个景色值,不需要比及IO操作透顶完成。

    遏止IO模子

    在Linux中,默许情况下通盘socket都是遏止的,一个典型的读操作如下图所示:

    当应用进程调用了recvfrom这个系统调用后,系统内核就脱手了IO的第一个阶段:准备数据。

    对于网络IO来说,好多时候数据在一脱手还没到达时(比如还莫得收到一个完竣的TCP包),系统内核就要恭候富饶的数据到来。而在用户进程这边,通盘这个词进程会被遏止。

    当系统内核一直比及数据准备好了,它就会将数据从系统内核中拷贝到用户内存中,然后系统内核复返收尾,用户进程才根除遏止的景色,重新运行起来。是以,遏止IO模子的特色便是在IO实施的两个阶段(恭候数据和拷贝数据)都被遏止了。

    非遏止IO模子

    在Linux中,不错通过成就socket使IO变为非遏止景色。当对一个非遏止的socket实施read操作时,读操作历程如下图所示:

    从图中不错看出,当用户进程发出 read 操作时,若是内核中的数据还莫得准备好,那么它不会遏止用户进程,而是坐窝复返一个诞妄。

    从用户进程角度讲,它发起一个read操作后,并不需要恭候,而是立时就获取了一个收尾。当用户进程判断收尾是一个诞妄时,它就骄横数据还莫得准备好,于是它不错再次发送read操作。

    一朝内核中的数据准备好了,况兼又再次收到了用户进程的系统调用,那么它立时就将数据复制到了用户内存中,然后复返正确的复返值。

    是以,在非遏止式IO中,用户进程其实需要继续田主动盘问kernel数据是否准备好。非遏止的接口比较遏止型接口的显赫相反在于被调用之后立即复返。

    多路复用IO模子

    多路IO复用,偶然也称为事件驱动IO(Reactor瞎想模式)。它的基承诺趣便是有个函数会继续地轮询所负责的通盘socket,当某个socket稀有据到达了,就见告用户进程,多路IO复用模子的历程如图所示:

    当用户进程调用了select,那么通盘这个词进程会被遏止,而同期,内核会"监视"通盘select负责的socket,当任何一个socket中的数据准备好了,select就会复返。这个时候用户进程再调用read操作,将数据从内核拷贝到用户进程。

    这个模子和遏止IO的模子其实并莫得太大的不同,事实上还更差一些。因为这里需要使用两个系统调用(select和recvfrom),而遏止IO只调用了一个系统调用(recvfrom)。但是,用select的上风在于它不错同期处理多个贯穿。是以,若是系统的贯穿数不是很高的话,使用select/epoll的web server不一定比使用多线程的遏止IO的web server性能更好,最近2019中文字幕在线高清可能延长还更大;select/epoll的上风并不是对单个贯穿能处理得更快,而是在于能处理更多的贯穿。

    若是select()发现某句柄捕捉到了"可读事件",处事器要领应实时做recv()操作,并凭证接收到的数据准备好待发送数据,并将对应的句柄值加入writefds,准备下一次的"可写事件"的select()检测。通常,若是select()发现某句柄捕捉到"可写事件",则要领应实时做send()操作,并准备好下一次的"可读事件"检测准备。

    如下图展示了基于事件驱动的责任模子,当不同的事件产生时handler将感应到并实施相应的事件,像一个多路开关似的。

    IO多路复用是最常使用的IO模子,但是其异步程度还不够“透顶”,因为它使用了会遏止线程的select系统调用。因此IO多路复用只可称为异步遏止IO,而非简直的异步IO。

    异步IO模子

    “简直”的异步IO需要操作系统更强的复旧。如下展示了异步 IO 模子的运行历程(Proactor瞎想模式):

    用户进程发起read操作之后,坐窝就不错脱手去做其他的事;而另一方面,从内核的角度,当它收到一个异步的read苦求操作之后,最初会坐窝复返,是以不会对用户进程产生任何遏止。

    然后,内核会恭候数据准备完成,然后将数据拷贝到用户内存中,当这一切都完成之后,内核会给用户进程发送一个信号,复返read操作已完成的信息。

    IO模子记忆

    调用遏止IO会一直遏止住对应的进程直到操作完成,而非遏止IO在内核还在准备数据的情况下会坐窝复返。

    两者的区别就在于同步IO进行IO操作时会遏止进程。按照这个界说,之前所述的遏止IO、非遏止IO及多路IO复用都属于同步IO。履行上,真实的IO操作,便是例子中的recvfrom这个系统调用。

    非遏止IO在实施recvfrom这个系统调用的时候,若是内核的数据莫得准备好,这时候不会遏止进程。但是当内核中数据准备好时,recvfrom会将数据从内核拷贝到用户内存中,这个时候进程则被遏止。

    而异步IO则不一样,当进程发起IO操作之后,就胜利复返,直到内核发送一个信号,告诉进程IO已完成,则在这通盘这个词过程中,进程总共莫得被遏止。

    各个IO模子的比较如下图所示:

    Redis中的应用

    Redis处事器是一个事件驱动要领,处事器需要处理以下两类事件:

    文献事件:Redis处事端通过套接字与客户端(或其他Redis处事器)进行贯穿,而文献事件便是处事器对套接字操作的玄虚。处事器与客户端(或者其他处事器)的通讯会产生相应的文献事件,而处事器则通过监听并处理这些事件来完成一系列网络通讯操作。 时辰事件:Redis处事器中的一些操作(如serverCron)函数需要在给定的时辰点实施,而时辰事件便是处事器对这类定时操作的玄虚。 I/O多路复用要领

    Redis的 I/O 多路复用要领的通盘功能都是通过包装常见的select、epoll、evport、kqueue这些多路复用函数库来结束的。

    因为Redis 为每个 I/O 多路复用函数库都结束了交流的API,是以I/O多路复用要领的底层结束是不错互换的。

    Redis 在 I/O 多路复用要领的结束源码顶用 #include 宏界说了相应的规章,要相识在编译时自动遴荐系统中性能最高的 I/O 多路复用函数库来四肢 Redis 的 I/O 多路复用要领的底层结束(ae.c文献):

    /* Include the best multiplexing layer supported by this system.  * The following should be ordered by performances, descending. */ #ifdef HAVE_EVPORT #include "ae_evport.c" #else     #ifdef HAVE_EPOLL     #include "ae_epoll.c"     #else         #ifdef HAVE_KQUEUE         #include "ae_kqueue.c"         #else         #include "ae_select.c"         #endif     #endif #endif 
    文献事件处理器

    Redis基于 Reactor 模式劝诱了我方的网络事件处理器:这个处理器被称为文献事件处理器:

    文献事件处理器使用 I/O 多路复用要领来同期监听多个套接字,并凭证套接字现在实施的任务来为套接字接洽不同的事件处理器。 当被监听的套接字准备好实施贯穿搪塞(accept)、读取(read)、写入(write)、关闭(close)等操作时,与操作相对应的文献事件就会产生,这时文献事件处理器就会调用套接字之前接洽好的事件处理器来处理这些事件。

    下图展示了文献事件处理器的四个构成部分:套接字、I/O多路复用要领、文献事件分配器(dispatcher)、事件处理器。

    文献事件是对套接字操作的玄虚,每当一个套接字准备好实施贯穿搪塞、写入、读取、关闭等操作时,就会产生一个文献事件。因为一个处事器闲居会贯穿多个套接字,是以多个文献事件有可能会并发地出现。I/O 多路复用要领负责监听多个套接字,并向文献事件分配器传送那些产生了事件的套接字。

    哪吒问的问题很棒,空想一下,生存中一群人去食堂打饭,大姨说的最多的一句话便是:列队啦!列队啦!一个都不会少!

    没错,一切来源生存!Redis 的 I/O多路复用要领老是会将通盘产滋事件的套接字都放到一个部队内部,然后通过这个部队,以有序、同步、每次一个套接字的样子向文献事件分配器传送套接字。当上一个套接字产生的事件被处理完毕之后,I/O 多路复用要领才会接续向文献事件分配器传送下一个套接字。

    Redis为文献事件处理器编写了多个处理器,这些事件处理器分离用于结束不同的网络通讯需求:

    为了对贯穿处事器的各个客户端进行搪塞,处事器要为监听套接字接洽贯穿搪塞处理器; 为了收受客户端传来的号令苦求,处事器要为客户端套接字接洽号令苦求处理器 ; 为了向客户端复返号令的实施收尾,处事器要为客户端套接字接洽号令回报处理器 ; 当左右事器和从处事器进行复制操作时,主从处事器都需要接洽独特为复制功能编写的复制处理器。 贯穿搪塞处理器

    networking.c/acceptTcpHandler函数是Redis的贯穿搪塞处理器,这个处理工具于对贯穿处事器监听套接字的客户端进行搪塞,具体结束为sys/socket.h/acccept函数的包装。

    当Redis处事器进行驱动化的时候,要相识将这个贯穿搪塞处理器和处事器监听套接字的AE_READABLE时辰接洽起来,当有客户端用sys/socket.h/connect函数贯穿处事器监听套接字的时候,套接字就会产生AE_READABLE事件,激发贯穿搪塞处理器实施,并实施相应的套接字搪塞操作。

    号令苦求处理器

    networking.c/readQueryFromClient函数是Redis的号令苦求处理器,这个处理器负责从套接字中读入客户端发送的号令苦求内容,具体结束为unistd.h/read函数的包装。

    当一个客户端通过贯穿搪塞处理器到手贯穿到处事器之后,处事器会将客户端套接字的AE_READABLE事件和号令苦求处理器接洽起来,当客户端向处事器发送号令苦求的时候,套接字就会产生AE_READABLE事件,激发号出令苦求处理器实施,并实施相应的套接字读入操作。

    在客户端贯穿处事器的通盘这个词过程中,处事器都会一直为客户端套接字AE_READABLE事件接洽号令苦求处理器。

    号令回报处理器

    networking.c/sendReplyToClient函数是Redis的号令回报处理器,这个处理器负责从处事器实施号令后获取的号令回报通过套接字复返给客户端,具体结束为unistd.h/write函数的包装。

    当处事器有号令回报需要传送给客户端的时候,处事器会将客户端套接字的AE_WRITABLE事件和号令回报处理器接洽起来,当客户端准备好接收处事器传回的号令回报时,就会产生AE_WRITABLE事件,激发号出令回报处理器实施,并实施相应的套接字写入操作。

    当号令回报发送完毕之后,处事器就会根除号令回报处理器与客户端套接字的AE_WRITABLE事件之间的接洽。 

    小记忆

    一句话描述 IO 多路复用在 Redis 中的应用:Redis 将通盘产滋事件的套接字都放到一个部队内部,以有序、同步、每次一个套接字的样子向文献事件分配器传送套接字,文献事件分配器凭证套接字对应的事件遴荐反应的处理器进行处理,从而结束了高效的网络苦求。

    Redis的自界说公约

    Redis客户端使用RESP(Redis的序列化公约)公约与Redis的处事器端进行通讯。它结束简易,明白快速况兼人类可读。

    RESP 复旧以下数据类型:简易字符串、诞妄、整数、批量字符串和数组。

    RESP 在 Redis 顶用作苦求-反应公约的样子如下:

    客户端将号令四肢批量字符串的 RESP 数组发送到 Redis 处事器。 处事器凭证号令结束以其中一种 RESP 类型进行回报。

    在 RESP 中,某些数据的类型取决于第一个字节:

    对于简易字符串,回报的第一个字节是“+” 对于诞妄,回报的第一个字节是“-” 对于整数,回报的第一个字节是“:” 对于批量字符串,回报的第一个字节是“$” 对于数组,回报的第一个字节是“*”

    此外,RESP 大约使用稍后指定的批量字符串或数组的特殊变体来透露 Null 值。在 RESP 中,公约的不同部分老是以“\r\n”(CRLF)断绝。

    底下只简易先容字符串的编码样子和诞妄的编码样子,细则不错查抄 Redis 官网对 RESP 进行了详备的证明。

    简易字符串

    用如下门径编码:一个“+”号背面跟字符串,临了是“\r\n”,字符串里弗成包含"\r\n"。简易字符串用来传输比较短的二进制安全的字符串。举例好多redis号令实施到手会复返“OK”,用RESP编码便是5个字节:

    "+OK\r\n" 

    想要发送二进制安全的字符串,需要用RESP的块字符串。当redis复返了一个简易字符串的时候,客户端库需要给调用者复返“+”号(不含)之后CRLF之前(不含)的字符串。

    RESP诞妄

    RESP 有一种有利为诞妄瞎想的类型。履行上诞妄类型很像RESP简易字符串类型,但是第一个字符是“-”。简易字符串类型和诞妄类型的区别是客户端把诞妄类型当成一个很是,诞妄类型包含的字符串是很是信息。边幅是:

    "-Error message\r\n" 

    有诞妄发生的时候才会复返诞妄类型,举例你实施了一个对于某类型诞妄的操作,或者号令不存在等。当复返一个诞妄类型的时候客户端库应该发起一个很是。底下是一个诞妄类型的例子

    -ERR unknown command 'foobar' -WRONGTYPE Operation against a key holding the wrong kind of value 

    “-”号之后空格或者换行符之前的字符串代表复返的诞妄类型,这只是常规,并不是RESP要求的边幅。举例ERR是一般诞妄,WRONGTYPE是更具体的诞妄透露客户端的试图在诞妄的类型上实施某个操作。这个称为诞妄前缀,能让客户端更便捷的识别诞妄类型。

    客户端可能为不同的诞妄复返不同的很是,也可能只提供一个一般的门径来捕捉诞妄并提供诞妄名。但是弗成依赖客户端提供的这些性情,因为有的客户端只是复返一般诞妄,比如false。

    高性能 Redis 公约分析器

    尽管 Redis 的公约独特利于人类阅读, 界说也很简易, 但这个公约的结束性能仍然不错和二进制公约一样快。

    因为 Redis 公约将数据的长度放在数据正文之前, 是以要领无谓像 JSON 那样, 为了寻找某个特殊字符而扫描通盘这个词 payload , 也无谓对发送至处事器的 payload 进行转义(quote)。

    要领不错在对公约文本中的各个字符进行处理的同期, 查找 CR 字符, 并策画出批量回报或多条批量回报的长度, 就像这样:

    #include <stdio.h>  int main(void) {     unsigned char *p = "$123\r\n";     int len = 0;      p++;     while(*p != '\r') {         len = (len*10)+(*p - '0');         p++;     }      /* Now p points at '\r', and the len is in bulk_len. */     printf("%d\n", len);     return 0; } 

    获取了批量回报或多条批量回报的长度之后, 要领只需调用一次 read 函数, 就不错将回报的正文数据全部读入到内存中, 而无谓对这些数据做任何的处理。在回报最末尾的 CR 和 LF 不作处理,丢弃它们。

    Redis 公约的结束性能不错和二进制公约的结束性能相比美, 况兼由于 Redis 公约的简易性, 大部分高等话语都不错孤高地结束这个公约, 这使得客户端软件的 bug 数目大大减少。

    冷学问:redis到底有多快?

    在到手安设了Redis之后,Redis自带一个不错用来进行性能测试的号令 redis-benchmark,通过运行这个号令,咱们不错模拟N个客户端同期发送苦求的场景,并监测Redis处理这些苦求所需的时辰。

    凭证官方的文档,Redis经过在60000多个贯穿中进行了基准测试,况兼仍然大约在这些条款下督察50000 q/s的服从,通常的苦求量若是打到MySQL上,那战胜扛不住,胜利就崩掉了。亦然因为这个原因,Redis经常四肢缓存存在,大约起到对数据库的保护作用。

    官方给的Redis服从测试统计图[1](横坐标是贯穿数目,纵坐标是QPS)

    不错看出来啊,Redis堪称十万朦拢量如实也没自大,以后全球口试的时候也不错假装不经意间提一嘴这个数目级,发现好多人对“十万级“、”百万级“这种量级经常乱用,大约比较精确的说出来亦然一个加分项呢。

    我是敖丙,你骄横的越多,你不骄横的越多,咱们下期见!

     



    Powered by 三级小说 @2013-2022 RSS地图 HTML地图