Я всегда завидую тем детским ботинкам, которые могут читать исходный код Redis, и я всегда хочу прочитать их сам, но под давлением короля Си дата интерпретации еще далека.
Я считаю, что многие мелкие партнеры также должны интересоваться или интересовались исходным кодом, но сначала они чувствуют, что не знают языка Си, а затем не знают, с чего начать, результат такой же, как у блогера, промедление.
Но лучшее время для посадки дерева-десять лет назад, а затем Сейчас? 。 Если вы действительно хотите узнать исходный код Redis и у вас есть возможность увидеть эту серию блогов, почему бы не последовать за блоггером, чтобы интерпретировать исходный код Redis и стать коллегой? Далее, давайте перейдем в исходный мир Redis.
Я решил прочитать его. Следующий шаг-это то, как его прочитать. Клонируйте исходный код с github, посмотрите на каталог SRC, посмотрите на небо, 104 файла, с какого файла мне начать? Посмотрите файлы один за другим? Нет, нет, нет, для меня нет соблазна, нет соблазна, как я могу преодолеть влечение ко мне игр, романов? Это трудно понять. Затем я вдруг вспомнил классический вопрос для интервью по протоколу HTTP: что произошло в процессе перехода от браузера к отображению страницы?
Измените вопрос интервью на Redis: Введите команду, чтобы открыть службу Redis, вернитесь и успешно запустите службу Redis. Что происходит в этом процессе?
Очень хорошо, этот вопрос успешно привлек меня. Давайте найдем ответ на этот вопрос в исходном коде. Во всех последующих статьях мы пытаемся лучше понять Redis, задавая вопросы и отвечая на них.
Чтобы понять процесс выполнения команды Redis, нам сначала нужно установить службу Redis и создать среду отладки. Если мы можем видеть выполнение команд в коде строка за строкой, нет никаких препятствий для интерпретации исходного кода.
Все последующие статьи основаны на redis версии 3.2.13.
1. Создание среды отладки
1. Загрузите скомпилированные файлы В linux, загрузите исходные файлы, скомпилируйте их и отладьте с помощью GDB (gdb).
# bash wget https://github.com/antirez/redis/archive/3.2.13.tar.gz tar -zxvf 3.2.13.tar.gz mv redis-3.2.13 /opt/ cd redis-3.2.13 Make Compile the file, get the executable files redis-server, redis-cli, etc.
2. Откройте отладку
# bash GDB Src / redis-server # Install directory in redis and enter GDB debugging environment
В соответствии с нашими обычными привычками отладки найдите функцию для установки точек останова, а затем шаг за шагом запустите отладку. Для Redis мы тоже находим сервер. Файл C, в котором находится основная функция, выполняемая сервером. Мы устанавливаем точки останова для основных функций:
# gdb (gdb) b main Breakpoint 1 at 0x42ed05: file server.c, line 3962.
На странице нам будет предложено установить точку останова в строке 3962 сервера. Файл C, в котором находится указанная нами основная функция.
Установив точку останова, следующим шагом является запуск службы:
// Start up service
(gdb) r ./redis.conf
Starting program: /opt/redis-3.2.13/src/redis-server ./redis.conf
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Breakpoint 1, main (argc=2, argv=0x7fffffffe5a8) at server.c:3962
3962 int main(int argc, char **argv) {Выведя информацию через страницу, мы обнаружим, что программа запустилась до заданной нами точки останова. Но мы не можем видеть код во время выполнения. Это невозможно. Мы не видим отладки исходного кода. Мы не можем принять вызов “исходный код”, используя следующие команды:
(gdb) layout src
Появится следующий интерфейс:
На данный момент мы официально вступили на путь интерпретации исходного кода Redis.
2 Служба Инициализации
Продолжайте, используйте команду n , выполните следующий шаг, а затем продолжайте возвращаться, возвращаться, возвращаться, как будто каждая строка не понимала, что она означает. Несмотря ни на что, продолжай идти. Боже, кажется, я нашел кого-то, кто мог понять. initServerConfig() 。 Если вы правы, это должно инициализировать конфигурацию сервера. Давайте перейдем к этой функции, чтобы подтвердить, что:
(gdb) s
Возвращайся и уходи. Затем мы видим следующий интерфейс:
Намекните нам на строку server. C 1464 initServerConfig В функции. n Заказывайте, продолжайте. Мы обнаружим, что в этой функции инициализируются различные основные параметры сервера. Параметры здесь подробно описаны в структуре сервера server.h/redis.
Когда мы вернемся к основной функции, мы пойдем дальше и найдем другую. initServer() Функция. Эта функция используется для регистрации событий драйвера и привязки функций обратного вызова.
Продолжайте, пока это не будет реализовано remain() Следующим образом:
К тому времени, когда программа набрала 4133 строки, служба Redis была успешно открыта. На данный момент сервер находится в состоянии покоя и использует aeMain() Для опроса событий и ожидания наступления события.
Весь процесс, упомянутый выше, мы просто следим за работой программы, примерно смотрим на процесс выполнения. Далее давайте подробнее остановимся на ключевых шагах, описанных выше: Инициализация базовой конфигурации и Инициализация структуры данных сервера 。
3. Подробная интерпретация инициализации
3.1 Инициализация базовой конфигурации
Первым шагом при инициализации сервера является его создание `redis Server Сервер переменных экземпляра типа действует как состояние сервера и устанавливает значения по умолчанию для каждого атрибута в структуре.
void initServerConfig(void) {
int j;
// Setting the Server Running ID
getRandomHexChars(server.runid,CONFIG_RUN_ID_SIZE);
// Add a trailing character to the running ID
server.runid[CONFIG_RUN_ID_SIZE] = '\0';
// Setting the default running architecture of the server
server.arch_bits = (sizeof(long) == 8) ? 64 : 32;
// Setting the default configuration file path for the server
server.configfile = NULL;
// Set the default running frequency of the server
server.hz = CONFIG_DEFAULT_HZ;
// Setting the default port of the server
server.port = CONFIG_DEFAULT_SERVER_PORT;
// ...
}о initServerConfig Функционально он в основном выполняет следующие основные задачи:
- Установите рабочий идентификатор сервера.
- Установите частоту работы сервера по умолчанию.
- Установите путь к файлу конфигурации по умолчанию для сервера.
- Настройте текущую архитектуру сервера.
- Установите номер порта сервера по умолчанию
Атрибуты состояния сервера, заданные функцией initServerConfig, в основном являются целочисленными, с плавающей запятой или строковыми атрибутами. В дополнение к командной строке функция initServerConfig не создает никакой другой структуры данных для состояния сервера. На последующих шагах создаются структуры данных, такие как базы данных, журналы медленных запросов, среды Lua, общие объекты.
После инициализации основных параметров конфигурации следующим шагом является запуск Загрузка параметров конфигурации 。
3.2 Параметры Конфигурации Загрузки
При запуске сервера пользователи могут изменить конфигурацию сервера по умолчанию, указав параметры конфигурации или зная файлы конфигурации. Точно так же, как мы можем указать порт при запуске службы:
# bash ./src/redis-server --port 7379
Номер рабочего порта сервера изменяется путем указания параметров конфигурации.
В дополнение к заданному параметру конфигурации мы можем запустить службу, указав файл конфигурации:
# bash ./src/redis-server ./redis.conf
Когда мы запускаем службу, указывая файл конфигурации, мы фактически изменяем конфигурацию базы данных сервера в виде файла конфигурации.
Используемые серверы initServerConfig Начальный конец функции сервер После загрузки переменной загружаются параметры конфигурации и файлы, заданные пользователем, и в соответствии с конфигурацией, заданной пользователем, изменяются атрибуты, связанные с сервером переменной.
Для конфигурации командной строки, конфигурации файла конфигурации, конфигурации по умолчанию используются следующие три конфигурации:
- При наличии указанной конфигурации сервер имеет указанное пользователем значение для обновления соответствующих свойств.
- Если указанное значение отсутствует, используйте
initServerConfigЗначения по умолчанию для настроек функций.
3.3 Инициализация структуры данных Сервера
Реализация initServerConfig Когда функция инициализирует конфигурацию, программа создает только одну структуру данных таблицы команд, в то время как сервер включает в себя другие структуры данных, помимо таблицы команд, такие как:
- Сервер. связанный список клиентов 。 В этом списке записана структура состояний всех клиентов, подключенных к серверу. Каждый узел связанного списка содержит один
Повторно обнаруженныйСтруктурный пример. - Массив Server.db . Массив содержит все базы данных сервера.
- Server.Словарь pubsub_channels Информация о подписке на канал сохраняется в словаре.
- Сервер. связанный список pubsub_pattern . Сохраните информацию о подписке на схему в связанном списке.
- Сервер. Атрибут Lua 。 Используется для выполнения сценариев Lua.
- Сервер. атрибут slowlog . Используется для сохранения медленных журналов.
Эти структуры данных будут initServer Функции выделяют для них память и устанавливают или связывают значения инициализации для этих структур данных по мере необходимости.
Причина, по которой структура данных инициализируется после загрузки конфигурации пользователя, заключается в том, что сервер должен загрузить параметры конфигурации пользователя, прежде чем правильно инициализировать структуру данных в соответствии с параметрами. Избегайте изменения атрибутов, связанных со структурой данных, в соответствии с конфигурацией пользователя.
Таким образом, мы видим, что инициализация состояния сервера делится на два этапа:
Функция initServerConfigявляется инициализацией общих свойств.initServerИнициализируйте структуру данных.
В дополнение к инициализации структуры данных, initServer Также были выполнены некоторые очень важные операции по настройке, в том числе:
- Настройте процессор обработки сигналов процесса для сервера.
- Создавайте общие объекты. Эти объекты включают только некоторые часто используемые серверы Redis, такие как строковые объекты, содержащие ответы “ОК”, строковые объекты, содержащие ответы “ОШИБКА”, строковые объекты, содержащие целые числа от 1 до 10 000 и так далее. Именно за счет повторного использования этих общих объектов сервер позволяет избежать повторного создания одних и тех же объектов и экономит память.
- Откройте порт прослушивания сервера и свяжите обработчик событий ответа для прослушивающего сокета, ожидая, пока сервер примет подключение клиента, когда оно будет официально запущено.
- Чтобы создать событие времени для сервера, ожидающий сервер выполняет функцию Cron сервера во время выполнения.
- Если сохраняемость AOF включена, откройте существующий файл AOF. Если файл AOF не существует, создайте и откройте новый файл AIF, чтобы подготовиться к записи.
- Инициализируйте модуль фонового ввода – вывода сервера для подготовки к операции ввода-вывода.
Когда initServer После выполнения функции сервер распечатает значок Redis и информацию о номере версии Redis в журнале с помощью символов ASCII.
4 Другие операции
4.1 Восстановление базы данных
После завершения состояния сервера сервер После инициализации переменных серверу необходимо загрузить файлы RDB или файлы AOF (файлы постоянного сохранения данных) и восстановить состояние базы данных сервера в соответствии с содержимым записей файлов.
Во время процесса восстановления сервер определяет, включена ли сохраняемость AOF:
- Если сохраняемость AOF включена, сервер будет использовать файл AOF для восстановления состояния базы данных.
- Если AOF не включен, сервер использует файлы RDP для восстановления состояния базы данных.
Когда сервер завершает восстановление состояния базы данных, требуется много времени, чтобы распечатать файл загрузки и восстановить состояние базы данных в журнале.
8189:M 31 мая 13:12:47,971 * ДБ загружено с диска: 0,000 секунды
4.2 Выполнение цикла событий
На последнем этапе инициализации сервер распечатывает следующие журналы:
8189:M 31 мая 13:12:47.971 * Сервер теперь готов принимать соединения через порт 8379
И начните выполнять цикл событий сервера.
На данный момент инициализация сервера завершена.
5 Основное использование GDB
| gdb src/redis-сервер | файл gdb | Загрузите исполняемый файл отладчика |
| r ./redis.conf | r | Запустите аббревиатуру, запустите отлаженную программу. |
| c | c | Аббревиатура для Продолжения. Продолжайте выполнение отлаженной программы до следующей точки останова или конца программы |
| b основные | b | Аббревиатура точки останова. Установите точки останова. Местоположение точки останова может быть указано по номеру строки, имени функции, адресу выполнения и т.д. |
| с/н | с/н | S эквивалентно “отслеживанию и вводу в один шаг”, то есть в выполняемую функцию. N эквивалентно “одноэтапному отслеживанию” и не входит в функцию выполнения |
| p сервер | Имя переменной P | Напечатать аббревиатуру. Отображает значение указанной переменной. |
резюме
- Для создания среды существует три шага: загрузка, компилятор и gdb.
- Запуск службы включает в себя инициализацию базовой конфигурации, структуры данных, подготовку к предоставлению внешних услуг, восстановление базы данных, выполнение цикла событий и т.д.
- Основная команда GDB: R C B N P.