"Это седьмой день моего участия в ноябрьском испытании обновлений, ознакомьтесь с подробностями события:Вызов последнего обновления 2021 г."
Как самая популярная база данных пар «ключ-значение», Redis играет очень важную роль в разработке системы нашими бэкэнд-инженерами. Его сверхвысокая производительность чтения и записи, богатая структура хранения, дизайн кластера с высокой доступностью и активное сообщество, несомненно, являются лучшим выбором для баз данных с открытым исходным кодом в памяти. Давайте узнаем сегодняКак Redis обрабатывает команду? Какую маленькую мысль он использует в коде для повышения производительности?
Источники данныхdb-engines.comдо начала
Прежде чем начать, убедитесь, что у нас есть определенное понимание установки, работы и общих команд Redis, чтобы у нас было понимание восприятия при попытке понять принцип внутренней реализации. Давайте рассмотрим:
- Запустите контейнер Redis через Docker и введите
$ docker pull redis:4
$ docker exec -p 6379:6379 -itd --name redis redis:4
# 进入容器
$ docker exec -it redis sh
- пройти через
redis-cli
подключиться, выполнить некоторые команды
$ redis-cli
redis-cli(6379)> set name foo
OK
redis-cli(6379)> get name
"foo"
Давайте посмотрим, что произошло с Redis в описанном выше процессе?С внешней точки зрения, то есть с точки зрения клиента, его можно разбить на следующие этапы.
- Служба Redis запускается
- Клиент устанавливает соединение с Redis
- Клиент отправляет
set name foo
команда, возврат ответаOK
- Клиент отправляет
get name
команда, возврат ответаfoo
Итак, далее мы начнем с внутренней точки зрения Redis (Анализ на основе исходного кода Redis 5.0), заходи и смотри, когда командаset name foo
Когда его получает Redis, насколько он «сопротивляется одному человеку»?
Когда запускается Редис
Когда Redis запускается, он сначала инициализирует сервер, включая следующие шаги:
- Исходная конфигурация (конфигурация системы по умолчанию)
- Загружать и анализировать файлы конфигурации (конфигурация пользователя)
- Инициализировать внутренние переменные службы
- Создать цикл событий eventLoop
- Создайте сокет и начните слушать
- Создать событие файла и событие времени
- запустить цикл событий
Начальная конфигурация
Основная функция первой операцииinitServerConfig(void)
, имеется более 200 строк, в основном для установки конфигурации системы по умолчанию для некоторых основных параметров сервера, таких как:
основные параметры | По умолчанию |
---|---|
Частота выполнения запланированной задачи по умолчанию | 10 |
номер порта прослушивания | 6379 |
Максимальное количество клиентов | 10000 |
тайм-аут клиента | 0 (никогда не истекает) |
Количество баз данных | 16 |
Кроме того, инициализируется список часто используемых команд. |
Загрузка и разбор файлов конфигурации
Основная функция операции второго шага состоит в том,void loadServerConfig(char *filename, char *options)
, в параметреfilename
это путь к конфигурационному файлу,options
Информация о конфигурации, указанная параметрами для командной строки, например:
$ redis-server /config/redis/redis.conf -p 400
но/config/redis/redis.conf
будет действовать какfilename
,-p 400
в видеoptions
.
При анализе файла конфигурации все содержимое файла конфигурации загружается в память через\n
разделить, а затем#
Строка в начале пропускается, что представляет собой комментарий.
Инициализировать внутренние переменные службы
Основная функция операции третьего шага состоит в том,initServer(void)
, в основном для инициализации некоторых клиентских связанных списков, баз данных, глобальных и общих переменных.
Redis уменьшает частое выделение памяти за счет повторного использования общих переменных через функцииcreateSharedObjects(void)
Для этого общие переменные хранятся в глобальной структуре.shared
, в основном включают:
- Строка для ответа, например:
shared.ok
,shared.err
- Целое число от 0 до 10000, например:
shared.integers[1]
Создать цикл событий eventLoop
Основная функция операции четвертого шага состоит в том,aeCreateEventLoop(int setsiee)
, создать цикл обработки событий eventLoop, то есть выделить необходимую для структуры память, инициализировать поля структуры и вызватьaeApiCreate
Функция инициализирует структуру, соответствующую epoll.
Создайте сокет и начните слушать
Основная функция операции пятого шага состоит в том,listenToPort(int port, int *fds, int *count)
используется в этой функцииserver
переменная, которая является глобальной переменной
// server.c
/* Global vars */
struct redisServer server; /* Server global state */
Инициализация этой переменной выполняется на третьем шаге, упомянутом выше.server.bindaddr
Все IP-адреса, записанные пользователем в конфигурационном файле, сохраняются. Пятый шаг — пройти по IP-адресу, настроенному пользователем, установить非阻塞
розетка для мониторинга.
Создать событие файла и событие времени
Следующим шагом является создание файловых событий и временных событий.Redis абстрагирует события чтения и записи сокета в файловые события, то естьaeFileEvent
, Выполнить по циклу события. Поэтому вам нужно создать соответствующее файловое событие для только что прослушанного сокета.
Основной функцией обработки для создания файловых событий является
int aeCreateFileEvent(aeEventLoop *eventLoop, int fd, int mask,
aeFileProc *proc, void *clientData)
Я понимаю, что использование неблокирующих свойств EPOLL, соответствующее связыванию обработчика для каждого события, когда происходит событие, вызов соответствующих функций обработки обрабатывается может быть. Например: обработчик событий для прослушиванияacceptTcpHandle
r, который реализует прием запроса на подключение к сокету и создание объекта клиента.
Событие времени инициируется функцией задачи по времени, а основная функция обработкиaeCreateTimeEvent
, на самом деле есть только одно временное событие, и он соединяет несколько задач синхронизации через связанный список.
запустить цикл событий
Последний шаг — запустить цикл обработки событий, код основной функции обработки очень мал, давайте посмотрим
void aeMain(aeEventLoop *eventLoop) {
eventLoop->stop = 0;
while (!eventLoop->stop) {
if (eventLoop->beforesleep != NULL)
eventLoop->beforesleep(eventLoop);
aeProcessEvents(eventLoop, AE_ALL_EVENTS|AE_CALL_AFTER_SLEEP);
}
}
уведомлениеeventLoop->beforesleep
Функция, которая выполняется перед каждым циклом событий, выполняет некоторые операции, не требующие больших затрат времени, такие как: операции, связанные с кластером, операции удаления просроченного ключа (здесь можно назвать быстрое удаление просроченного ключа), возврат ответов на команды на клиент и т.д. после этогоaeProcessEvents
выполнение функции, которая блокирует ожиданиеНекоторое времяОтвет на событие файла, если есть результат, выполнить соответствующую функцию обработки, а затем выполнить событие времени.
Суммировать
В этой статье объясняется, какие действия выполняет программа при запуске Redis: инициализация конфигураций и переменных, создание циклов событий, прослушивание сокетов, создание файловых событий и временных событий и многое другое. Я также узнал о роли глобальных переменных и общих переменных в Redis.Операция инициализации целых чисел от 0 до 10000 в общих переменных — это идея из небольшого пула целых чисел при изучении управления памятью Python ранее (пространство — это время).