Douyin, Tencent, Ali, Meituan Spring Recruitment Server После жесткого интервью (завершено)

интервью задняя часть

существуетПредыдущийСреди нас мы поделились вопросами интервью нескольких крупных интернет-компаний, и эта статья выйдетПодробный анализ ответов на вопросы интервью и обзор упомянутых и систематизированных материалов интервью, личные сокровища Xiaomin🐶.

Первая — оглашение ответов на вопросы интервью, при объяснении мы в основном делим их на следующие части: базовые знания языков, промежуточного программного обеспечения, операционных систем, компьютерных сетей, рукописных алгоритмов, открытые вопросы и проектный опыт. Организуйте вопросы интервью и связанные с ними точки знаний, чтобы учащимся было легче их понять. Пожалуйста, простите меня за то, что я не объяснил в том порядке, в котором вопросы были заданы.

Далее следуют справочные материалы по обзору Java и сопоставленные материалы интервью. Из-за большого количества контента обучениеЭто очень важно. Позвольте представить основные моменты и содержание. Для полного файла, пожалуйста, обратитесь к информации в формате pdf, предоставленной автором.

Анализ вопросов интервью.

Как работает Дженкинс?

Jenkins включает в себя знания, связанные с DevOps, и в основном используется для автоматической интеграции, непрерывного и автоматического построения/тестирования программных проектов и мониторинга некоторых запланированных задач.

Сегодня непрерывная интеграция (CI) стала обычной практикой для многих групп разработчиков программного обеспечения, поскольку они сосредоточены на обеспечении качества кода на протяжении всего жизненного цикла разработки программного обеспечения. Это практика, предназначенная для облегчения и стабилизации процесса создания программного обеспечения.

В чем польза MVCC с точки зрения чтения

Большинство транзакционных механизмов хранения MySQL реализуют больше, чем просто блокировку на уровне строк. Основываясь на соображении повышения производительности параллелизма, они обычно одновременно реализуют управление параллелизмом нескольких версий (MVCC). Реализации MVCC для разных механизмов хранения различаются, как правило, оптимистичный контроль параллелизма и пессимистичный контроль параллелизма.

MVCC просто означает, что отправка любой модификации в базу данных не будет напрямую перезаписывать предыдущие данные, а будет генерировать новую версию, которая будет сосуществовать со старой версией, так что чтение может быть полностью разблокировано. При чтении определенных данных таким образом транзакция может выбрать, какую версию данных читать в соответствии с уровнем изоляции. Нет абсолютно никакой необходимости в блокировке во время процесса.

MVCC можно рассматривать как вариант блокировки на уровне строк, но во многих случаях он позволяет избежать операций блокировки и, следовательно, менее затратен. Большинство MVCC реализуют неблокирующие операции чтения, а операции записи блокируют только необходимые строки. MVCC может действовать только на уровне изоляции Repeatable Read и Commitable Read. Незафиксированное чтение не может использовать его, потому что оно не может читать версии строк, соответствующие транзакционным версиям. Они всегда читают последнюю версию строки. Причина, по которой Serializable не может использовать MVCC, заключается в том, что он всегда блокирует строку.

Реализация MVCC достигается за счет сохранения моментального снимка данных в определенный момент времени. То есть независимо от того, сколько времени требуется для выполнения, данные, видимые каждой транзакцией, непротиворечивы. В зависимости от того, когда начинается транзакция, каждая транзакция может одновременно видеть разные данные для одной и той же таблицы.

Как реализовать заказ mysql с помощью

В MySQL есть два способа реализации ORDER BY:

  • Генерация упорядоченных результатов с помощью сканирования индекса
  • Использование файловой сортировки (filesort)
Используйте упорядоченный индекс для получения упорядоченных данных

Извлеките поля, которые удовлетворяют условиям фильтрации, в качестве условий сортировки и информацию указателя строки, которая может быть непосредственно расположена в данных строки, выполните фактическую операцию сортировки в буфере сортировки, а затем используйте отсортированные данные для возврата в таблицу. в соответствии с информацией указателя строки для получения запроса клиента. Данные других полей возвращаются клиенту.

Таким образом, при использовании объяснения для анализа запроса отображается индекс использования. И сортировка файлов показывает Использование сортировки файлов.

В операторах SQL как предложение WHERE, так и предложение ORDER BY могут использовать индексы: предложение WHERE использует индекс, чтобы избежать полного сканирования таблицы, а предложение ORDER BY использует индекс, чтобы избежать сортировки файлов (использование «избегать» может быть несколько неуместно, а в некоторых сценариях полное сканирование таблицы и сортировка файлов могут быть не медленнее индексации) для повышения эффективности запросов.

Хотя индексы могут повысить эффективность запроса, в SQL только один индекс может использоваться для запроса к таблице за раз (Примечание: возможность слияния индексов исключена), то есть когда предложение WHERE и предложение ORDER BY требуются. Когда используемые индексы несовместимы, MySQL может использовать только один из индексов (дерево B+).

То есть в SQL с WHERE и ORDER BY есть три возможных сценария использования индексов:

  • Используется только в предложении WHERE для фильтрации данных, соответствующих условиям.
  • Используется только в предложении ORDER BY, возвращает отсортированный результат
  • Используется как для WHERE, так и для ORDER BY, отфильтровывает данные, соответствующие условиям, и возвращает отсортированные результаты.
сортировка файлов

filesort — это просто сортировка, будет ли она ставиться на диск или нет, зависит от ситуации. Использование файловой сортировки на диске зависит от объема данных, с которыми она работает. Подводя итог, файловая сортировка делится на два типа в зависимости от метода сортировки:

  • Когда объем данных небольшой, они быстро сортируются в памяти
  • Когда объем данных большой, он разбивается на блоки в памяти и быстро сортируется, а затем каждый блок объединяется на диске

В случае большого объема данных задействуется disk io, поэтому эффективность будет ниже. По количеству запросов, возвращаемых к таблице, файловую сортировку можно разделить на два способа:

  • Вернуться к таблице, чтобы прочитать данные дважды (два прохода): две сортировки передачи
  • Чтение данных обратно в таблицу (однопроходная): однопроходная сортировка

Недостатком однократной сортировки является то, что все задействованные столбцы помещаются в буфер сортировки, а одновременно в буфер сортировки может быть помещено меньшее количество кортежей, и повышается вероятность сортировки слиянием. Чем больше объем данных столбца, тем больше способов слияния требуется, что увеличивает дополнительные затраты на ввод-вывод. Поэтому, когда объем данных столбца слишком велик, эффективность сортировки с одной передачей может быть не такой эффективной, как сортировка с двумя передачами.

Две сортировки переноса будут выполнять две операции с таблицей возврата: первая таблица возврата используется для фильтрации идентификатора строки, соответствующего условиям, и значения столбца ORDER BY, соответствующего идентификатору строки в предложении WHERE; вторая таблица возврата встречается в предложении ORDER BY. пара После того, как указанный столбец отсортирован, информация о поле, требуемая предложением SELECT, извлекается из таблицы возврата rowid.

Вы хотите добавить поля после порядка индекса mysql?

Для проблемы добавления порядка по полю в сам индекс, если окончательный набор результатов фильтруется на основе порядка по полю, добавление порядка по полю в индекс и размещение его в правильном положении в индексе значительно улучшит производительность. .

эврика исходный код

Eureka — это компонент регистрации и обнаружения служб, рекомендованный Spring Cloud, включая Eureka Server и Eureka Client:

  1. Eureka Server предоставляет услугу регистрации службы.После запуска каждой ноды она будет зарегистрирована в Eureka Server, так что реестр служб на сервере будет хранить информацию обо всех доступных сервисных нодах;

  2. Eureka Client — это Java-клиент, упрощающий взаимодействие с Eureka Server.Клиент также имеет встроенный балансировщик нагрузки, использующий циклический алгоритм балансировки нагрузки;

  3. После запуска приложения оно отправит тактовый сигнал на сервер Eureka (период по умолчанию — 30 с). Если сервер Eureka не получит сигнал от узла в течение нескольких периодов тактового сигнала, период 30с) для 90с);

  4. Синхронизация данных между серверами Eureka осуществляется посредством репликации;

  5. Eureka Client имеет механизм буферизации.Если все серверы Eureka не работают, клиент по-прежнему может использовать кэшированную информацию для использования других сервисных API;

  6. Регион Эврика можно понимать как географический раздел, конкретных ограничений по размеру нет;

  7. Зону Эврика можно понимать как конкретную информацию компьютерного зала в регионе;

  8. Фреймворк Jersey используется для реализации собственного HTTP-интерфейса Restful.Синхронизация и регистрация сервисов между пирами реализованы через HTTP-протокол.Задачи по расписанию (отправка пульсаций, регулярная очистка сервисов с истекшим сроком действия, синхронизация узлов и т.д.) реализованы через Timer который поставляется с JDK, а кеш памяти реализует реализацию Google guava;

  9. Когда сервер реестра услуг обнаруживает, что поставщик услуг не работает, он переводит службу в состояние DOWN в сервисном центре и публикует услугу для других подписчиков, а подписчики обновляют информацию о локальном кэше;

  10. Когда узел Eureka Server теряет слишком много клиентов за короткий промежуток времени, узел переходит в режим самозащиты и больше не выходит из каких-либо служб;

Исходный код Hystrix

В распределенной системной среде подобные зависимости между сервисами очень распространены, и бизнес-вызов обычно зависит от нескольких базовых сервисов. Как показано на рисунке ниже, для синхронных вызовов, когда служба инвентаризации недоступна, поток запроса службы инвентаризации блокируется.При наличии больших пакетов запросов на вызов службы инвентаризации все ресурсы службы инвентаризации могут в конечном итоге быть исчерпаны, и внешняя служба не может быть продолжена. И эта недоступность может передаваться вверх по цепочке вызовов запросов — явление, известное как эффект лавины.

Hystrix по-китайски означает дикобраз, так как его спина покрыта шипами, он обладает способностью защищаться.

Цели дизайна Hystrix
  • Защита и контроль задержек и сбоев из-за зависимостей — часто доступ по сети
  • Остановить цепную реакцию неудач
  • Быстро терпите неудачу и быстро восстанавливаетесь
  • Откат и изящная деградация
  • Обеспечивает мониторинг и оповещение в режиме, близком к реальному времени
Принципы проектирования, которым следует Hystrix
  • предотвратить исчерпание ресурсов (потоков) любой отдельной зависимостью
  • Перегрузка немедленно отключается и быстро выходит из строя, предотвращая возникновение очередей
  • Обеспечьте запасные варианты, когда это возможно, чтобы защитить пользователей от сбоев.
  • Используйте методы изоляции, такие как перегородки, плавательные дорожки и шаблоны автоматических выключателей, чтобы ограничить влияние любой зависимости.
  • Обеспечьте своевременное обнаружение сбоев с помощью метрик почти в реальном времени, мониторинга и оповещения.
  • Динамическое изменение свойств конфигурации для обеспечения своевременного восстановления после сбоев
  • Предотвращает сбой выполнения всего зависимого клиента, а не только сетевой связи.

Как реализована распределенная блокировка?

Распределенные блокировки обычно используются в микросервисных архитектурах, и существует несколько реализаций:

Распределенная блокировка на основе базы данных

Уникальная распределенная блокировка на основе первичного ключа таблицы

Идея: Используя уникальную функцию первичного ключа, если в базу данных одновременно отправляется несколько запросов, база данных будет гарантировать только то, что только одна операция может быть успешной, тогда можно считать, что поток, который успешно выполнил операцию получил блокировку метода. Когда метод завершает выполнение, блокировку можно снять, удалив строку данных.

  • Единая база данных приводит к сильным зависимостям, которые можно переключать между ведущим и подчиненным через несколько баз данных.
  • Избегайте взаимоблокировки, удаляя данные тайм-аута по таймеру
  • Введение путем вращения CAS обеспечивает блокировку
  • Реентерабельность может быть достигнута путем проверки существования соответствующей записи.
  • Справедливые блокировки могут быть реализованы путем ожидания в таблице потоков.
  • В случае большого параллелизма легко заблокировать таблицу через конфликт первичных ключей и антидупликацию.Попробуйте произвести первичный ключ в программе для антидупликации.

Распределенная блокировка на основе номера версии поля таблицы

Основываясь на механизме mvcc mysql, соответствующие изменения могут быть сделаны только в том случае, если номер версии непротиворечив.После изменения номер версии увеличивается на 1 и модифицируется CAS.

Распределенная блокировка на основе монопольной блокировки базы данных

Через транзакцию и оператор for update база данных добавит монопольную блокировку к базе данных в рамках транзакции. Когда механизм InnoDB блокируется, блокировки на уровне строк используются только при извлечении через индексы, в противном случае используются блокировки на уровне таблицы.

Распределенная блокировка на основе Redis

Распределенные блокировки на основе методов SETNX() и EXPIRE() Redis.

Семантика метода setnx — SET, если не существует, который в основном имеет два параметра: setnx (ключ, значение). Этот метод является атомарным. Если ключ не существует, успешно установите текущий ключ и верните 1; если текущий ключ уже существует, не удалось установить текущий ключ и вернуть 0.

Метод expire устанавливает время истечения срока действия.Команда setnx не может установить время ожидания ключа. Оно может быть установлено для ключа только через expire().

Если после успешного выполнения setnx выполнение команды expire выполняется успешно, а поток выполнения не работает, может возникнуть явление взаимоблокировки.

Распределенная блокировка на основе методов Redis SETNX(), GET(), GETSET()

  • Метод getset имеет два параметра getset(key, newValue). Этот метод является атомарным, устанавливает значение newValue равным ключу и возвращает старое значение ключа. Предполагая, что ключ изначально не существует, многократное выполнение этой команды будет иметь следующий эффект: getset(key, "value1") возвращает значение null, и значением ключа будет установлено значение1; getset(key, "value2") Возвращаемое значение1 В это время значение ключа будет установлено на значение2. Шаги для использования:

    • setnx(lockkey, текущее время + истечение срока действия), если он возвращает 1, блокировка получена успешно; если он возвращает 0, блокировка не получена и становится 2.
    • get(lockkey) получает значение oldExpireTime и сравнивает это значение с текущим системным временем.Если оно меньше текущего системного времени, считается, что время блокировки истекло, и другим запросам можно разрешить повторное получение, и перейти к 3.

Вычислите newExpireTime = текущее время + время истечения срока действия, затем getset(lockkey, newExpireTime) вернет значение текущего ключа блокировки currentExpireTime. Определите, равны ли currentExpireTime и oldExpireTime. Если они равны, текущая настройка getset выполнена успешно и блокировка получена. Если оно не равно, это означает, что блокировка была получена другим запросом, тогда текущий запрос может сразу вернуться к ошибке или продолжить повторную попытку.

После получения блокировки текущий поток может начать свою собственную бизнес-обработку. Когда обработка будет завершена, сравните свое собственное время обработки с временем ожидания, установленным для блокировки. Если оно меньше времени ожидания, установленного блокировкой, он будет непосредственно выполнить удаление, чтобы снять блокировку; если оно больше, чем Если время ожидания, установленное блокировкой, установлено, блокировка больше не требуется для обработки.

Распределенная блокировка на основе REDLOCK

Redlock — это распределенная блокировка Redis в кластерном режиме, разработанная автором Redis, которая основана на N полностью независимых узлах Redis.

Клиент получает текущее время в миллисекундах. Клиент пытается получить блокировку N узлов (каждый узел получает блокировку так же, как упомянутая выше блокировка кэша), и N узлов получают блокировку с одним и тем же ключом и значением. Клиент должен установить тайм-аут доступа к интерфейсу. Тайм-аут интерфейса должен быть намного меньше, чем тайм-аут блокировки. Например, если блокировка автоматически снимается на 10 секунд, тайм-аут интерфейса должен быть установлен примерно на 5-50 мс. Таким образом, после того, как узел redis не работает, доступ к узлу может быть ограничен по времени как можно скорее, а обычное использование блокировок может быть сокращено.

Клиент вычисляет, сколько времени требуется для получения блокировки, вычитая из текущего времени время, полученное на шаге 1. Только клиент получает блокировки более чем для 3 узлов, а время для получения блокировки меньше, чем время ожидания блокировку.Клиент получает распределенную блокировку.

Время, необходимое клиенту для получения блокировки, равно установленному времени ожидания блокировки за вычетом времени, затраченного на получение блокировки, рассчитанного на шаге 3. Если клиенту не удается получить блокировку, клиент по очереди удаляет все блокировки.

Распределенный замок на основе REDISSON

Redisson — официальный распределенный компонент блокировки Redis. В Redisson, если поток успешно получает блокировку, Redisson запускает сторожевой таймер задачи по времени в фоновом режиме, а задача по времени будет периодически проверять и вызывать renewExpirationAsync(threadId) для возобновления блокировки. Разница во времени планирования времени равна internalLockLeaseTime/3, что составляет 10 секунд, а время блокировки по умолчанию — 30 секунд.

Распределенная блокировка на базе Consul

Распределенные блокировки на основе Consul в основном реализуются с использованием операций получения и освобождения в API хранилища ключей/значений. Операции получения и освобождения аналогичны операциям Check-And-Set. Операция получения вернет true только в том случае, если нет держателя блокировки, а значение Value установлено набором, а сеанс, выполняющий операцию, будет удерживать блокировку ключа, в противном случае он вернет false Операция освобождения заключается в использовании указанного сеанса для снятия блокировки ключа.Если указанный сеанс недействителен, он вернет false, в противном случае он установит значение Value и вернет true.

Принцип исходного кода zk

Zookeeper выполняет следующие роли:

  • Лидер (вождь), отвечающий за инициирование и разрешение голосования, а также обновление статуса системы
  • Ученик (learner), в том числе последователь (follower) и наблюдатель (observer), последователь используется для приема клиентских запросов и возврата результатов клиенту, а также участия в голосовании в процессе избрания мастера
  • Наблюдатель может принимать клиентские подключения и пересылать запросы на запись ведущему, но наблюдатель не участвует в процессе голосования, а только синхронизирует статус ведущего.Назначение наблюдателя - расширение системы и повышение скорости чтения
  • Клиент (клиент), инициатор запроса

Ядром Zookeeper является атомарная трансляция, обеспечивающая синхронизацию между серверами. Протокол, реализующий этот механизм, называется протоколом Zab. Протокол Zab имеет два режима: режим восстановления и режим широковещания.

  • Заб переходит в режим восстановления при запуске службы или при сбое лидера.Реанимация режима восстановления заканчивается, когда лидер избран и большинство серверов завершили синхронизацию с состоянием лидера. Синхронизация состояний гарантирует, что лидер и сервер имеют одинаковое состояние системы.

  • Как только лидер синхронизировал состояние с большинством последователей, он может начать транслировать сообщения, то есть войти в широковещательное состояние. В это время, когда сервер присоединяется к службе zookeeper, он запускается в режиме восстановления, обнаруживает лидера и синхронизирует состояние с лидером. После завершения синхронизации он также участвует в рассылке сообщений. Сервис Zookeeper остается в состоянии Broadcast до тех пор, пока лидер не выйдет из строя или лидер не потеряет поддержку большинства последователей.

Чтобы обеспечить последовательную согласованность транзакций, zookeeper использует возрастающий идентификатор транзакции (zxid) для идентификации транзакций. Все предложения сделаны с добавлением zxid. В реализации zxid — это 64-битное число, а его старшие 32 бита — это эпоха, используемая для определения того, изменилось ли отношение лидера. Младшие 32 бита используются для подсчета.

Собеседования со старшими инженерами-разработчиками обычно связаны с исходным кодом.Почему многие студенты думают, что принцип и исходный код - это ракеты?На самом деле это во многом связано с их собственным опытом. Во-первых, не исключено, что действительно другая часть вопросов на собеседовании касается строительства ракеты. Многие студенты работают над относительно простыми проектами.В качестве примера возьмем Java.Большая часть бизнеса может добавлять,удалять,модифицировать и проверять.У них долгое время формировалась иллюзия,что им не нужно читать исходный код для работы , и даже чувствуют, что чтение исходного кода и ознакомление с принципами им мало поможет. Просмотр хорошего исходного кода требует более глубокого изучения.

Метод сериализации

Сначала разберитесь с сериализацией и десериализацией.

  • Сериализация: объекты могут быть преобразованы в последовательность байтов для удобства хранения.
  • Десериализация: восстановить сериализованную последовательность байтов

Преимущества: Может быть достигнуто "постоянство" объекта.Так называемое постоянство означает, что жизненный цикл объекта не зависит от программы.

Методы сериализации в Java включают сериализацию с помощью собственного потокового метода Java, сериализацию Json, сериализацию FastJson и сериализацию Protobuff. Сериализация Protobuff поддерживает несколько языков.

Собственная сериализация Java

Собственный метод сериализации Java преобразуется с помощью собственного потока Java (преобразование между InputStream и OutputStream). Следует отметить, что класс сущности JavaBean должен реализовывать интерфейс Serializable, иначе он не может быть сериализован.

Json-сериализация

Сериализация Json обычно использует пакет jackson и выполняет некоторые операции через класс ObjectMapper, например преобразование объектов в массивы байтов или преобразование строк json в объекты. В настоящее время большинство компаний используют json в качестве формата данных, возвращаемых сервером. Например, при вызове интерфейса сервера обычный запрос имеет форму xxx.json?a=xxx&b=xxx.

Сериализация FastJson

fastjson — это анализатор и генератор Json, разработанный Alibaba и реализованный на языке Java с хорошей производительностью. Особенности: Быстро, тесты показывают, что fastjson имеет чрезвычайно высокую производительность, превосходя любой другой парсер java json. Мощный, полностью поддерживает Java-бины, коллекции, карты, даты, перечисления, поддерживает общие типы и самоанализ. Никаких зависимостей, может работать непосредственно на Java SE 5.0 и выше для поддержки Android. При его использовании вам необходимо импортировать сторонний jar-пакет FastJson.

Сериализация ProtoBuf

ProtocolBuffer — это легкий и эффективный формат хранения структурированных данных, который можно использовать для сериализации структурированных данных. Подходит для хранения данных или формата обмена данными RPC. Независимый от языка, платформы и расширяемый сериализованный формат структурированных данных, который можно использовать в протоколах связи, хранении данных и других областях.

Преимущества: Кросс-языковость, сериализованные данные занимают меньше места, чем JSON, JSON имеет определенный формат, и еще остается место для сжатия с точки зрения объема данных.

Недостаток: он хранится в двоичном виде, не может быть прочитан напрямую и отредактирован, если у вас нет определения .proto, вы не можете напрямую прочитать какое-либо содержимое протобуфера.

По сравнению с Thrift: их синтаксис аналогичен, и оба поддерживают обратную совместимость версий и прямую совместимость. Сервисы удобно создавать напрямую, не выполняя много другой работы. Protobuffer — это в основном механизм сериализации. Для сравнения производительности при сериализации данных Protobuffer относительно хорош.

Сериализованные объекты ProtoBuff могут быть в значительной степени сжаты, что может значительно уменьшить размер передаваемых данных и повысить производительность системы. Для кэширования большого объема данных также может быть увеличен объем хранения данных в кэше. Оригинальный ProtoBuff должен написать свой собственный файл .proto и преобразовать его в файл java через компилятор, что довольно громоздко. Фреймворк jprotobuf, разработанный Baidu, инкапсулирует оригинальный protobuf Google, упрощает его и предоставляет только методы сериализации и десериализации. На самом деле, он относительно прост в использовании. Достаточно аннотировать поля в JavaBean. Нет необходимости писать файл .proto и практичный компилятор для создания файла .java. jprotobuf от Baidu сделал это за нас. .

настойчивость

Redis — это база данных в памяти, и данные хранятся в памяти, но все мы знаем, что данные в памяти быстро изменяются и подвержены потере. К счастью, Redis также предоставляет нам механизмы сохранения, а именно RDB (Redis DataBase) и AOF (Append Only File).

механизм РБД

RDB фактически сохраняет данные на диске в виде моментальных снимков. Под снимком можно понимать получение данных в текущий момент в виде фотографии и их сохранение.

Постоянство RDB относится к записи моментального снимка набора данных в памяти на диск через определенные промежутки времени. Это также метод сохраняемости по умолчанию.Этот метод заключается в записи данных в памяти в двоичный файл в виде моментального снимка.Имя файла по умолчанию — dump.rdb.

Механизм RDB заключается в сохранении путем создания моментального снимка всех данных в определенный момент, поэтому для реализации этого процесса должен быть механизм триггера. Для RDB предусмотрено три механизма: save, bgsave и автоматизация. Рассмотрим их отдельно:

  • save: эта команда заблокирует текущий сервер Redis.Во время выполнения команды сохранения Redis не может обрабатывать другие команды, пока не завершится процесс RDB.
  • Режим триггера bgsave: при выполнении этой команды Redis будет выполнять операции со снимками асинхронно в фоновом режиме, и снимок также может отвечать на запросы клиентов.
  • Авто-триггер: Авто-триггер выполняется нашим конфигурационным файлом.

РДБ имеет следующие преимущества:

  • Файлы RDB представляют собой компактные полные резервные копии, идеально подходящие для резервного копирования и аварийного восстановления.
  • При создании файла RDB основной процесс redis вызовет fork() дочерний процесс для обработки всей работы по сохранению, а основному процессу не нужно выполнять какие-либо операции ввода-вывода с диском.
  • RDB быстрее, чем AOF, при восстановлении больших наборов данных.

Есть и недостатки: моментальный снимок RDB представляет собой полную резервную копию, которая хранит двоичную сериализованную форму данных памяти, а хранилище очень компактно. При сохранении моментального снимка будет запущен дочерний процесс, который будет отвечать за сохранение моментального снимка. Дочерний процесс будет иметь данные памяти родительского процесса. Если родительский процесс изменяет память, дочерний процесс не будет отражать это, поэтому данные, измененные в течение периода сохранения моментального снимка, не будут отражены, данные могут быть потеряны.

AOF

Полное резервное копирование всегда занимает много времени. Иногда мы предоставляем более эффективный способ AOF. Рабочий механизм очень прост. Redis будет добавлять каждую полученную команду записи в файл через функцию записи. Популярное понимание — ведение журнала.

Подход AOF также поднимает другую проблему. Постоянные файлы могут становиться все больше и больше. Для сжатия постоянных файлов AOF. Redis предоставляет команду bgrewriteaof. Сохраните данные в памяти во временный файл в виде команд, и в то же время разветвите новый процесс, чтобы перезаписать файл. Операция перезаписи файла aof не читает старый файл aof, а перезаписывает содержимое базы данных во всей памяти в новый файл aof с помощью команд, что чем-то похоже на снимок.

AOF также имеет три триггерных механизма:

  • Синхронизация для каждой модификации всегда: синхронное сохранение Каждый раз, когда происходит изменение данных, оно будет немедленно записано на диск, низкая производительность, но лучшая целостность данных
  • Синхронно каждую секунду каждую секунду: асинхронная операция, запись каждую секунду. Если машина выйдет из строя в течение одной секунды, произойдет потеря данных.
  • другое нет: никогда не синхронизировать

AOF может лучше защитить данные от потери.Как правило, AOF выполняет операцию fsync через фоновый поток каждую 1 секунду и теряет до 1 секунды данных; Файлы журналов AOF не имеют накладных расходов на адресацию диска, а производительность записи Очень высокий Высокий, файл нелегко повредить, даже если файл журнала AOF слишком велик, операция фоновой перезаписи не повлияет на чтение и запись клиента, команды файла журнала AOF записываются в очень читаемом виде Кстати, эта функция очень подходит для аварийного восстановления после катастрофических ошибочных удалений. Например, если кто-то случайно использует команду flushall для очистки всех данных, если в это время не произошло фоновой перезаписи, файл AOF может быть скопирован немедленно, последняя команда flushall может быть удалена, а затем файл AOF может быть скопирован. быть возвращены.Через механизм восстановления, все данные автоматически восстанавливаются.

Конечно, для одних и тех же данных файл журнала AOF обычно больше, чем файл моментального снимка данных RDB; после включения AOF поддерживаемое количество запросов в секунду для записи будет ниже, чем количество запросов в секунду для записи, поддерживаемое RDB, поскольку AOF обычно настроен на журнал fsync. файлов раз в секунду , Конечно, производительность все равно очень высокая с fsync раз в секунду, раньше был баг в AOF, то есть при выполнении восстановления данных через лог, записанный AOF, точно такие же данные не восстанавливались .

Репликация Redis master-slave

Подобно репликации master-slave Mysql, хотя Redis очень быстр в чтении и записи, он также создает ситуацию, когда давление чтения особенно велико. Чтобы распределить давление чтения, Redis поддерживает репликацию ведущий-ведомый.Структура ведущий-ведомый Redis может принимать одну структуру главный-несколько-ведомых или каскадную.Репликацию ведущий-ведомый Redis можно разделить на полную синхронизацию и инкрементную синхронизацию в соответствии с полный ли он. На следующем рисунке показана каскадная структура.

Полная синхронизация

Полная репликация Redis обычно происходит на этапе инициализации Slave, в это время Slave необходимо скопировать все данные на Master. Конкретные шаги заключаются в следующем:

  • Подчиненный сервер подключается к главному серверу и отправляет команду SYNC;
  • После того, как главный сервер получает имя SYNC, он начинает выполнять команду BGSAVE для создания файла RDB и использует буфер для записи всех команд записи, выполняемых после этого;
  • После того, как главный сервер BGSAVE выполнен, он отправляет файлы моментальных снимков на все подчиненные серверы и продолжает записывать выполненные команды записи в течение периода отправки;
  • После получения файла снимка с сервера отбросить все старые данные и загрузить полученный снимок;
  • После того, как снапшот главного сервера отправлен, он начинает посылать команду записи в буфер подчиненному серверу;
  • Подчиненный сервер завершает загрузку моментального снимка, начинает получать запросы команд и выполняет команду записи из буфера главного сервера;
Инкрементная синхронизация

Инкрементная репликация Redis относится к процессу синхронизации операций записи с главного сервера на подчиненный сервер, когда подчиненный начинает нормально работать после инициализации.

Процесс инкрементной репликации в основном заключается в том, что каждый раз, когда главный сервер выполняет команду записи, он отправляет эту же команду записи подчиненному серверу, а подчиненный сервер получает и выполняет полученную команду записи.

Стратегия синхронизации Redis master-slave

Когда ведущий и ведомый только что подключены, выполняется полная синхронизация, после завершения полной синхронизации выполняется инкрементная синхронизация. Конечно, ведомое устройство может инициировать полную синхронизацию в любое время, если это необходимо. Стратегия Redis заключается в том, что в любом случае сначала будет предпринята попытка инкрементной синхронизации, а в случае неудачи ведомому устройству потребуется выполнить полную синхронизацию.

Конфигурация репликации master-slave Redis очень проста, она может сделать подчиненный сервер полной копией главного сервера. Несколько важных моментов, которые необходимо прояснить для репликации Redis master-slave:

  • Redis использует асинхронную репликацию. Но начиная с Redis 2.8 подчиненный сервер периодически отвечает количеством обработанных данных из потока репликации.
  • Главный сервер может иметь несколько подчиненных серверов.
  • Подчиненный сервер также может принимать соединения от других подчиненных серверов. В дополнение к нескольким подчиненным серверам, подключенным к главному серверу, несколько подчиненных серверов также могут быть подключены к подчиненному серверу, образуя графоподобную структуру.
  • Репликация Redis master-slave не блокирует сторону главного сервера. То есть, когда несколько подчиненных серверов выполняют первоначальную синхронизацию, главный сервер все еще может обрабатывать запросы.
  • Репликация master-slave также не блокирует подчиненный сервер. Когда ведомое устройство выполняет первоначальную синхронизацию, оно использует старую версию данных для запросов запросов, при условии, что вы настроили ее таким образом в файле конфигурации redis.conf. В противном случае можно настроить ведомое устройство для возврата клиенту ошибки при закрытии потока репликации. Однако, когда первоначальная синхронизация завершена, старый набор данных необходимо удалить и загрузить новый набор данных.В течение этого короткого периода времени подчиненный сервер будет блокировать входящие запросы.
  • Репликация ведущий-ведомый может использоваться для повышения масштабируемости, использования нескольких подчиненных устройств для обработки запросов только на чтение (например, тяжелые операции сортировки могут быть размещены на подчиненных устройствах) или просто для избыточности данных.
  • Использование репликации master-slave может исключить потребление записи данных на диск для главного сервера: настройте «не сохранять» в Redis главного сервера подчиненного сервера. Но эта конфигурация гарантирует, что главный сервер не перезапустится автоматически.

Структура репликации ведущий-ведомый, как правило, подчиненный сервер не может выполнять операции записи, но это не мертво.Причина этого заключается в том, чтобы упростить обеспечение согласованности данных между ведущим и каждым подчиненным.Если данные на подчиненном сервере изменен, то необходимо обеспечить согласованность всех главных и подчиненных серверов, что может быть более ответственным в структуре и логике обработки. Однако вы также можете включить подчиненный сервер для поддержки операций записи через файл конфигурации.

Между мастер-сервером и слейвом будут регулярные звонки, но если на мастере установлен пароль, то если не поставить пароль на слейв, слейв не сможет ничего сделать с мастером, так что если вы иметь пароль на главном сервере, а затем дать его подчиненному соответствующий пароль настройки.

Зачем использовать Spring Cloud

Spring Cloud инкапсулирует ряд зрелых и стабильных сервисных фреймворков, разработанных различными компаниями с помощью Spring Boot, устраняет громоздкие конфигурации и предоставляет разработчикам набор инструментов для разработки распределенных систем, которые просты в использовании, развертывании и обслуживании. Spring Boot — это набор шаблонов быстрой конфигурации для Spring, который позволяет быстро разработать отдельный микросервис на основе Spring Boot. Spring Boot ориентирован на быструю и удобную интеграцию одного человека, а Spring Cloud — на глобальную структуру управления сервисами.

Spring Boot может оставить Spring Cloud для независимого использования проектов разработки, но Spring Cloud неотделим от Spring Boot, который является зависимостью.

Принцип реестра микросервисов

Реестр в основном включает три роли:

  • поставщики услуг
  • потребители услуг
  • Регистрационный центр

Соотношение между ними примерно такое:

  • Когда каждый микросервис запускается, он регистрирует в реестре свой сетевой адрес и другую информацию, а реестр хранит эти данные.
  • Потребитель услуг запрашивает адрес поставщика услуг из реестра и вызывает интерфейс поставщика услуг через этот адрес.
  • Каждая микрослужба взаимодействует с реестром с помощью определенного механизма (например, пульса). Если реестр не может взаимодействовать с микрослужбой в течение длительного времени, регистрация экземпляра будет отменена.
  • При изменении сетевого адреса микросервиса (например, при добавлении экземпляра или изменении IP-адреса и т. д.) он будет повторно зарегистрирован в реестре. Таким образом, потребителю услуги не нужно вручную изменять сетевой адрес поставщика.

Как оценить сервис онлайн и оффлайн регистрации

  • Когда служба запущена, если развертывание порта прошло успешно, она вызовет API регистрации службы, предоставленный центром регистрации, чтобы передать свой собственный сетевой адрес и другие данные для регистрации и обнаружения службы для завершения регистрации;
  • Реестр будет поддерживать связь с экземпляром микрослужбы в реестре с помощью определенного механизма (например, пульса).Если реестр не может связаться с экземпляром микрослужбы в течение длительного времени, информация об экземпляре службы будет удалена из реестра;
  • Когда экземпляр микрослужбы закрыт, он будет активно вызывать автономный интерфейс, предоставленный реестром, для отмены регистрации данных собственного экземпляра микрослужбы из реестра.

Операционные системы и компьютерные сети

что происходит, когда вы посещаете URL-адрес

Когда мы вводим www.google.com в адресную строку браузера и нажимаем Enter, что происходит со страницей, когда мы нажимаем Enter?

Выполните разрешение доменного имени DNS в соответствии с доменным именем, которому оно принадлежит.
  • Браузер Chrome сначала выполнит поиск в собственном кеше DNS браузера (время кеша относительно короткое и может вместить только 1000 кешей), чтобы увидеть, есть ли в его собственном кеше запись, соответствующая www.google.com, и срок ее действия не истек. Если срок действия не истек, синтаксический анализ заканчивается здесь.
  • Если соответствующая запись не будет найдена в собственном кеше браузера, Chrome выполнит поиск в собственном кеше DNS операционной системы, и если он будет найден и срок его действия не истек, он остановит поиск и разрешит до конца.
  • Если он не найден в DNS-кэше системы, попробуйте прочитать файл hosts, чтобы увидеть, есть ли в нем IP-адрес, соответствующий доменному имени, и если он есть, то разрешение выполнено успешно.
  • Если соответствующая запись не найдена в файле hosts, браузер инициирует системный вызов DNS и инициирует запрос разрешения доменного имени на локально сконфигурированный предпочитаемый DNS-сервер.DNS-сервер оператора сначала выполняет поиск в собственном кэше и находит соответствующий , и не истек, синтаксический анализ выполнен успешно. Если соответствующая запись не найдена, DNS оператора инициирует повторяющийся запрос разрешения DNS от имени нашего браузера.
Разрешить IP-адрес, установить TCP-соединение

После получения IP-адреса, соответствующего доменному имени, User-Agent (обычно относится к браузеру) инициирует вызов TCP на порт 80 веб-программы сервера (обычно httpd, nginx и т. д.) со случайным портом (1024

отправить HTTP-запрос

После трехэтапного рукопожатия TCP браузер инициирует http-запрос (см. первый пакет), используя метод http GET, запрошенный URL-адрес — / , а протокол — HTTP/1.0.

Сервер обрабатывает запрос и возвращает ответ

После того, как веб-программа на стороне сервера получает http-запрос, она начинает обрабатывать запрос и после обработки возвращает html-файл в браузер. Закройте TCP-соединение.

Браузер анализирует HTML

После того, как браузер получает файл index.html, он начинает парсить в нем html-код, а при встрече со статическими ресурсами, такими как js/css/image, запрашивает загрузку с сервера (будет использоваться многопоточная загрузка, и поток каждого браузера. В это время используется функция поддержания активности. Когда устанавливается HTTP-соединение, может быть запрошено несколько ресурсов. Порядок загрузки ресурсов соответствует порядку в коде, но поскольку размер каждого ресурс отличается, и браузер И многопоточные запросы запрашивают ресурсы, поэтому, как вы можете видеть на рисунке ниже, порядок, показанный здесь, не обязательно является порядком в коде.

Когда браузер запрашивает статический ресурс (если срок его действия не истек), он инициирует http-запрос к серверу (спрашивая, был ли ресурс изменен с момента последнего изменения), если сервер возвращает код состояния 304 (сообщите браузеру Если на стороне сервера нет модификации), браузер будет напрямую читать локальный файл кеша ресурса.

Отрисовка макета браузера

Наконец, браузер использует собственный внутренний рабочий механизм для рендеринга запрошенных статических ресурсов и html-кода и представляет его пользователю после рендеринга.

Будет ли несогласованность, когда два процесса операционной системы будут записывать данные в разделяемую память?

Общая память позволяет двум или более процессам совместно использовать определенную область памяти. Точно так же, как функция malloc() возвращает указатели на одну и ту же область физической памяти разным процессам. Когда процесс изменяет содержимое этого адреса, другие процессы узнают об этом изменении. Поскольку данные не нужно копировать между клиентом и сервером, данные записываются непосредственно в память без нескольких копий данных, поэтому это самый быстрый IPC.

Однако проблемы возникают, когда несколько программ одновременно считывают и записывают данные в общую память и из нее. Общая память не обеспечивает механизма синхронизации, что заставляет нас часто использовать другие средства для синхронизации между процессами при использовании общей памяти для межпроцессного взаимодействия.

Как реализован тайм-аут API HTTP-запроса

Настройте балансировку нагрузки шлюза и rpc, например, единообразно настройте период тайм-аута интерфейса в шлюзе API. В одной микрослужбе вызовы между службами настраивают тайм-ауты, такие как тайм-аут ленты.

что такое http-протокол

Протокол HTTP — это аббревиатура от Hyper Text Transfer Protocol (протокол передачи гипертекста), который представляет собой протокол передачи для передачи гипертекста с сервера World Wide Web (WWW: World Wide Web) в локальный браузер. Протокол прикладного уровня, основанный на TCP, который не заботится о деталях передачи данных. HTTP (протокол передачи гипертекста) — это протокол прикладного уровня без сохранения состояния, основанный на режиме запроса и ответа. Только следуя унифицированному формату HTTP-запроса, сервер может правильно анализировать запросы, отправленные разными клиентами.Точно так же сервер следует единому формату ответа, чтобы клиент мог правильно анализировать ответы с разных веб-сайтов.

HTTP-запрос состоит из строки запроса, заголовка запроса, пустой строки и тела запроса.

Строка запроса: метод запроса + URL + версия протокола

  • Общие методы запроса: GET, POST, PUT, DELETE, HEAD.
  • Путь к ресурсу (так называемый URL), который должен быть получен клиентом.
  • Номер версии протокола HTTP, используемого клиентом (используя http1.1)

Заголовок запроса: Дополнительное описание запроса, отправленного клиентом на сервер:

  • хост: адрес запроса
  • User-Agent: название и версия операционной системы и браузера, используемых клиентом.
  • Content-Length: длина данных, отправляемых на HTTP-сервер.
  • Content-Type: тип данных параметра
  • Cookie: отправьте значение файла cookie на HTTP-сервер.
  • Accept-Charset: набор символов, который вы получаете
  • Accept-Language: язык, который принимает сам браузер.
  • Принять: типы мультимедиа, принимаемые браузером.

Тело запроса: обычно передаются параметры запроса

application/json:{"name":"value","name1":"value2”}
application/x-www-form-urlencoded: name1=value1&name2=value2
multipart/from-data:表格形式
text/xml
content-type:octets/stream
Какие поля есть в POST-запросе

В заголовке HTTP-запроса вы можете использовать Content-type для указания информации запроса в различных форматах. Протокол HTTP предусматривает, что данные, отправленные POST, должны быть помещены в тело сообщения (entity-body), но протокол не определяет, какую кодировку должны использовать данные. На самом деле разработчик может полностью определить формат тела сообщения, если окончательный HTTP-запрос соответствует указанному выше формату.

После того, как данные отправлены, это имеет смысл только в том случае, если сервер успешно их анализирует. Общие серверные языки, такие как php, python и т. д., а также их фреймворки имеют встроенные функции для автоматического анализа распространенных форматов данных. Сервер обычно узнает, как кодируется тело сообщения в запросе, в соответствии с полем Content-Type в заголовке запроса, а затем анализирует тело.

Атрибут enctype в форме можно использовать для управления кодированием данных формы перед отправкой.Существует три типа enctype:

  • multipart/form-data не кодирует символы и используется для отправки бинарных файлов, два других типа не могут использоваться для отправки файлов;
  • text/plain используется для отправки обычного текстового контента, пробелы преобразуются в знак «+» плюс, специальные символы не кодируются, обычно используются для электронной почты и т.п.;
  • application/x-www-form-urlencoded, кодируются все символы перед отправкой, то есть перед отправкой на сервер кодируются все символы (пробелы преобразуются в плюсы "+", плюсики "+" преобразуются в пробелы , специальные символы в значения ASCII HEX).

где application/x-www-form-urlencoded — тип по умолчанию.

В чем разница между HTTPS и HTTP? Как взаимодействует клиентский сервер HTTPS?

HTTPS: это HTTP-канал, предназначенный для обеспечения безопасности. Короче говоря, это безопасная версия HTTP, то есть к HTTP добавляется слой SSL. Основой безопасности HTTPS является SSL, поэтому для подробного содержания шифрования требуется SSL.

Основные функции протокола HTTPS можно разделить на два типа: одна — установление канала защиты информации для обеспечения безопасности передачи данных, другая — подтверждение подлинности веб-сайта.

Данные, передаваемые по протоколу HTTP, не зашифрованы, т. е. представляют собой открытый текст. Поэтому очень небезопасно использовать протокол HTTP для передачи частной информации. Чтобы гарантировать, что эти личные данные могут быть зашифрованы и переданы, Netscape разработала протокол SSL. (Secure Sockets Layer) для HTTPS был создан для шифрования данных, передаваемых по протоколу HTTP. Проще говоря, протокол HTTPS — это сетевой протокол, созданный на основе протокола SSL+HTTP, который может выполнять зашифрованную передачу и аутентификацию личности и является более безопасным, чем протокол http.

Основные различия между HTTPS и HTTP заключаются в следующем:

  • Протокол https должен идти в центр сертификации, чтобы подать заявку на сертификат.Как правило, бесплатных сертификатов мало, поэтому требуется определенная плата.
  • http — это протокол передачи гипертекста, информация передается в виде открытого текста, а https — безопасный протокол передачи с шифрованием ssl.
  • http и https используют совершенно разные методы подключения и используют разные порты: первый — 80, а второй — 443.
  • Соединение http очень простое и не имеет состояния; протокол HTTPS — это сетевой протокол, созданный на основе протокола SSL+HTTP, который может выполнять зашифрованную передачу и аутентификацию и является более безопасным, чем протокол http.

Клиент должен выполнить следующие шаги при использовании HTTPS для связи с веб-сервером:

  • Клиенты получают доступ к веб-серверу, используя URL-адрес https, требуя SSL-подключения к веб-серверу.
  • После того, как веб-сервер получит запрос клиента, он отправит клиенту копию информации о сертификате веб-сайта (сертификат содержит открытый ключ).
  • Браузер клиента и веб-сервер начинают согласовывать уровень безопасности SSL-соединения, то есть уровень шифрования информации.
  • Браузер клиента устанавливает сеансовый ключ в соответствии с уровнем безопасности, согласованным обеими сторонами, а затем шифрует сеансовый ключ открытым ключом веб-сайта и передает его веб-сайту.
  • Веб-сервер расшифровывает сеансовый ключ своим закрытым ключом.
  • Веб-сервер шифрует связь с клиентом с помощью сеансового ключа.

Хотя HTTPS не является абсолютно безопасным, организации, которые осваивают корневые сертификаты, и организации, которые осваивают алгоритмы шифрования, также могут проводить атаки «человек посередине», но HTTPS по-прежнему остается наиболее безопасным решением в текущей архитектуре.

Скользящее окно -> какие области находятся на стороне клиента и на стороне сервера (подтвержденная передача неподтвержденная непереданная)

Все мы знаем, что когда мы отправляем данные с одной машины на другую, данные не передаются и не могут быть переданы получателю за один раз. Это нетрудно понять, потому что сетевое окружение очень сложное, где-то быстро, где-то медленно. Поэтому операционная система записывает эти данные в непрерывные пакеты данных и отправляет их друг другу с определенной скоростью.

Нам необходимо учитывать такие факторы, как буферы полосы пропускания.Если все данные отправляются одновременно, это только увеличит нагрузку на сеть, что приведет к потере пакетов и повторным попыткам. Поскольку TCP отправляется последовательно, операционная система отправляет эти пакеты данных друг другу пакетами, подобно окну, перемещаясь вперед и назад, поэтому мы называем это протоколом скользящего окна TCP.

В TCP размер окна согласовывается после трехэтапного рукопожатия TCP, и размер окна не является фиксированным, а регулируется в соответствии с условиями сети. Для повышения эффективности передачи TCP регулирует размер окна. TCP обнаруживает потерю пакетов с помощью механизма скользящего окна и регулирует скорость передачи данных в случае потери пакетов.

Для отправителя пакеты данных, которые должны быть отправлены, располагаются в очереди.Для отправителя пакеты данных делятся в общей сложности на четыре категории. Соответственно перед окном было отправлено получателю, и получен ответ от получателя, мы называем его отправленным. В окне два состояния, одно - отправлено получателю, но получатель не подтвердил доставку, называем отправлено, но не подтверждено, и другое - готово к отправке, но не отправлено тем не менее, мы называем это разрешено отправлять, но не отправлять. Последний находится за пределами окна, мы называем его неотправляемым, и он не будет отправлен, пока окно не будет сдвинуто сюда.

Как только предыдущие данные будут подтверждены сервером, окно медленно переместится назад, как показано на рисунке ниже, после подтверждения двух пакетов данных P1 и P2 окно переместится назад, и новые пакеты данных будут изменился с неотправляемого на отправляемое и отправляемое состояние.

Каково значение протокола скользящего окна TCP? Во-первых, конечно, надежность.Скользящее окно будет двигаться назад только после подтверждения начала очереди, чтобы гарантировать, что пакет данных подтвержден и получен получателем. Во-вторых, эффективность передачи. Если окна нет, сервер будет отправлять пакеты беспорядочно. Из-за эффекта заголовка TCP, если предыдущие пакеты не были отправлены успешно, они будут повторять попытки, что приведет к к ухудшению эффективности передачи. Последнее - это стабильность. Размер скользящего окна TCP является результатом согласования всей сложной сети. Он будет динамически регулироваться, чтобы максимально избежать перегрузки сети и сделать ее более стабильной.

что такое днс

Большая часть текущего сетевого доступа разработана на основе протокола TCP/IP, а TCP/IP основан на IP-адресации. И поскольку большинство людей не могут запомнить бессмысленные IP-адреса, они хотят использовать вместо адресов какие-то простые доменные имена, а DNS выступает в роли такого «переводчика». Мы вводим доменное имя, и DNS помогает нам запросить IP-адрес, привязанный к соответствующему доменному имени.

время ожидания http рукопожатия

В соответствии с процессом четырехэтапного рукопожатия, когда tcp закрыт, активная закрывающая сторона войдет в состояние time_wait после отправки последнего пакета ACK, и продолжительность этого состояния составляет 2MSL (MSL относится к максимальному времени выживания сообщения, и данные, которые не принимаются по истечении времени MSL Пакет будет отброшен, 2 минуты рекомендуется в RFC793) По истечении времени он перейдет в закрытое состояние и закроет текущее TCP-соединение.

Активная сторона завершения работы входит в состояние time_wait 2MSL по двум причинам:

  • Убедитесь, что все пакеты данных, сгенерированные в этом TCP-соединении, умирают в сети, чтобы избежать задержки прибытия пакетов данных, сгенерированных в этом TCP-соединении, и не повлиять на использование новых TCP-соединений;
  • Гарантируется, что пассивная закрывающая сторона может получить окончательный ACK. Если последний ACK потерян при доставке по сети, пассивная сторона отключения повторно передаст пакет FIN. Активная закрывающая сторона может получить пакет FIN в течение времени 2MSL и повторно отправить пакет ACK, чтобы перезапустить синхронизацию 2MSL.

Чтобы расширить, что мне делать, если на tcp-клиенте большое количество состояний time_wait?

Подскажите по поводу мультиплексирования соединения.

Связанный с алгоритмом

Расчетный вопрос: вероятность двух королей в покере

Сотый розыгрыш может вытянуть короля среднего размера из 54 карт с вероятностью 2/54=1/27. Во второй раз вы можете взять только оставшегося короля из 53 карт, вероятность 1/53. Таким образом, вероятность того, что два вытянутых являются большим и маленьким королями = (1/27) * (1/53) = 1/1431.

Практическая роль устойчивости алгоритма

Предполагая, что в последовательности сортируемых записей есть несколько записей с одним и тем же ключом, при сортировке относительный порядок этих записей остается неизменным, то есть в исходной последовательности Ai=Aj, а Ai стоит перед Aj, в Сортировка В последней последовательности, если Ai все еще предшествует Aj, говорят, что алгоритм сортировки устойчив, в противном случае алгоритм нестабилен.

Содержимое, подлежащее сортировке, представляет собой несколько числовых атрибутов сложного объекта, и его исходный первоначальный порядок имеет значение, тогда нам нужно сохранить исходное значение сортировки на основе вторичной сортировки, а затем нам нужно использовать устойчивый алгоритм, такой как т.к. Контент для сортировки представляет собой группу объектов, которые изначально были отсортированы по цене.Теперь их нужно отсортировать по объему продаж.Используя алгоритм стабильности, объекты, которые хотят одинаковых объемов продаж, по-прежнему могут отображаться в порядке цены уровень.Только товары с разным объемом продаж будут переупорядочиваться.сортировать. (Конечно, если требование не требует сохранения исходного смысла упорядочения, то использовать алгоритм стабильности все равно будет бессмысленно).

  • Стабильность бессмысленна, если вы просто сортируете числа.
  • Если содержанием сортировки является только определенное числовое свойство сложного объекта, то устойчивость все равно будет бессмысленной (как было сказано выше, она повысит определенную стоимость, но не является решающим фактором, стоимость самого алгоритма это ключ - типа другой алгоритм)
  • Если сортируемое содержимое представляет собой несколько числовых свойств сложного объекта, но его первоначальный порядок не имеет значения, стабильность по-прежнему не имеет смысла.

Алгоритм: K-й наибольший элемент

Найдите k-й (n>=k) самый большой элемент в неупорядоченном массиве длины N.

Есть несколько способов:

  • Метод 1: метод сортировки, сначала отсортируйте неупорядоченный массив от большого к меньшему, k-й элемент после сортировки, естественно, является k-м по величине элементом в массиве. Но временная сложность этого метода составляет O(nlogn), а производительность несколько низкая.
  • Метод 2: метод вставки поддерживает упорядоченный массив массива A длины k, который используется для хранения известных K более крупных элементов. Затем пройдите по неупорядоченному массиву и сравните каждый элемент с наименьшим элементом в массиве A. Если он меньше или равен наименьшему элементу в массиве A, продолжайте обход, если он больше наименьшего элемента в массиве A, вставьте его в массив A. и "выжимает" когда-то наименьший элемент. Временная сложность составляет O(N*k), что подходит для случая, когда k мало по сравнению с N.
  • Метод 3: Метод маленькой верхней кучи, поддерживать небольшую верхнюю кучу с емкостью K, K узлов в куче представляют текущие самые большие K элементов, а вершина кучи, очевидно, является наименьшей среди K элементов. Проходим исходный массив, сравниваем каждый элемент с вершиной кучи, если текущий элемент меньше или равен вершине кучи, продолжаем обход, если элемент больше вершины кучи, ставим текущий элемент в верхней части кучи и настроить двоичную кучу (ниже операции Shen). После завершения обхода вершиной кучи является наименьший из самых больших K элементов массива, то есть K-й по величине элемент. Когда k намного меньше n, временная сложность также может приблизительно считаться равной O(nlogk).
  • Метод 4: метод «разделяй и властвуй», быстрая сортировка использует метод «разделяй и властвуй», чтобы разделить массив на две части, каждый раз увеличивая и уменьшая элементы. Когда мы ищем K-й самый большой элемент, мы также можем использовать эту идею, чтобы использовать определенный элемент A в качестве эталона и заменить все элементы, большие, чем A, слева от массива, а элементы, меньшие, чем A, заменить на справа от массива.

Ниже мы реализуем алгоритм на основе третьего метода:

public static int findNumberK(int[] array, int k) {
        //1.用前k个元素构建小顶堆
        buildHeap(array, k);
        //2.继续遍历数组,和堆顶比较
        for (int i = k; i < array.length; i++) {
            if(array[i] > array[0]) {
                array[0] = array[i];
                downAdjust(array, 0, k);
            }
        }
        //3.返回堆顶元素
        return array[0];
    }

    private static void buildHeap(int[] array, int length) {
        //从最后一个非叶子节点开始,依次下沉调整
        for (int i = (length - 2) / 2; i >= 0; i--) {
            downAdjust(array, i, length);
        }
    }

    /**
     * 下沉调整
     * @param array 待调整的堆
     * @param index 要下沉的节点
     * @param length 堆的有效大小
     */
    private static void downAdjust(int[] array, int index, int length) {
        //temp保存父节点的值,用于最后的赋值
        int temp = array[index];
        int childIndex = 2 * index + 1;
        while (childIndex < length) {
            //如果有右孩子,且右孩子小于左孩子的值,则定位到右孩子
            if (childIndex + 1 < length && array[childIndex + 1] < array[childIndex]) {
                childIndex++;
            }
            //如果父节点小于任何一个孩子的值,直接跳出
            if (temp <= array[childIndex])
                break;
            //无需真正交换,单项赋值即可
            array[index] = array[childIndex];
            index = childIndex;
            childIndex = 2 * childIndex + 1;
        }
        array[index] = temp;
    }

    public static void main(String[] args) {
        int[] array = new int[] {7, 5, 15, 3, 17, 2, 20, 24, 1, 9, 12, 8};
        System.out.println(findNumberK(array, 5));
    }

Конкретные этапы операции следующие:

  1. Соберите первые K элементов массива в кучу.
  2. Продолжайте обход массива и сравнивайте его с вершиной кучи. Если он меньше или равен вершине кучи, продолжайте обход, если он больше вершины кучи, замените элемент наверху кучи и настроить кучу.
  3. Вершина кучи в это время является наименьшим элементом в куче, который является K-м по величине элементом в массиве.

Алгоритм: первый состоит в том, чтобы извлечь m чисел с умеренной вероятностью из массива n чисел.

Эта модель похожа налотерейная модель, есть n лотерейных билетов, по одному на каждого из n человек, как выбрать m человек, чтобы выиграть в лотерею. То есть нам нужно всего лишь смоделировать процесс честной лотереи, чтобы получить m человек с равной вероятностью.

Все мы знаем, что в лотерее нет определенного порядка. У всех одинаковые шансы на победу. следовательно. Самый простой способ — случайным образом расположить n человек в столбец, а затем выбрать m лучших людей, чтобы выиграть в лотерею.

Сам вопрос несложно понять, но ключевой момент в том, чторавная вероятность, и есть неявное условие, то есть его нельзя повторить.

При столкновении с текущим элементом. Используйте вероятность (эта вероятность может быть динамической. Или инвариантной), чтобы решить, остаться ли, если она останется, замените ее выбранным элементом. Другой способ приведен ниже.

Пусть A будет исходным массивом. B — вспомогательный массив (загружает выбранные элементы). A имеет длину n. Длина В равна м. Вам нужно взять m чисел из A и подставить их в B. сделать их равновероятными.

Проходя A, столкнувшись с i-м элементом x, запишите p как количество элементов, которые нужно выбрать из A. q — количество As, отсчитываемое в обратном порядке от x. содержит х. Вероятность того, что x будет выбран, устанавливается равной p/q. Это также может быть достигнуто с равной вероятностью.

  • 1: Вероятность выбора 0-го элемента: m/n
  • 2: Вероятность выбора первого элемента: m/n*(m-1)/(n-1) + (1-m/n)*m/(n-1) = m/n
  • 3: Вероятность того, что будет выбран второй элемент: ... = m/n
  • ....

И так далее, независимо от того, какой элемент выбран, вероятность равна m/n. Ниже мы докажем, что вероятность выбора любого элемента равна m/n.

Предполагая, что будет очень сложно доказать в соответствии с изложенными выше идеями. Но есть очень хитрый способ доказать это.

Рассмотрим модель этой задачи.По сути это модель лотереи.Теперь есть коробка с n лотерейными билетами, на которых написано "in". Или "не в", в. Там m листов с надписью «中», и я спрашиваю сейчас. Какова вероятность выиграть k-ю лотерею? Это явно м/н!

Помните "лотерея не имеет никакого отношения к заказу"? тогда. Самостоятельно запишем выражение для вероятности выигрыша k-й лотереи:

C(m,1)*A(n-1,m-1) / A(n,m) = m/n。

Следовательно, в описанном выше способе работы вероятность выбора любого элемента равна m/n.

Алгоритм: найти самую длинную повторяющуюся подстроку строки

Выберите суффикс, префикс строки суффикса содержит некоторые подстроки строки S, и все подстроки строки S можно косвенно представить, только запросив все суффиксы строки S. Конкретные шаги заключаются в следующем:

  • Сохранить все суффиксы строки S
  • Сортировать все суффиксы (естественный порядок)
  • Сравните самую длинную общую подстроку соседних суффиксов после сортировки (два суффикса, начинающиеся с первого символа, равны для получения общей подстроки) и найдите самую длинную общую подстроку.
public class Main{
    //保存最长公共子串
	static String result = "";
	public static void main(String [] args) throws InterruptedException {
		Scanner sc = new Scanner(System.in);
		String s = sc.nextLine();
		ArrayList<String> list = new ArrayList<String>();
		//得到字符串的所有后缀
		for(int i = s.length()-1;i>=0;i--) {
			list.add(s.substring(i));
		}
		Collections.sort(list);
		int maxLen = 0;
		for(int i = 0;i<s.length()-1;i++) {
			int len = getComlen(list.get(i),list.get(i+1));
			maxLen = Math.max(maxLen, len);
		}
		System.out.println(result+":"+maxLen);
    }
    //得到两个字符串最长公共长度
	public static int getComlen(String str1,String str2) {
		int i;
		for(i =0;i<str1.length()&&i<str2.length();i++) {
			if(str1.charAt(i)!=str2.charAt(i)) {
				break;	
			}
		}
		String temp = str1.substring(0,i);
		if(temp.length()>result.length()) result = temp;
		return i;
	}
	
}

Алгоритм: инвертировать каждую группу узлов K

Односвязный список переворачивается каждые k узлов как группа (не переворачивается, если в конце меньше k)

исходный вопрос leetcode, одно из решений представлено следующим образом:

public class LinkReverse {

    public static Node mhead=null;
    public static Node mtail=null;

    public static Node newLink(int n){
        Node head = new Node();
        head.setData(1);
        head.setNext(null);
        Node tmp = head;
        for(int i=2;i<=n;i++){
            Node newNode = new Node();
            newNode.setData(i);
            newNode.setNext(null);
            tmp.setNext(newNode);
            tmp = newNode;
        }
        return head;
    }


    public static void main(String[] args) {
        Node node = newLink(10);
        pritNode(node);
//        Node node1 = reverseKLink(node,3);
//        Node node1 = reverse(node,2);
        Node node1 = reverseLink3(node,4);
        pritNode(node1);

    }
    public static void pritNode(Node head){
        Node temp = head;
        while(temp !=null){
            System.out.print(temp.getData()+"->");
            temp = temp.getNext();
        }
        System.out.println();
    }

    /*public static Node reverseLink(Node head){
        Node pre=null,cur=head,next=null;
        while(cur!=null){
            next=cur.getNext();
            cur.setNext(pre);
            pre=cur;
            cur=next;
        }
        return pre;
    }*/


    /*public static Node reverseKLink(Node head,int k){
        Node pre=null,cur=head,next=null;

        Node pnext=null,global_head=null;
        int i=0;
        Node tmp=null;

        while(cur!=null){
            next = cur.getNext();

            if(tmp==null) tmp=cur;   //tmp记录当前组反转完最后一个节点
            if(pnext!=null) pnext.setNext(cur);  //pnext是上一组反转完最后一个节点

            cur.setNext(pre);
            pre=cur;
            cur = next;

            i++;
            if(i>=k){  //当前组反转完成的时候
                if(global_head==null){
                    global_head=pre;
                }
                if(pnext!=null){  //将上一组反转完的最后一个节点指向 当前组反转完后的第一个节点
                    pnext.setNext(pre);
                }
                pnext=tmp; //迭代

                i=0;  //新的一组反转时 关键数据初始化
                tmp=null;
                pre=null;
            }
        }
        return global_head;
    }*/

    //反转每组
    public static void inreverse(Node left,Node right){
        Node pre=null,cur=left,next=null;
        while(pre!=right){
            next = cur.getNext();
            cur.setNext(pre);
            pre=cur;
            cur=next;
        }
        if(mtail!=null) mtail.setNext(right);
        mhead=right;
        mtail=left;
    }
    //每k个节点为一组反转
    public static Node reverseLink3(Node head,int k){
        Node cur=head,global_head=head;
        int i=1;
        Node left=null,right=null;
        while(cur!=null){
            if(i%k==1)
                left=cur;
            right=cur;
            cur=cur.getNext();
            if(i%k==0){
                inreverse(left,right);
                if(mtail!=null){
                    mtail.setNext(cur);
                }
                if(global_head==head){
                    global_head = mhead;
                }
            }

            i++;
        }
        return global_head;
    }

}

Алгоритм Вопрос: определить, находится ли IP в Китае

входить: В базе сотни тысяч сегментов отечественных IP (start_ip, end_ip) IP для проверки
вывод: Да или нет

Во-первых, наведите порядок в конфигурации IP-сегмента. Для облегчения сравнения IP-адресов здесь IP-адрес преобразуется в длинный формат.

  • Загрузите данные, возьмите первую и вторую строки и обработайте их с помощью ip2long.
  • Первая строка сохраняется слева, вторая строка сохраняется справа
  • Затем сортировать слева

Получите результат, аналогичный следующему:

('16842752','16843007'),('16843264','16859135')

Далее вы можете использовать метод бинарного поиска, который относительно прост.

Рукописный код: объединить N связанных списков -> оптимизировать до log(n) -> нулевое суждение -> как реализовать изменение структуры данных не разрешено

отLeetCode Вопрос 23 - Объединение упорядоченных связанных списковСамый простой и грубый способ — создать набор, пройтись по всем связанным спискам, добавить его элементы в набор, отсортировать набор в порядке возрастания по массиву, добавить его в новый связанный список и вернуть его.

Временная сложность этого метода: o(n2) внешний слой обходит элементы связанного списка во внутреннем слое, то есть двухуровневый обход и однослойный обход, поэтому результат приблизительно равен o(n2) ; космическая сложность: o (n) определяет переменную listNode со многими длинами массива и определяет длину связанного списка с длиной набора, то есть o (n).

Рассмотрите возможность оптимизации описанного выше метода и используйте метод «разделяй и властвуй» для слияния.

public ListNode mergeKLists(List<ListNode> lists) {
        // write your code here
        if (lists == null || lists.size() == 0) {
            return null;
        }
        ListNode dummy = new ListNode(0);
        ListNode p = dummy;
        Queue<ListNode> queue = new PriorityQueue<ListNode>(lists.size(), new Comparator<ListNode>()
        {   
            @Override
            public int compare(ListNode o1, ListNode o2) {
                return o1.val - o2.val;
            }
        });
        for (ListNode node : lists) {
            if (node != null) {
                queue.offer(node);
            }
        }
        while (!queue.isEmpty()) {
             ListNode node = queue.poll();
                 p.next = node;
                 if (node.next != null) {
                     queue.offer(node.next);
                 }
                 p = p.next;
        }
        return dummy.next;
}
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
        ListNode dummy = new ListNode(-1);
        ListNode p = dummy;
        ListNode p1 = l1;
        ListNode p2 = l2;
        while (p1 != null && p2 != null) {
            if (p1.val < p2.val) {
                p.next = p1;
                p1 = p1.next;
            } else {
                p.next = p2;
                p2 = p2.next;
            }
            p = p.next;
        }
        if (p1 != null) {
            p.next = p1;
        }
        if (p2 != null) {
            p.next = p2;
        }
        return dummy.next;
}    

Открытые вопросы и проектный опыт

Открытые вопросы и проектный опыт необходимо заранее отсортировать в соответствии с их реальным опытом.

Что делать, если одна версия службы обновлена, а другие службы не обновлены?

Обработка совместимости, совместимость на уровне интерфейса, плюс слой адаптеров. С этим нужно обращаться осторожно, и обслуживание особенно проблематично, если проект большой.

Шаблоны проектирования Spring cloud/jdk Шаблоны проектирования в проектах

Это зависит от обычных привычек, и должен быть дух исследования. Посмотрите на отличный исходный код.

  • Режим наблюдателя, публикации и подписки использует класс в java, java.util.observable в качестве издателя и java.util.observer в качестве подписчика.
  • Адаптер: Превратите один интерфейс или класс в другой. Например, java.util.Arrays#asList()
  • Декоратор: динамическое добавление ряда действий к объекту без создания большого количества унаследованных классов из-за различий в этих действиях. Этот шаблон почти вездесущ в JDK, поэтому в следующем списке приведены лишь некоторые типичные примеры. Например, java.io.BufferedInputStream(InputStream)

Общий язык? сравнение питона и джавы

И Java, и Python — очень популярные языки со следующими отличиями:

  • С точки зрения сложности. Python намного проще, чем Java.
  • скорость развития. Python намного превосходит Java
  • скорость бега. java намного превосходит стандартный python, pypy и cython могут догнать java, но ни один из них не является достаточно зрелым, чтобы делать проекты.
  • доступные ресурсы. Ява хапает много, а вот питонов очень мало, особенно китайских ресурсов.
  • степень стабильности. Python 3 и 2 несовместимы, вызывая некоторую путаницу и выход из строя большого количества библиотек классов. Java гораздо более стабильна из-за поддержки предприятий, стоящих за ней.
  • Это с открытым исходным кодом. Python с самого начала был полностью открытым исходным кодом. Java была разработана Sun, но теперь доступен Openjdk для GNU, так что не беспокойтесь.
  • Компилировать или интерпретировать, оба интерпретируются.

Посмотрите на запись моего собеседования в младших классах? Вы спрашивали, почему интервью провалилось? Я сказал, что алгоритм был не очень хорош в то время, кстати, я спросил о моем письменном тесте в этом году.

Обобщить опыт между неудачами.

Планы на будущую карьеру?

Точно ответьте на два аспекта работы и учебы:

  • Пункт первый: представьтесь, чтобы вы серьезно задумались над этим вопросом, и ваш план разработан исходя из текущей реальной ситуации, а не только воображаемой.
  • Второй момент: В плане работы подчеркните свое намерение активно выполнять рабочие задачи и накапливать опыт во всех аспектах, чтобы стать профессионалом в этой области, а также надеяться иметь возможность возглавить команду, стать отличным менеджером и добиться лучшего прогресса для подразделения Большой вклад и беспроигрышный вариант.
  • Третий пункт: Что касается обучения, я планирую продолжить обучение и исследования в профессиональной сфере, совместить практический опыт с профессиональными знаниями и заложить прочную основу для своего карьерного роста.

Это не только общение с интервьюером, но и размышления о собственной жизни.Очень важно.

У вас есть блог? Проект с открытым исходным кодом?

Блоги и проекты с открытым исходным кодом — это все бонусные баллы, а лучшие — это лучшие, поэтому обратите внимание на накопление.

Стажировка? Есть ли что-то, что кажется трудным? Как вы координируете свои действия с остальной командой?

Изучить умение работать в команде и решать проблемы.

Кем ты вырос после стажировки? Где можно улучшить бизнес?

Так же обратите внимание на обобщение предыдущего опыта.

Проект: введение, трудности, детали реализации, похожие на две стороны

Выбрать знакомый и масштабный проект проще.

Какую книгу ты читаешь в последнее время? как учиться

HR хочет использовать этот вопрос, чтобы изучить путь и метод приобретения знаний и опыта. Благодаря обычным привычкам чтения мы можем понять структуру знаний и привычки к поиску знаний соискателей.

На метод обучения можно ответить в соответствии с вашей реальной ситуацией, такой как повторная практика, укрепление памяти, применение научных методов и так далее. Способность к обучению очень важна, и нужно это подчеркнуть.

Советы по собеседованию

Вопросы для интервью, перечисленные выше, могут только помочь учащимся понять большинство вопросов, и они не охватывают все.Вот некоторые материалы для обзора интервью для младших школьников и учителей только для справки.

Младший брат получил предложения от Ali, Douyin, Tencent и Meituan и в настоящее время работает в Ali. Прежде всего, я предоставлю вам обзорный материал, подготовленный им самим.

частная коллекция

Благосостояние, ответьте «интервью» в фоновом режиме, вы можете получить файл PDF. Ниже приведены некоторые обзорные материалы для ознакомления.Качество контента очень высокое.Алгоритм также необходим для собеседования в компании первой линии, такой как Toutiao, поэтому я также даю вам ссылку на классический алгоритм.

Основы компьютера и основы Java
алгоритм
  • Longest Increasing Subsequence variants:

Ли ТСО's.com/problems/… Ли TCO.com/problems/pull… Ли ТСО's.com/problems/as… Ли TCO.com/problems/horse… Ли TCO.com/problems/rage… Ли ТСО's.com/problems/… Ли ТСО's.com/problems/…

  • Partition Subset:

Lee TCO's.com/problems/afraid…

  • BitMasking:

Lee TCO's.com/problems/afraid…

  • Longest Common Subsequence Variant:

Ли ТСО's.com/problems/… .com/problems/quota… Ли ТШО Lee TCO's.com/problems/th… Ли TCO.com/problems/m…

  • Palindrome:

Lee TCO's.com/problems/afraid… Lee TCO's.com/problems/afraid…

  • Coin Change variant:

Ли TCO.com/problems/co… Ли TCO.com/problems/co… Ли TCO.com/problems/co… Ли TCO.com/problems/PE… Ли TCO.com/problems/m… Ли TCO.com/problems/pull…

  • Matrix multiplication variant:

Ли TCO.com/problems/m… Ли TCO.com/problems/m… Ли ТСО's.com/problems/no…

  • Matrix/2D Array:

Ли TCO.com/problems/horse… Lee TCO's.com/problems/people... Ли TCO.com/problems/степени… Lee TCO's.com/problems/ вдруг… Ли TCO.com/problems/horse… Ли TCO.com/problems/m…

  • Hash + DP:

Ли TCO.com/problems/he… Ли ТСО's.com/problems/… Ли ТСО's.com/problems/… Ли TCO.com/problems/horse…

  • State machine:

Lee TCO's.com/problems/не голоден… Lee TCO's.com/problems/не голоден… Lee TCO's.com/problems/не голоден… Lee TCO's.com/problems/не голоден… Lee TCO's.com/problems/не голоден… Lee TCO's.com/problems/не голоден…

  • Depth First Search + DP:

Ли ТСО's.com/problems/even… Lee TCO's.com/problems/maybe…

  • Minimax DP:

Lee TCO's.com/problems/cheat… Ли TCO.com/problems/body…

  • Misc:

Ли ТСО's.com/problems/personal… Ли ТСО's.com/problems/… Ли TCO.com/problems/PE… Ли TCO.com/problems/co… Ли ТСО's.com/problems/… Ли TCO.com/problems/rage…

Священные Писания

Что касается писаний лиц, каждый должен заглянуть на сайт Niuke.com, который содержит очень много информации.

Благосостояние, организованное

напиши в конце

Овладение базовыми знаниями – это процесс накопления.Хотя навыков на собеседовании много, но можно наверстать упущенное. Но если мы сможем сохранить хорошие учебные привычки и самое главное стремление к знаниям в мирное время, мы сможем сделать больше с меньшими затратами при подготовке к интервью.

Наконец, я оставляю вам вопрос, над которым вы должны подумать, чтобы проверить эффект вашего собственного обучения😀, добро пожаловать, чтобы написать свои мысли в области сообщений или личное сообщение мне, чтобы общаться. Если это действительно невозможно сделать, автор, наконец, предоставит идеи и ответы.

  • Алгоритм Вопрос: Расчет пиковых значений пользователя в сети

Вход: журнал пользователя (время, user_id, логин | выход)
Вывод: пиковое количество людей онлайн одновременно, пиковый сегмент (90% пика) (например, с 19:50 до 22:10, пиковое значение составляет 300 миллионов, а минимум 270 миллионов)

Рекомендуемое чтение

Коллекция интервью

Подписывайтесь на свежие статьи, приглашаю обратить внимание на мой публичный номер

微信公众号