Redis understanding of single-threaded mode

0.5 Overview

Based on Redis version is 4.0 or less, not completely single-threaded in later Redis, the increase of BIO-threaded , single-threaded mode This paper describes the main thread of the work.

Through this article you will learn the following:

  1. Redis reasons for adopting the single-threaded server model
  2. Redis single-threaded processing files and event time event
  3. Redis execution and scheduling events

1.Redis single-threaded mode

  • Status single-threaded

Redis is essentially not a simple single-threaded service model, some auxiliary work such as persistent brush plate, inert delete tasks are done by the BIO thread here that the main point is that the single-threaded client interaction to complete the command requests and replies the worker threads.

  • The reason single-threaded

As for design Antirez how to think big brother was not known as a single-threaded, it can only be analyzed from several angles, to determine the reasons for choosing single-threaded model:

  • CPU is not the bottleneck

Multi-threading model is mainly to take advantage of multi-core CPU, so that the thread is suspended while blocking IO to give up the right to use the CPU to other threads, and fully improve CPU utilization, but the scene is not obvious in Redis, because the CPU is not Redis bottlenecks, all operations are based on Redis memory, handle events fast, so use multithreading to switch threads to improve CPU utilization demand is not strong;

  • Memory is the bottleneck

Redis use a single instance of monocytes has been very good, but Redis memory bottleneck is envisaged 64-core machine if memory is only 16GB, so multi-threaded Redis what comes in?

  • Value type complex

Redis has a wealth of data structure, not simply type the Key-Value NoSQL, which is also a popular reason Redis, which are commonly used Hash, Zset, List and other structures in the value large, CURD operation will be very complicated,

If a multi-threaded mode during the same operation key lock is required to be synchronized, so that may cause deadlock.

This time you will ask: do the hash key will be assigned to the same threads to handle it can be resolved, is indeed the case, so would need to increase the hash key process of load balancing and multi-threaded processing in Redis,

Redis implementation has become so multi-threaded mode, as if indeed there is no problem, but Antirez did not do so, the great God is certainly a reason to do so, sure enough, we saw a cluster of Redis;

  • Cluster Extensions

When machines are currently polynuclear, but memory is generally 128GB / 64GB is relatively common, but the use of memory Redis stability as good as 60% or 50% of the performance (at least I Redis clustering using more than 70%, cluster failover frequency will be higher),

Therefore, when data is large, when Redis as main memory, it is necessary to use multiple machines constructed Redis clustered database system, since such a single-threaded mode Redis clustering process has been extended by the;

  • Software engineering perspective

In terms of single-threaded multi-threaded development and maintenance easier than a lot, and can also improve the stability of services, treatment no lock to make single-threaded Redis in the development and maintenance of all have a considerable advantage;

  • Redis class system:

Redis design adhering to the first practical and engineering, although theoretically there are many excellent design mode, but does not necessarily apply themselves, the software design process is the trade-off process.

The industry also has many of the NoSQL Redis class, such as the infrastructure 360 ​​Pika group developed system, based on SSD storage engine and Rocks, encapsulating an upper layer protocol conversion to analog Redis all functions, and can be used research interest.

 

2. single-threaded file events and time events

Redis as a service to work single-threaded process is also a lot, Redis is event-driven server, the main types of events is:

  1. File type of event
  2. Time Event Type

Among them, the time the event is key to understanding the logic of the single-threaded model.

  • Time Event

Redis time events are divided into two categories:

  1. Timed Events: The task is executed after waiting for the waiting time specified size, perform the complete execution is no longer triggered only once;
  2. Cycle events: the task is executed at predetermined time intervals, wait for the next performance after the execution is complete, periodic trigger;
  3. Periodic time events

Most are Redis cycle event, cycle event mainly on the operation of the server on a regular basis to detect and adjust itself to ensure the stability of HA, this work is mainly done ServerCron function, the content cycle events include:

  1. Delete key database
  2. AOF trigger RDB and persistence
  3. Master-slave synchronization
  4. Cluster keep alive
  5. Close clean up dead client link
  6. Memory, the number of key statistical information such as the update server

Redis visible cyclical Although the main event handling support missions, but the stable operation of the entire service, play a crucial role.

  • Unordered list time of the event

Redis each time the event is divided into three parts:

  1. Event ID globally unique in ascending order
  2. Ms accuracy time stamp trigger level
  3. Event handler event callback function

Time Event Time_Event structure:

Redis time events are stored in a linked list, and is in accordance with the stored ID, a new event in the head at the end of old events, but not stored in the order is about to be executed .

That is the first element of 50ms after the execution, but the third might perform after 30ms, so each get Redis recent events to be executed from the list, the need to be O (N) traversal ,

Obviously performance is not the best, certainly the best case minimum stack MinStack similar ideas, but Antirez chiefs chose disorderly linked list.

Redis disorder selected scene list are also suitable, because the time is not much Redis event number, even if the O (N) performance loss is also minimal traversal, each time a new event there is no need for rearrangement inserted list.

Disorderly Redis storage time of the event list as shown:

3. Under single-threaded scheduling and execution of events

Redis service because it contains time events and file events, things will get complicated, file server to determine when to process the event, when the processing time of the event, and also to know exactly the length of time the processing time, and therefore the implementation of the event and scheduling has become the focus.

Redis server will in turn deal with file events and time of the event , to handle both events are synchronous, ordered, atomically executed, the server does not terminate event is being executed, the event will not be preempted.

The scheduling process is quite interesting , let's look together:

  • Event execution scheduling rules

File events are random, if a file event processing is complete, the file is still no other event arrives, the server will continue to wait,

In the event of the ongoing implementation of the file, the time will gradually earliest time event reaches at the set time and eventually came close to the time of arrival,

这时服务器就可以开始处理到达的时间事件了。由于时间事件在文件事件之后执行,并且事件之间不会出现抢占,

所以时间事件的实际处理时间一般会比设定的时间稍晚一些。

  • 事件执行调度的代码实现

Redis源码ae.c中对事件调度和执行的详细过程在aeProcessEvents中实现的,具体的代码如下:

int aeProcessEvents(aeEventLoop *eventLoop, int flags)
{
  int processed = 0, numevents;
  if (!(flags & AE_TIME_EVENTS) && !(flags & AE_FILE_EVENTS))
    return 0;

  if (eventLoop->maxfd != -1 ||
    ((flags & AE_TIME_EVENTS) && !(flags & AE_DONT_WAIT))) {
    int j;
    aeTimeEvent *shortest = NULL;
    struct timeval tv, *tvp;

    if (flags & AE_TIME_EVENTS && !(flags & AE_DONT_WAIT))
      shortest = aeSearchNearestTimer(eventLoop);
    if (shortest) {
      long now_sec, now_ms;
      aeGetTime(&now_sec, &now_ms);
      tvp = &tv;
      long long ms =
        (shortest->when_sec - now_sec)*1000 +
        shortest->when_ms - now_ms;

      if (ms > 0) {
        tvp->tv_sec = ms/1000;
        tvp->tv_usec = (ms % 1000)*1000;
      } else {
        tvp->tv_sec = 0;
        tvp->tv_usec = 0;
      }
    } else {
      if (flags & AE_DONT_WAIT) {
        tv.tv_sec = tv.tv_usec = 0;
        tvp = &tv;
      } else {
        tvp = NULL; /* wait forever */
      }
    }
    numevents = aeApiPoll(eventLoop, tvp);
    if (eventLoop->aftersleep != NULL && flags & AE_CALL_AFTER_SLEEP)
      eventLoop->aftersleep(eventLoop);

    for (j = 0; j < numevents; j++) {
      aeFileEvent *fe = &eventLoop->events[eventLoop->fired[j].fd];
      int mask = eventLoop->fired[j].mask;
      int fd = eventLoop->fired[j].fd;
      int fired = 0;
      int invert = fe->mask & AE_BARRIER;
      if (!invert && fe->mask & mask & AE_READABLE) {
        fe->rfileProc(eventLoop,fd,fe->clientData,mask);
        fired++;
      }
      if (fe->mask & mask & AE_WRITABLE) {
        if (!fired || fe->wfileProc != fe->rfileProc) {
          fe->wfileProc(eventLoop,fd,fe->clientData,mask);
          fired++;
        }
      }
      if (invert && fe->mask & mask & AE_READABLE) {
        if (!fired || fe->wfileProc != fe->rfileProc) {
          fe->rfileProc(eventLoop,fd,fe->clientData,mask);
          fired++;
        }
      }
      processed++;
    }
  }
  /* Check time events */
  if (flags & AE_TIME_EVENTS)
    processed += processTimeEvents(eventLoop);
  return processed;
}
  • 事件执行和调度的伪码

上面的源码可能读起来并不直观,在《Redis设计与实现》书中给出了伪代码实现:

def aeProcessEvents()
  #获取当前最近的待执行的时间事件
  time_event = aeGetNearestTimer()
  #计算最近执行事件与当前时间的差值
  remain_gap_time = time_event.when - uinx_time_now()
  #判断时间事件是否已经到期 则重置 马上执行
  if remain_gap_time < 0:
    remain_gap_time = 0
  #阻塞等待文件事件 具体的阻塞等待时间由remain_gap_time决定
  #如果remain_gap_time为0 那么不阻塞立刻返回
  aeApiPoll(remain_gap_time)
  #处理所有文件事件
  ProcessAllFileEvent()
  #处理所有时间事件
  ProcessAllTimeEvent()

可以看到Redis服务器是边阻塞边执行的,具体的阻塞事件由最近待执行时间事件的等待时间决定的,在阻塞该最小等待时间返回之后,开始处理事件任务,

并且先执行文件事件、再执行时间事件,所有即使时间事件要即刻执行,也需要等待文件事件完成之后再执行时间事件,所以比预期的稍晚。

  • 事件调度和执行流程

 

 

4.参考资料

    • 深入了解Redis之事件原理和实现
    • 《Redis设计与实现》黄健宏

Guess you like

Origin www.cnblogs.com/backnullptr/p/12010391.html