Обобщите часто задаваемые вопросы в интервью по разработке Java и продолжайте обновлять~

Java Redis база данных сервер
Обобщите часто задаваемые вопросы в интервью по разработке Java и продолжайте обновлять~

Адрес гитхаба:GitHub.com/В облаке 1…, если это поможет вам приветствовать звезду

база данных

mysql

Зачем использовать столбец с автоматическим приращением в качестве первичного ключа

  1. Если мы определим первичный ключ (PRIMARY KEY), InnoDB выберет первичный ключ в качестве кластеризованного индекса.Если первичный ключ явно не определен, InnoDB выберет первый уникальный индекс, который не содержит значений NULL, в качестве индекса первичного ключа. , Если такого нет. Для уникального индекса InnoDB выберет встроенный 6-байтовый ROWID в качестве неявного кластеризованного индекса (ROWID увеличивается по мере записи записей строк, и на этот ROWID не так ссылаются, как на ROWID ORACLE, т.е. скрытый).

  2. Сами записи данных хранятся на листовых узлах основного индекса (B+Tree). Это требует, чтобы каждая запись данных в одном и том же листовом узле (размером является одна страница памяти или страница диска) хранилась в порядке первичного ключа, поэтому всякий раз, когда вставляется новая запись, MySQL будет вставлять ее в соответствующий узел в соответствии с его первичный ключ и положение, если страница достигает коэффициента загрузки (InnoDB по умолчанию 15/16), открыть новую страницу (узел)

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

  4. Если используется несамоинкрементный первичный ключ (если это идентификационный номер или номер студента и т. д.), поскольку значение вставляемого каждый раз первичного ключа примерно случайно, каждая новая запись должна быть вставлена ​​в определенную позицию в середина существующей страницы индекса MySQL должен перемещать данные, чтобы вставить новую запись в нужное место, и даже целевая страница может быть записана обратно на диск и сброшена из кеша, а затем считана с диска, что добавляет много накладных расходов, а частые операции перемещения и подкачки вызывают большую фрагментацию, что приводит к недостаточно компактной структуре индекса.Позже для перестроения таблицы и оптимизации заполнения страницы необходимо использовать OPTIMIZE TABLE.

Почему использование индексации данных может повысить эффективность

  1. Хранение индексов данных упорядочено
  2. В случае порядка запрос данных через индекс не требует обхода записей индекса.
  3. В крайних случаях эффективность запроса индекса данных равна эффективности запроса дихотомии, которая близка к log2(N).

Разница между индексом дерева B+ и хэш-индексом

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

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

Преимущества хэш-индексов:

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

Сценарии, в которых хэш-индексы неприменимы:

  1. Запросы диапазона не поддерживаются
  2. Сортировка завершения индекса не поддерживается
  3. Крайнее левое правило сопоставления префиксов для объединенных индексов не поддерживается.

Как правило, древовидная структура индекса B+ подходит для большинства сценариев, и более выгодно использовать хэш-индекс в следующих сценариях:

В таблице HEAP, если хранимые данные имеют низкую степень повторения (то есть кардинальность велика), данные столбца в основном представляют собой запрос эквивалентности, а когда нет запроса диапазона и сортировки, это особенно подходит использовать хеш-индекс, например, этот SQL:

select id,name from table where name='李明'; — 仅等值查询

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

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

Разница между B-деревом и B+ деревом

  1. B-дерево, каждый узел хранит ключ и данные, все узлы образуют это дерево, а указатель конечного узла равен нулю, а листовой узел не содержит никакой ключевой информации.
    这里写图片描述
  2. В дереве B+ все листовые узлы содержат информацию обо всех ключевых словах и указатели на записи, содержащие эти ключевые слова, а сами листовые узлы связаны в порядке размера ключевых слов от малого к большому, а все неконечные узлы могут рассматриваться как часть индекса, а узел содержит только самый большой (или самый маленький) ключ в корневом узле своего поддерева. (И неконечные узлы B-дерева также содержат достоверную информацию, которую необходимо искать)

这里写图片描述

Почему говорят, что B+ больше подходит для индексации файлов и баз данных операционных систем в практических приложениях, чем B-дерево?

  1. Затраты на чтение и запись диска B+ ниже Внутренний узел B+ не имеет указателя на конкретную информацию ключевого слова. Следовательно, его внутренние узлы меньше, чем B-деревья. Если все ключевые слова одного и того же внутреннего узла хранятся в одном блоке диска, тем больше ключевых слов может содержать блок диска. Чем больше ключевых слов нужно искать, тем больше считывать в память за один раз. Условно говоря, количество операций чтения и записи ввода-вывода также уменьшается.

  2. Эффективность запросов B+-дерева более стабильна Потому что нетерминал — это не тот узел, который окончательно указывает на содержимое файла, а только индекс ключевого слова в листовом узле. Таким образом, любой поиск по ключевому слову должен проходить по пути от корневого узла к конечному узлу. Длина пути всех запросов с ключевыми словами одинакова, что обеспечивает одинаковую эффективность запроса для всех данных.

совместный индекс mysql

  1. Индекс объединения — это индекс двух или более столбцов. Для совместного индекса: Mysql использует поля в индексе слева направо, запрос может использовать только часть индекса, но только самую левую часть. Например, индекс является ключевым индексом (a,b,c). Он может поддерживать три комбинации a, a,b, a,b,c для поиска, но не поддерживает b,c для поиска. Когда крайнее левое поле является постоянной ссылкой, индекс очень эффективен.
  2. Дополнительные столбцы в индексе позволяют сузить область поиска, но использование одного индекса с двумя столбцами — это не то же самое, что использование двух отдельных индексов. Структура составного индекса аналогична телефонной книге, где имя человека состоит из имени и фамилии, а телефонная книга сортируется сначала по парам фамилий, а затем по именам для людей с одинаковыми именами. фамилия. Телефонная книга очень полезна, если вы знаете фамилию; еще полезнее, если вы знаете имя и фамилию, но она бесполезна, если вы знаете только имя, но не фамилию.

При каких обстоятельствах не следует создавать индексы или создавать меньше индексов?

  1. слишком мало записей в таблице
  2. Часто вставляемые, удаляемые, изменяемые таблицы
  3. Поля таблицы с повторяющимися данными и равномерно распределенными данными, если в таблице 100 000 строк записей, есть поле A только с двумя значениями T и F, а вероятность распределения каждого значения составляет около 50%, то создайте поле для этой таблицы Поле A. Индексы обычно не улучшают скорость запросов к базе данных.
  4. Поля таблицы, которые часто запрашиваются вместе с основным полем, но имеют больше значений индекса основного поля.

Разделение MySQL

Что такое секционирование таблицы?

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

Разница между разделом таблицы и подтаблицей

Подтаблицы: относится к разделению таблицы на несколько разных таблиц по определенным правилам. Например, записи пользовательских заказов разделены на несколько таблиц в зависимости от времени.

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

Каковы преимущества секционирования таблиц?

  1. Данные таблицы разделов могут быть распределены по разным физическим устройствам, что позволяет эффективно использовать несколько аппаратных устройств. 2. Может хранить больше данных, чем один диск или файловая система.
  2. Оптимизируйте запросы. Когда оператор where содержит условия секционирования, вы можете просматривать только одну или несколько секционированных таблиц для повышения эффективности запроса; когда задействованы операторы sum и count, вы также можете обрабатывать их параллельно на нескольких разделах и, наконец, суммировать результаты.
  3. Секционированные таблицы легче поддерживать. Например, если вы хотите удалить большой объем данных в пакетном режиме, вы можете очистить весь раздел.
  4. Секционированные таблицы можно использовать, чтобы избежать некоторых особых узких мест, таких как взаимоисключающий доступ к одному индексу в InnoDB, конкуренция за блокировку inode в ext3 и т. д.

Ограничивающие факторы для секционированных таблиц

  1. Таблица может иметь до 1024 разделов.
  2. В MySQL 5.1 выражение раздела должно быть целым числом или выражением, которое возвращает целое число. Поддержка разделения нецелочисленных выражений была предоставлена ​​в MySQL 5.5.
  3. Если в поле раздела есть столбец первичного ключа или уникального индекса, необходимо включить все столбцы первичного ключа и уникального индекса. То есть: поле раздела либо не содержит столбцов первичного ключа или индекса, либо содержит все столбцы первичного ключа и индекса.
  4. Ограничения внешнего ключа нельзя использовать в секционированных таблицах.
  5. Разбиение MySQL применимо ко всем данным и индексам таблицы, оно не может разбивать только данные таблицы без разбиения индекса, не может разбивать только индекс без разбиения таблицы и не может разбивать только часть данных таблицы.

Как определить, поддерживает ли текущий MySQL разделение?

Команда: показать переменные типа '%partition%' Результат выполнения:

mysql> показывать переменные типа '%partition%'; +-------------------+-------+ |имя_переменной |значение | +-------------------+-------+ |иметь_разметку |ДА | +-------------------+-------+ 1 ряд в наборе (0,00 сек) Значение have_partintioning равно YES, что указывает на то, что разделение поддерживается.

Какие типы разделов поддерживает MySQL?

  1. RANGE Partitioning: Этот режим позволяет разделить данные на разные диапазоны. Например, таблицу можно разделить на несколько разделов по годам.
  2. LIST Partitioning: этот режим позволяет системе разбивать данные по предварительно заданному списку значений. В соответствии с разделом значений в списке отличие от RANGE состоит в том, что значение диапазона раздела диапазона является непрерывным.
  3. ХЭШ-раздел: этот режим позволяет вычислить хэш-ключ одного или нескольких столбцов таблицы и, наконец, разбить область данных, соответствующую различным значениям хэш-кода. Например, вы можете создать таблицу, которая разделяет первичный ключ таблицы.
  4. Раздел KEY: расширение описанного выше режима хеширования, здесь хэш-ключ генерируется системой MySQL.

Четыре уровня изоляции

  1. Сериализуемый: избегайте грязных чтений, неповторяемых чтений и фантомных чтений.
  2. Повторяемое чтение (повторяемое чтение): позволяет избежать возникновения грязных чтений и неповторяемых чтений.
  3. Чтение зафиксировано (read commit): во избежание возникновения грязных чтений.
  4. Чтение незафиксированного: самый низкий уровень, не гарантируется ни при каких обстоятельствах.

О МВВК

Механизм хранения MySQL InnoDB реализует протокол управления параллелизмом на основе нескольких версий — MVCC (управление параллелизмом нескольких версий) (Примечание: в отличие от MVCC, это управление параллелизмом на основе блокировки). Самое большое преимущество MVCC: чтение без блокировки, чтение и запись без конфликтов. В OLTP-приложениях с большим количеством операций чтения и меньшим количеством операций записи очень важно, чтобы операции чтения и записи не конфликтовали, что значительно увеличивает одновременную производительность системы.На данном этапе почти все СУБД поддерживают MVCC.

  1. LBCC: контроль параллелизма на основе блокировки, контроль параллелизма на основе блокировки.
  2. MVCC: Multi-Version Concurrency Control, протокол управления многоверсионным параллелизмом. Механизм параллелизма, основанный исключительно на блокировке, имеет низкий уровень параллелизма.MVCC — это улучшение управления параллелизмом на основе блокировки, в основном для улучшения параллелизма операций чтения.

В управлении параллелизмом MVCC операции чтения можно разделить на две категории:

  1. Чтение моментального снимка: чтение видимой версии записи (возможно, исторической версии) без блокировки (блокировка общей блокировки чтения не добавляется, поэтому она не будет блокировать запись других транзакций).
  2. Текущее чтение: считывается последняя версия записи, и запись, возвращенная текущим чтением, будет заблокирована, чтобы гарантировать, что другие транзакции не будут одновременно изменять запись.

Преимущества блокировки на уровне строки:

  1. При доступе к разным строкам во многих потоках возникает всего несколько конфликтов блокировки.
  2. Откат с небольшими изменениями
  3. Одна строка может быть заблокирована на долгое время.

Недостатки блокировки на уровне строки:

  1. Занимает больше памяти, чем блокировка на уровне страницы или таблицы.
  2. Медленнее, чем блокировка на уровне страницы или таблицы при использовании на больших частях таблицы, потому что вам нужно получить больше блокировок.
  3. Значительно медленнее, чем другие блокировки, если вы часто выполняете операции GROUP BY для большей части данных или часто сканируете всю таблицу.
  4. С высокоуровневой блокировкой вы также можете легко масштабировать свое приложение, поддерживая различные типы блокировки, поскольку стоимость блокировки меньше, чем блокировка на уровне строки.

Простой пример триггера MySQL

  1. CREATE TRIGGER -- Триггер должен иметь имя длиной до 64 символов, за которым может следовать разделитель.В основном это то же самое, что и другие объекты в MySQL.
  2. { BEFORE | AFTER } -- триггеры имеют настройки времени выполнения: можно установить до или после наступления события.
  3. { INSERT | UPDATE | DELETE } -- Также можно установить триггерные события: они могут запускаться во время выполнения вставки, обновления или удаления.
  4. ON --Триггер принадлежит таблице: когда в этой таблице выполняется операция вставки, обновления или удаления, триггер активируется Мы не можем запланировать два события для одного и того же триггера таблицы.
  5. FOR EACH ROW -- Интервал выполнения триггера: Предложение FOR EACH ROW указывает триггеру выполнять действие через каждую вторую строку, а не один раз для всей таблицы.
  6. -- триггер содержит запускаемый SQL-оператор: оператор здесь может быть любым допустимым оператором, включая составной оператор, но на оператор здесь распространяются те же ограничения, что и на функцию.

что такое хранимая процедура

Проще говоря, это набор операторов SQL с мощными функциями, которые могут реализовывать некоторые более сложные логические функции, подобные методам в языке JAVA;

ps: Хранимые процедуры чем-то похожи на триггеры, все они представляют собой набор наборов SQL, но хранимые процедуры вызываются активно, и их функции более мощные, чем триггеры.Триггеры автоматически вызываются после того, как что-то сработало;

Каковы особенности

  1. Есть входные и выходные параметры, переменные могут быть объявлены, есть if/else, case, while и другие управляющие операторы, а сложные логические функции могут быть реализованы путем написания хранимых процедур;
  2. Общие черты функций: модульность, инкапсуляция, повторное использование кода;
  3. Скорость высокая, только первое выполнение должно пройти этапы компиляции и оптимизации, а последующие вызовы могут выполняться напрямую, минуя вышеуказанные шаги;
DROP PROCEDURE IF EXISTS `proc_adder`;
DELIMITER ;;
CREATE DEFINER=`root`@`localhost` PROCEDURE `proc_adder`(IN a int, IN b int, OUT sum int)
BEGIN
    #Routine body goes here...

    DECLARE c int;
    if a is null then set a = 0; 
    end if;
  
    if b is null then set b = 0;
    end if;

    set sum  = a + b;
END
;;
DELIMITER ;

set @b=5;
call proc_adder(0,@b,@s);
SELECT @s as sum;



create table tab2(
   tab2_id varchar(11)
);

DROP TRIGGER if EXISTS t_ai_on_tab1;
create TRAILING t_ai_on_tab1
AFTER INSERT ON tab1
for EACH ROW
BEGIN
   INSERT INTO tab2(tab2_id) values(new.tab1_id);
end;

INSERT INTO tab1(tab1_id) values('0001');

SELECT * FROM tab2;

Оптимизация MySQL

  1. Включите кэширование запросов для оптимизации запросов
  2. Объясните свой запрос на выборку, который может помочь вам проанализировать узкое место производительности оператора запроса или структуры таблицы. Результаты запроса EXPLAIN также расскажут вам, как используются первичные ключи вашего индекса, как выполняется поиск и сортировка ваших таблиц данных.
  3. При использовании ограничения 1, когда имеется только одна строка данных, механизм базы данных MySQL прекратит поиск после нахождения строки данных, вместо того чтобы продолжать поиск следующей строки данных, соответствующей записи.
  4. Индексировать поле поиска
  5. Используйте ENUM вместо VARCHAR, если у вас есть такие поля, как «пол», «страна», «нация», «статус» или «отдел», вы знаете, что значение этих полей ограничено и фиксировано, тогда вам следует использовать ENUM вместо VARCHAR.
  6. Подготовленные отчеты Подготовленные операторы, как и хранимые процедуры, представляют собой набор операторов SQL, которые выполняются в фоновом режиме, и мы можем получить много преимуществ от использования подготовленных операторов, будь то проблема производительности или проблема безопасности. Подготовленные операторы могут проверять некоторые из ваших связанных переменных, которые могут защитить вашу программу от атак «SQL-инъекций».
  7. вертикальный стол
  8. Выберите правильный механизм хранения

Разница между ключом и индексом

  1. Ключом является физическая структура базы данных, которая содержит два уровня значения и функции, один из которых является ограничением (акцент на ограничениях и стандартизация структурной целостности базы данных), а другой — индексом (используется для вспомогательных запросов). Включая первичный ключ, уникальный ключ, внешний ключ и т. д.
  2. Индекс - это физическая структура базы данных. Он предназначен только для вспомогательных запросов. Когда он создается, он будет храниться в структуре, подобной каталогу, в другом табличном пространстве (табличное пространство innodb в mysql). Если индекс подлежит классификации, он делится на префиксный индекс, полнотекстовый индекс и т. д.;

В чем разница между MyISAM и InnoDB в Mysql?

разница:

  1. InnoDB поддерживает транзакции, а MyISAM нет.Для InnoDB каждый язык SQL инкапсулируется в транзакцию по умолчанию и автоматически фиксируется, что повлияет на скорость, поэтому лучше всего поставить несколько языков SQL между началом и фиксацией, чтобы сформировать сделка;

  2. InnoDB поддерживает внешние ключи, а MyISAM — нет. Преобразование таблицы InnoDB с внешними ключами в MYISAM не удастся;

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

  4. InnoDB не сохраняет определенное количество строк в таблице, и при выполнении команды select count(*) from table требуется полное сканирование таблицы. MyISAM использует переменную для хранения количества строк во всей таблице.При выполнении приведенного выше оператора вам нужно только прочитать переменную, что очень быстро;

  5. Innodb не поддерживает полнотекстовое индексирование, в то время как MyISAM поддерживает полнотекстовое индексирование, а MyISAM имеет более высокую эффективность запросов;

как выбрать:

  1. Если вы хотите поддерживать транзакции, если хотите, выберите innodb, если вам это не нужно, вы можете рассмотреть MyISAM;

  2. Если подавляющее большинство таблиц являются только запросами на чтение, вы можете рассмотреть MyISAM, а если у вас есть и чтение, и запись, используйте InnoDB.

  3. После сбоя системы MyISAM труднее восстановить, допустимо ли это?

  4. Начиная с MySQL 5.5 Innodb стал движком по умолчанию Mysql (ранее MyISAM), что показывает, что его преимущества очевидны для всех.Если не знаете, что использовать, то используйте InnoDB, по крайней мере, это будет не плохо.

Рекомендации по созданию таблицы базы данных

1. Рациональность названий полей и конфигурации полей

  1. Удалите ненужные поля

  2. Именование полей должно иметь правила и соответствующие значения (не часть английского языка, часть пиньинь и поля с неизвестными значениями, такими как abc).

  3. Старайтесь не использовать аббревиатуры для именования полей (большинство аббревиатур не могут пояснить значение поля)

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

  5. Не используйте зарезервированные слова или ключевые слова для имен полей.

  6. Сохраняйте имена и типы полей согласованными

  7. Тщательно выбирайте типы номеров

  8. Оставьте достаточно места для текстовых полей

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

  1. Добавьте маркеры удаления (например, оператор, время удаления)

  2. Создайте механизм версий

3. Рациональная конфигурация структуры таблицы

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

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

4. Другие предложения

  1. Для больших полей данных хранятся отдельные таблицы, чтобы повлиять на производительность (например, поля профиля).

  2. Используйте тип varchar вместо char, потому что varchar динамически выделяет длину, а указанная длина char является фиксированной.

  3. Создайте первичный ключ для таблицы. Для таблицы без первичного ключа это оказывает определенное влияние на определение запроса и индекса.

  4. Чтобы поле таблицы не работало как пустое, рекомендуется установить значение по умолчанию (например, тип int, чтобы установить значение по умолчанию равным 0) в индексном запросе, эффективность очевидна сразу!

  5. Лучше всего создавать индексы для уникальных и ненулевых полей. Создание слишком большого количества индексов окажет определенное влияние на последующие вставки и обновления (учитывайте реальную ситуацию при создании).

redis

проблема с одним потоком Redis

Один поток означает, что модуль сетевых запросов использует один поток (поэтому нет необходимости учитывать безопасность параллелизма), то есть один поток обрабатывает все сетевые запросы, а другие модули по-прежнему используют несколько потоков.

Почему Redis может выполняться быстро

  1. Подавляющее большинство запросов — это операции с чистой памятью (очень быстрые).
  2. Однопоточный, избегающий ненужных переключений контекста и условий гонки
  3. Неблокирующий ввод-вывод — мультиплексирование ввода-вывода

Внутренняя реализация Redis

Внутренняя реализация принимает epoll и использует простую структуру событий, реализованную самим epoll+. Чтение, запись, закрытие и соединение в epoll преобразуются в события, а затем используются функции мультиплексирования epoll, чтобы не тратить немного времени на io.Эти три условия не независимы друг от друга, особенно первое, если запрос все это отнимает много времени, использует один поток и имеет низкую пропускную способность и производительность. Redis выбирает подходящее техническое решение для особых сценариев.

Redis о безопасности потоков

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

Каковы преимущества использования Redis?

  1. Быстро, потому что данные хранятся в памяти, аналогично HashMap, преимущество HashMap в том, что временная сложность поиска и работы составляет O(1)
  2. Поддержка расширенных типов данных, поддержка строки, списка, набора, отсортированного набора, хэша
  3. Транзакции поддерживаются, а операции атомарны, так называемая атомарность означает, что все изменения данных либо выполняются, либо не выполняются вообще.
  4. Богатые возможности: можно использовать для кеша, сообщения, установить время истечения срока действия в соответствии с ключом, он будет автоматически удален после истечения срока действия

В чем преимущества Redis перед memcached?

  1. Все значения memcached представляют собой простые строки, а redis, как их замена, поддерживает более богатые типы данных.
  2. Redis намного быстрее, чем memcached
  3. Redis может сохранять свои данные
  4. Redis поддерживает резервное копирование данных, то есть резервное копирование данных в режиме master-slave.
  5. Используются разные базовые модели, а также базовые методы реализации и прикладные протоколы для связи с клиентами. Redis напрямую сам строит механизм ВМ, потому что, если общая система вызывает системные функции, она будет тратить определенное количество времени на перемещение и запрос.
  6. Размер значения: Redis может достигать 1 ГБ, а memcache — всего 1 МБ.

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

Принцип процесса:

  1. Когда связь MS установлена ​​между подчиненной базой данных и главной базой данных, команда SYNC будет отправлена ​​в главную базу данных.
  2. После того, как основная библиотека получит команду SYNC, она начнет сохранять снимки в фоновом режиме (процесс сохранения RDB) и кэшировать команды записи, полученные в течение периода.
  3. Когда моментальный снимок будет завершен, главный Redis отправит файл моментального снимка и все кэшированные команды записи подчиненному Redis.
  4. После получения от Redis файл снапшота будет загружен и полученная кешированная команда будет выполнена
  5. После этого мастер Redis будет отправлять команду из Redis всякий раз, когда он получает команду записи, чтобы обеспечить согласованность данных.

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

Преимущества и недостатки двух методов персистентности Redis

  1. Постоянство RDB может генерировать моментальные снимки наборов данных на определенный момент времени через определенные промежутки времени.
  2. AOF постоянно записывает все команды записи, выполняемые сервером, и восстанавливает набор данных, повторно выполняя эти команды при запуске сервера.
  3. Redis также может использовать как сохранение AOF, так и сохранение RDB. Когда Redis перезапустится, он будет использовать файл AOF для восстановления набора данных ограниченным образом, поскольку набор данных, сохраненный в файле AOF, обычно более полный, чем набор данных, сохраненный в файле RDB.

Преимущества РДБ:

  1. RDB — это очень компактный файл, который содержит набор данных Redis на определенный момент времени. Этот файл отлично подходит для резервного копирования: например, вы можете создавать резервную копию файла RDB каждый час в течение последних 24 часов и файла RDB каждый день месяца. Таким образом, вы всегда сможете восстановить свой набор данных до другой версии, даже если у вас возникнут проблемы.

  2. RDB отлично подходит для аварийного восстановления: это один файл, и все настолько компактно, что его можно отправить (после шифрования) в другой центр обработки данных или в Amazon S3.

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

  4. RDB быстрее, чем AOF, при восстановлении больших наборов данных

Каковы общие проблемы с производительностью Redis? Как решить?

  1. Мастер записывает снимки памяти, а команда сохранения назначает функцию rdbSave, которая блокирует работу основного потока.Когда снимок относительно большой, влияние на производительность очень велико, и служба будет периодически приостанавливаться, поэтому мастер не должен записывать снимки памяти.
  2. Мастер AOF является постоянным. Если файл AOF не перезаписывается, влияние этого метода сохранения на производительность минимально. Однако файл AOF будет продолжать расти. Если файл AOF слишком велик, это повлияет на скорость восстановления Мастер перезагрузки. Ведущему устройству лучше не выполнять никакой постоянной работы, включая создание моментальных снимков памяти и файлов журнала AOF, особенно не включать моментальные снимки памяти для сохраняемости. синхронизировать раз в секунду.
  3. Мастер вызывает BGREWRITEAOF для перезаписи файла AOF. AOF будет занимать много ресурсов ЦП и памяти при перезаписи, что приводит к высокой нагрузке на службу и кратковременной приостановке службы.
  4. Проблема производительности репликации master-slave Redis, для скорости репликации master-slave и стабильности соединения лучше всего, чтобы Slave и Master находились в одной локальной сети.

Redis предлагает 6 стратегий удаления данных

  1. volatile-lru: выберите данные из набора данных (server.db[i].expires), которые использовались наименее недавно, с установленным временем истечения срока действия.
  2. volatile-ttl: выберите данные, срок действия которых истекает, из набора данных (server.db[i].expires), в котором установлено время истечения срока действия.
  3. volatile-random: произвольный выбор удаления данных из набора данных с установленным временем истечения срока действия (server.db[i].expires)
  4. allkeys-lru: выбрать наименее использованные данные из набора данных (server.db[i].dict) для исключения
  5. allkeys-random: Случайный выбор данных из набора данных (server.db[i].dict) для исключения
  6. no-enviction: запретить удаление данных

java

виртуальная машина java

这里写图片描述
Источник изображения (публичный аккаунт Hollis WeChat)

Когда будет запущен полный gc

  1. Вызов метода System.gc()
  2. Недостаточно места для старости
  3. Недостаточно места в бессмертной области (область метода в области данных времени выполнения в спецификации JVM также обычно называют бессмертной генерацией или бессмертной областью в виртуальной машине HotSpot, а в постоянной генерации хранится некоторая информация о классах, константы, статические переменные и прочее данные)
  4. Не удалось повысить уровень, и во время GC появляется сообщение об ошибке параллельного режима.
  5. Полученная статистика продвижения Minor GC до среднего размера старого поколения больше, чем оставшееся место старого поколения
  6. Размещение больших объектов в куче

Объекты, которые можно использовать как root:

  1. Статическая переменная в классе, которая действует как корень, когда содержит ссылку на объект.
  2. Активный поток, может действовать как root
  3. Параметр метода Java или локальная переменная в методе, оба из которых могут использоваться как root
  4. Локальные переменные или параметры в методах JNI, эти два объекта могут использоваться как корневые

Пример: Следующие Something и Apple могут использоваться как корневые объекты.

public AClass{
 
  public static Something;
  public static final Apple;
   ''''''
}

Параметры методов Java и локальные переменные в методах могут использоваться как root.

public Aclass{

public void doSomething(Object A){
    ObjectB b = new ObjectB; 
    }
 }

Триггерное условие перехода молодого поколения к старому поколению

  1. долгоживущие объекты
  2. Крупные предметы уходят прямо в старость
  3. После незначительного gc выживший все еще не может оторваться
  4. Динамическое суждение о возрасте, объекты старше или равные определенному возрасту превышают половину оставшегося пространства, а объекты старше или равные определенному возрасту напрямую входят в старость

Разница между G1 и CMS

  1. G1 перерабатывает как старое поколение, так и молодое поколение, в то время как CMS может перерабатывать только старое поколение и должен сотрудничать со сборщиком молодого поколения. Кроме того, генерация G1 является более логической концепцией, G1 делит память на несколько областей одинакового размера, Eden/Survivor/Old являются логическими совокупностями части областей, а адреса физической памяти не являются непрерывными.
    这里写图片描述
  2. CMS будет перерабатывать всю старую область, когда это старый gc.Для G1 нет понятия старого gc, но различают полностью молодой gc и смешанный gc.Первый соответствует сборке мусора молодого поколения, а второй смешивает молодое поколение и часть старого поколения.Поэтому каждая коллекция обязательно будет перерабатывать молодое поколение, а старое поколение может не перерабатывать или перерабатывать часть или все это в зависимости от ситуации с памятью (такая ситуация должна быть возможна).

Какие методы есть в родительской модели делегирования. Как пользователи могут настроить classloader. Как сломать механизм родительского делегирования

  1. Методы, используемые в родительской модели делегирования:
  • findLoadedClass(),
  • loadClass()
  • findBootstrapClassOrNull()
  • findClass()
  • defineClass(): Преобразование двоичных данных в байт-код.
  • resolveClass()

Метод настройки загрузчика классов: наследуйте класс ClassLoader и переопределяйте метод findClass().

  1. Унаследуйте ClassLoader, чтобы переопределить метод loadClass. первоначальный заказ
  2. findLoadedClass
  3. Делегируйте родительский загрузчик для загрузки (обратите внимание, что родительский загрузчик начальной загрузки имеет значение null)
  4. самозагрузка Что вам нужно сделать, чтобы сломать механизм делегирования, так это нарушить порядок 2 и 3, отфильтровать классы, которые вы хотите загрузить, по имени класса, а остальное делегировать родительскому загрузчику.

Методы оптимизации JIT-компиляторов

Байт-код можно преобразовать в подходящий язык двумя способами:

  1. устный переводчик
  2. Своевременный компилятор своевременный компиляторВесь байт-код компилируется в собственный код, выполнение нативного кода намного быстрее, чем интерпретация и выполнение по одному, потому что нативный код хранится в кеше

Пять этапов процесса компиляции

  1. Этап 1: Лексический анализ
  2. Этап 2: Синтаксический анализ
  3. Третий этап: лексический анализ и генерация промежуточного кода
  4. Этап 4: Оптимизация
  5. Этап 5: Генерация объектного кода

Решение проблемы низкой скорости работы системы Java-приложений

Идеи решения проблемы:

  1. Проверьте использование системных ресурсов, ЦП, памяти и операций ввода-вывода развернутой системы приложений. Найдите правильный процесс.
  2. Используйте jstack, jmap и другие команды, чтобы увидеть, в каком типе памяти JVM выполняет GC (восстановление памяти), и проверьте журнал GC, чтобы увидеть, какой фрагмент кода занимает память. Сначала настройте параметры памяти.Если проблема не устранена, найдите соответствующий код.
  3. Найдите код и измените код (обычно логическая проблема кода или слишком большой объем данных, полученных кодом).

Что такое переполнение памяти и чем оно вызвано

Переполнение памяти означает, что есть память, которую нельзя восстановить, или слишком много памяти используется в системе приложений, и в конечном итоге память, используемая программой для запуска, превышает максимальный объем памяти, который может предоставить виртуальная машина. Чтобы решить проблему переполнения памяти в Java, мы должны сначала понять, как Java управляет памятью. Управление памятью в Java — это выделение и освобождение объектов. В Java выделение памяти осуществляется программой, а освобождение памяти осуществляется сборщиком мусора (GC), программисту не нужно вызывать функцию GC для освобождения памяти, поскольку разные разработчики JVM могут использовать разные алгоритмы. используются для управления GC, некоторые из них начинают работать, когда использование памяти достигает определенного уровня, некоторые выполняются периодически, а некоторые выполняются с прерыванием. Но сборщик мусора может освободить пространство, занятое бесполезными объектами, на которые больше не ссылаются другие объекты. Механизм сборки мусора в памяти Java заключается в проверке цепочки ссылок от основного запущенного объекта программы.

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

  1. Объем данных, загруженных в память, слишком велик, например, из базы данных одновременно извлекается слишком много данных;

  2. В классе коллекции есть ссылка на объект, и он не очищается после использования, чтобы JVM не могла его переработать;

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

  4. ОШИБКА в используемом стороннем ПО;

  5. Установлено слишком малое значение памяти параметров запуска;

решение проблемы с переполнением памяти

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

Первый шаг — изменить параметры запуска JVM и напрямую увеличить объем памяти. Это может показаться простым, но это легко упустить из виду. Память по умолчанию, которую может использовать JVM, составляет 64 МБ, а память по умолчанию, которую может использовать Tomcat, составляет 128 МБ, что недостаточно для немного более сложной системы. В определенном проекте часто сообщается об ошибке «OutOfMemory» из-за значений по умолчанию, используемых параметрами запуска. Поэтому нужно не забыть добавить параметры -Xms и -Xmx.

Второй шаг — проверить журнал ошибок, чтобы увидеть, есть ли другие исключения или ошибки перед ошибкой «OutOfMemory». В проекте используются два подключения к базе данных, среди которых подключение к базе данных, предназначенное для отправки коротких сообщений, управляется пулом подключений DBCP.Чтобы не отправлять короткие сообщения, пользователь намеренно меняет имя пользователя подключения к базе данных на неправильное, в результате чего много аномальных подключений к БД в лог.логе, через некоторое время появляется ошибка "OutOfMemory". После анализа это вызвано ошибкой в ​​пуле соединений DBCP.После сбоя соединения с базой данных соединение не освобождается, и, наконец, DBCP сообщает об ошибке «OutOfMemory». После изменения правильных параметров подключения к базе данных ошибка переполнения памяти больше не появляется.

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

Третий шаг — выяснить, где может произойти переполнение памяти. Сосредоточьтесь на следующих моментах:

  1. Проверьте свой код на наличие бесконечных циклов или рекурсивных вызовов.

  2. Проверьте, нет ли больших циклов, которые многократно генерируют новые сущности объекта.

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

  4. Проверьте, не очищаются ли объекты коллекции, такие как List и MAP, после использования. Объекты-коллекции, такие как List и MAP, всегда будут иметь ссылки на объекты, поэтому сборщик мусора не сможет повторно использовать эти объекты.

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

Существует много инструментов для просмотра памяти, наиболее известные из них: Optimizeit Profiler, JProbe Profiler, JinSight и Jconsole для Java 1.5. Их основные принципы работы схожи, все они следят за применением, освобождением и другими действиями всех объектов при работе Java-программы, а также выполняют статистику, анализ и визуализацию всей информации управления памятью. Разработчики могут использовать эту информацию, чтобы определить, есть ли в программе проблема с утечкой памяти. Вообще говоря, использование памяти нормальной системой в основном стабильно после завершения ее запуска и не должно расти без ограничений. Постоянно наблюдайте за объемом памяти, используемой системой во время ее работы, и вы можете увидеть зигзагообразный график, который является основным правилом в окне мониторинга использования памяти.Если размер памяти продолжает расти, это означает, что система есть проблема с утечкой памяти. Делая моментальный снимок памяти через определенные промежутки времени, а затем сравнивая и анализируя использование и ссылки на объекты в моментальном снимке памяти, вы можете определить, какой класс объектов имеет утечку.

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

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

параллелизм Java

Диаграмма перехода состояния потока JAVA

这里写图片描述

Как реализовать нижний слой синхронизированного

  1. Блок синхронизированного кода(Синхронизация) реализована на основе входа и выхода из объекта монитора. Каждый объект имеет блокировку монитора (монитор). Когда монитор занят, он будет в заблокированном состоянии.Когда поток выполняет инструкцию monitorenter, он пытается получить право собственности на монитор.Процесс выглядит следующим образом:
  • Если номер записи монитора равен 0, поток входит в монитор, а затем номер записи устанавливается равным 1, и поток становится владельцем монитора.

  • Если поток уже владеет монитором и просто повторно входит в него, количество записей в мониторе увеличивается на 1.

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

  1. Синхронизированный метод, украшенный синхронизированнымЭто делается не инструкциями monitorenter и monitorexit (теоретически, этого можно добиться и этими двумя инструкциями), а по сравнению с обычным методом в константный пул добавляется идентификатор ACC_SYNCHRONIZED. JVM реализует синхронизацию методов по этому идентификатору: при вызове метода вызывающая инструкция проверяет, установлен ли флаг доступа ACC_SYNCHRONIZED метода, после выполнения метода монитор освобождается. Во время выполнения метода ни один другой поток не может снова получить тот же объект монитора. На самом деле разницы по сути нет, но синхронизация метода реализована неявным образом, без необходимости завершения байткода

Разговор о КАС

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

принцип:

  1. CAS имеет 3 операнда: значение памяти V, старое ожидаемое значение A и новое значение B, которое необходимо изменить. Измените значение памяти V на B тогда и только тогда, когда ожидаемое значение A и значение памяти V совпадают, в противном случае ничего не делайте.

В документации JDK говорится, что cas имеет как энергозависимую семантику чтения, так и энергозависимую запись памяти.

недостаток:

  1. проблема с АБА. Поскольку CAS необходимо проверить, изменилось ли значение при работе со значением, и если изменений нет, обновить его, но если значение изначально было A, стало B, а затем стало A, то при использовании CAS для проверки вы найти, что его значение не изменилось

  2. Время цикла велико, а накладные расходы высоки. Если прокрутка CAS не работает в течение длительного времени, это вызовет очень большие накладные расходы на выполнение ЦП.

  3. Гарантируются только атомарные операции с общей переменной. При работе с несколькими общими переменными CAS цикла не может гарантировать атомарность операции, в это время можно использовать блокировки или есть хитрый способ объединить несколько общих переменных в одну общую переменную для операции. Например, есть две общие переменные i=2, j=a, объединяются ij=2a, а затем используется CAS для работы с ij. Начиная с Java 1.5, JDK предоставляет класс AtomicReference для обеспечения атомарности между ссылочными объектами.Вы можете поместить несколько переменных в один объект для выполнения операций CAS.

Пул потоков

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

Стратегия, выполняемая ThreadPoolExecutor

  1. Если количество потоков не достигает corePoolSize, создайте новый поток (основной поток) для выполнения задачи
  2. Когда количество потоков достигает corePools, задача перемещается в очередь и ожидает
  3. Очередь заполнена, новый поток (не основной поток) выполняет задачу
  4. Когда очередь заполнена и общее количество потоков достигает максимального размера пула, (RejectedExecutionHandler) будет сгенерировано исключение.

Новый поток -> количество достигнутых ядер -> очередь присоединения -> новый поток (не основной) -> достигнуто максимальное количество -> политика отклонения срабатывания

Четыре общих пула потоков

  1. CachedThreadPool(): Кэшированный пул потоков.
  • Неограниченное количество потоков
  • Если есть бездействующие потоки, они используются повторно, а если бездействующих потоков нет, создаются новые потоки.
  • Некоторые программы сокращают частое создание/уничтожение потоков и снижают нагрузку на систему.
  1. FixedThreadPool(): пул потоков фиксированной длины.
  • Максимальное количество параллельных потоков, которыми можно управлять (количество потоков, выполняющихся одновременно)
  • Превышенные потоки будут ждать в очереди
  1. ScheduledThreadPool(): пул потоков по времени.
  • Поддерживает запланированное и периодическое выполнение задач.
  1. SingleThreadExecutor(): однопоточный пул потоков.
  • Существует один и только один рабочий поток, который выполняет задачу
  • Все задачи выполняются в указанном порядке, то есть в соответствии с правилами постановки в очередь и исключения из очереди.

Четыре стратегии отказа

  1. AbortPolicy: отклоняет задачу, а также выдает RejectedExecutionException, политику пула потоков по умолчанию.
  2. CallerRunPolicy: запретить ввод новых задач, если пул потоков не был закрыт, то эта новая задача вызывается в потоке выполнения.
  3. DiscardOldestPolicy: если исполнитель не был закрыт, задача во главе будет удалена, а затем задача будет запущена повторно (если снова произойдет сбой, процесс будет повторен), что приведет к выполнению новой задачи и предыдущий Задача будет удалена.
  4. DiscardPolicy: задачи, которые не добавлены, будут отброшены, и исключение не будет выдано. В основном беззвучный режим.

Зачем использовать пул потоков

  1. Количество создаваемых и уничтожаемых потоков уменьшается, и каждый рабочий поток можно повторно использовать для выполнения нескольких задач.
  2. Использование пула потоков позволяет эффективно контролировать максимальное количество одновременных потоков.Вы можете настроить количество рабочих потоков в пуле потоков в соответствии с емкостью системы, чтобы предотвратить истощение сервера из-за чрезмерного потребления памяти (каждому потоку требуется около 1 МБ памяти, чем больше потоков открывается, тем больше памяти потребляется и, наконец, вылетает).
  3. Некоторое простое управление потоками, такое как: отложенное выполнение, стратегия выполнения циклов по времени и т. д., может быть хорошо реализовано с использованием пулов потоков.

Разница между блокировкой объекта и статической блокировкой

  1. Блокировки объекта используются для методов экземпляра объекта,
  2. Блокировки класса используются в статических методах класса или в объекте класса класса.
  3. Может быть много экземпляров объекта класса, блокировки объектов разных экземпляров объектов не мешают друг другу, и каждый класс имеет только одну блокировку класса.

Кратко опишите изменчивое слово

две особенности

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

Чтобы параллельные программы выполнялись правильно, должны быть гарантированы атомарность, видимость и упорядоченность Блокировки гарантируют атомарность, а volatile гарантирует видимость и упорядоченность.

происходит до принципа:

  1. Правило порядка программы: в потоке, в соответствии с порядком кода, операции, написанные в начале, выполняются первыми перед операциями, написанными в последующие операции
  2. Правила блокировки: операция разблокировки выполняется до операции блокировки того же замка.
  3. правило volatile переменной: запись в переменную происходит до чтения переменной
  4. Правило доставки: если операция A происходит до операции B, которая происходит до операции C, то вы можете заключает, что операция А происходит раньше операции С
  5. Правила запуска потока: метод start() объекта Thread выполняется первым для каждого действия этого потока.
  6. Правила прерывания потока: вызов метода прерывания потока() происходит первым при обнаружении кода прерванного потока. к возникновению события прерывания
  7. Правило завершения потока: все операции в потоке происходят первыми при обнаружении завершения потока, мы можем передать T Метод thread.join() завершается, и возвращаемое значение Thread.isAlive() определяет, что выполнение потока завершено.
  8. Правила финализации объекта: инициализация объекта происходит сначала в начале его метода finalize()

Разница между блокировкой и синхронизацией

  1. Блокировка — это интерфейс, а синхронизация — это ключевое слово в Java, синхронизированный — это встроенная языковая реализация;

  2. Когда возникает исключение, synchronized автоматически снимает блокировку, удерживаемую потоком, поэтому это не приведет к Возникает явление взаимоблокировки; когда возникает исключение, если блокировка не снимается активно с помощью unLock() lock, это может привести к взаимоблокировке, поэтому при использовании Lock вам нужно снять блокировку в блоке finally;

  3. Блокировка позволяет потокам, ожидающим блокировок, реагировать на прерывания (прерываемые блокировки) при синхронизации. Но это не работает При использовании synchronized ожидающий поток будет продолжать ждать и не сможет ответить. взломать (невзламываемый замок);

  4. Через Lock вы можете узнать, успешно ли получена блокировка (метод tryLock(): если получен Если блокировка получена, верните true, в противном случае верните false e, , что означает, что этот метод вернется немедленно, несмотря ни на что. Он не будет ждать там вечно, если не сможет получить замок. ), который синхронизирован не может.

  5. Блокировка может повысить эффективность операций чтения несколькими потоками (блокировки чтения-записи).

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

ThreadLocal (копия переменной потока)

Synchronized реализует совместное использование памяти, а ThreadLocal поддерживает локальную переменную для каждого потока. Используя пространство вместо времени, оно используется для изоляции данных между потоками, предоставляя копию для каждого потока, использующего переменную, и каждый поток может изменять свою собственную копию независимо, не конфликтуя с копиями других потоков. Карта поддерживается в классе ThreadLocal для хранения копии переменной каждого потока.Ключом элемента в карте является объект потока, а значением является копия переменной соответствующего потока. ThreadLocal играет огромную роль в Spring и появляется в управлении Bean, управлении транзакциями, планировании задач, AOP и других модулях в области запросов. Большинство bean-компонентов в Spring могут быть объявлены как области Singleton и инкапсулированы ThreadLocal, поэтому bean-компоненты с отслеживанием состояния могут нормально работать в многопоточности в одноэлементном режиме.

Создание потоков через Callable и Future

В Java 5 в пакете параллелизма появился интерфейс java.util.concurrent.Callable, который похож на интерфейс Runnable, но может возвращать объект или вызывать исключение.

Вызываемый интерфейсиспользовать дженерики для определения возвращаемого типа. Класс Executors предоставляетНекоторые полезные способы выполнения задач внутри Callable в пуле потоков. Поскольку задача Callable является параллельной, нам нужно дождаться результата, который она вернет. Объект java.util.concurrent.Future решает эту проблему за нас. в пуле потоковОтправить вызываемую задачуЗаднийвозвращает объект Future, используя его, мы можем узнать статус задачи Callable и получить результат выполнения, возвращаемый Callable.Future предоставляет метод get(), так что мы можем дождаться завершения Callable и получить результат его выполнения..

  1. Создайте класс реализации интерфейса Callable и реализуйте метод call().Метод call() будет действовать как тело выполнения потока и иметь возвращаемое значение.
  2. Создайте экземпляр класса реализации Callable,Используйте класс FutureTask для переноса объекта Callable, объект FutureTask инкапсулирует возвращаемое значение метода call() объекта Callable.
  3. Создайте и запустите новый поток, используя объект FutureTask в качестве цели объекта Thread..
  4. Вызовите метод get() объекта FutureTask, чтобы получить возвращаемое значение после завершения выполнения дочернего потока.

Что такое поток демона и какой метод используется для реализации потока демона (значение Thread.setDeamon())

В Java существует два типа потоков: User Thread (пользовательский поток), Daemon Thread (поток демона) Чтобы использовать более общий пример, любой поток демона является няней всех потоков, не являющихся демонами, во всей JVM: До тех пор, пока в текущем экземпляре JVM есть какой-либо поток, не являющийся демоном, который не завершился, поток демона завершается; только когда завершается последний поток, не являющийся демоном, поток демона завершается с JVM. Внутренняя реализация JVM заключается в том, что если в работающей программе остались только потоки демона, программа завершится и завершится напрямую. Поэтому поток демона существует как вспомогательный поток, и его основная функция заключается в обеспечении вспомогательных функций, таких как подсчет.

Как остановить поток?

Три способа завершить поток:

  1. Используйте флаг выхода, чтобы поток завершился в обычном режиме, т. е. когда метод запуска завершится, поток завершится. При определении флага выхода exit используется ключевое слово Java volatile, предназначенное для синхронизации выхода, то есть только один поток может одновременно изменять значение выхода.
  thread.exit = true;  // 终止线程thread 
  1. Используйте метод остановки для принудительного завершения потока (этот метод не рекомендуется, поскольку остановка, как и приостановка и возобновление, также может привести к непредсказуемым результатам). Используйте метод остановки для принудительного завершения работающего или приостановленного потока. Мы можем использовать следующий код для завершения потока: нить.стоп(); Хотя приведенный выше код может завершить поток, использовать метод остановки очень опасно, так же как и внезапное отключение питания компьютера, вместо выключения в соответствии с обычной процедурой может привести к непредсказуемым результатам, поэтому не рекомендуется использовать метод остановки для завершения потока.

  2. Использование метода прерывания для прерывания потока, использование метода прерывания для завершения потока можно разделить на две ситуации:

  • Поток заблокирован, например, при использовании метода сна.
  • Используйте while(!isInterrupted()){...}, чтобы определить, прерван ли поток. При использовании метода прерывания в первом случае метод sleep вызовет исключение InterruptedException, а во втором случае поток завершится напрямую.

Примечание. В классе Thread есть два метода для определения того, завершается ли поток методом прерывания. Один из них — статический метод interrupted(), а другой — нестатический метод isInterrupted(). Разница между этими двумя методами заключается в том, что interrupted используется для определения того, прервана ли текущая строка, а isInterrupted может использоваться для определения того, прерывается ли текущая строка. другие потоки прерываются. Следовательно, while (!isInterrupted()) также можно заменить на while (!Thread.interrupted()).

Что такое потокобезопасность? Что такое небезопасность потока?

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

Java-контейнер

Разница между HashSet и TreeSet

HashSet

  1. Порядок расположения элементов не гарантируется и может измениться
  2. не синхронно
  3. Элементы коллекции могут быть нулевыми, но может быть размещен только один нулевой Когда элемент хранится в комбинации HashSet, HashSet вызывает метод hashCode() объекта, чтобы получить значение hashCode объекта, а затем определяет место хранения объекта в HashSet в соответствии со значением hashCode.

TreeSet

  1. TreeSet — единственный класс, реализующий интерфейс SortedSet.
  2. TreeSet обеспечивает сортировку элементов коллекции. TreeSet поддерживает два метода сортировки: естественную сортировку и пользовательскую сортировку, где естественная сортировка является методом сортировки по умолчанию. Объекты одного класса должны быть добавлены в TreeSet

Разговор о LinkedHashMap

Реализация LinkedHashMap является реализацией HashMap+LinkedList Структура данных поддерживается HashMap, а порядок вставки данных поддерживается LinkList.

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

Используйте LinkedHashMap для реализации кэша алгоритма LRU (

  1. LinkedList - это прежде всего карта, карта основана на K-V, согласуется с кешем
  2. LinkedList предоставляет логическое значение, которое позволяет пользователю указать, следует ли реализовать LRU)

Оптимизация HashMap в Java8 (введение красно-черной древовидной структуры данных и оптимизация расширения)

  1. если (binCount >= TREEIFY_THRESHOLD - 1) Когда это условие выполняется, связанный список превращается в красно-черное дерево карты дерева, так что эффективность поиска меняется с o(n) на o(log n). выполнение:
  2. Мы используем расширение степени 2 (имеется в виду, что длина увеличивается в 2 раза по сравнению с исходной), поэтому положение элемента либо в исходном положении, либо он перемещается в положение степени 2 в исходное положение

Алгоритм хэширования здесь состоит из трех шагов: получение значения hashCode ключа, операция высокого порядка и операция по модулю.

После того, как элемент пересчитает хэш, поскольку n удваивается, диапазон маски n-1 на 1 бит больше в старшей позиции (красный), поэтому новый индекс изменится следующим образом:hashMap 1.8 Пример хеш-алгоритма Рисунок 2

这里写图片描述
Поэтому, когда мы расширяем HashMap, нам не нужно пересчитывать хэш, как в реализации JDK 1.7. Нам нужно только посмотреть, равен ли новый бит исходного значения хеш-функции 1 или 0. Если он равен 0, индекс не меняется.Если он равен 1, индекс становится "исходный индекс + oldCap"

Причина разницы в производительности между keySet() и entrySet() для обхода карты

Set<Entry<String, String>> entrySet = map.entrySet();
Set<String> set = map.keySet();` 
  1. В цикле keySet(), когда соответствующее значение будет получено через ключ, getEntry() будет вызываться для цикла. петля дважды
  2. entrySet() напрямую использует метод getEntry() для получения результата, зациклив один раз
  3. Таким образом, производительность keySet() будет хуже, чем entrySet(). Поэтому, если вы перемещаетесь по карте, используйте entrySet() для перемещения
 public V get(Object key) {
        if (key == null)
            return getForNullKey();
        Entry<K,V> entry = getEntry(key);

        return null == entry ? null : entry.getValue();
    }    
final Entry<K,V> getEntry(Object key) {
        if (size == 0) {
            return null;
        }

        int hash = (key == null) ? 0 : hash(key);
        for (Entry<K,V> e = table[indexFor(hash, table.length)];
             e != null;
             e = e.next) {
            Object k;
            if (e.hash == hash &&
                ((k = e.key) == key || (key != null && key.equals(k))))
                return e;
        }
        return null;
}

основы Java

абстрактный класс против интерфейса

параметр абстрактный класс интерфейс
Реализация метода по умолчанию Он может иметь реализацию метода по умолчанию Интерфейсы полностью абстрактны. у него вообще нет реализации метода
выполнить Подклассы используют ключевое слово extends для наследования абстрактных классов. Если подкласс не является абстрактным классом, он должен предоставить реализации всех методов, объявленных в абстрактном классе. Подклассы используют ключевое слово «реализует» для реализации интерфейса. Он должен обеспечить реализацию всех объявленных методов в интерфейсе.
Конструктор Абстрактные классы могут иметь конструкторы Интерфейс не может иметь конструктор
Отличия от обычных классов Java Он ничем не отличается от обычного класса Java, за исключением того, что вы не можете создать экземпляр абстрактного класса. Интерфейсы бывают совершенно разных типов
модификатор доступа Абстрактные методы могут иметь модификаторы public, protected и default. Модификатор по умолчанию для методов интерфейса является общедоступным. Вы не можете использовать другие модификаторы.
основной метод Абстрактный метод может иметь основной метод, и мы можем его запустить В интерфейсе нет основного метода, поэтому мы не можем его запустить.
множественное наследование Абстрактные методы могут наследоваться от класса и реализовывать несколько интерфейсов. Интерфейс может наследоваться только от одного или нескольких других интерфейсов.
скорость это быстрее, чем интерфейс Интерфейс немного медленнее, потому что требуется время, чтобы найти методы для реализации в классе.
добавить новый метод Если вы добавляете новые методы в абстрактный класс, вы можете предоставить ему реализации по умолчанию. Таким образом, вам не нужно менять текущий код. Если вы добавляете методы к интерфейсу, вы должны изменить класс, реализующий интерфейс.

Сколько способов создать класс?

  1. используя новое ключевое слово → конструктор был вызван
  2. Использование метода newInstance класса Class → вызов конструктора
Employee emp2 = (Employee)Class.forName("org.programming.mitra.exercises.Employee").newInstance();
  1. Используйте метод newInstance класса Constructor → вызывается конструктор
Constructor<Employee> constructor = Employee.class.getConstructor();
Employee emp3 = constructor.newInstance();
  1. используя метод клонирования → конструктор не вызывается
  2. использовать десериализацию } → конструктор не вызывается
ObjectInputStream in = new ObjectInputStream(new FileInputStream("data.obj"));
Employee emp5 = (Employee) in.readObject();

Перенаправить и вперед

  1. Процесс косвенной переадресации запроса, показанный на рисунке выше, выглядит следующим образом: Браузер отправляет запрос на доступ к Servlet1; Servlet1 вызывает метод sendRedirect() для перенаправления браузера на Servlet2; Браузер делает запрос к servlet2; В конце концов Servlet2 отвечает.

  2. Процесс прямой переадресации запроса, показанный на рисунке выше, выглядит следующим образом: Браузер отправляет запрос на доступ к Servlet1; Servlet1 вызывает метод forward() для пересылки запроса Servlet2 на стороне сервера; В конце концов Servlet2 отвечает.

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

  1. Суть дженериков заключается в «параметризованных типах», что означает, что тип данных, которым нужно манипулировать, указывается в качестве параметра. При создании коллекции укажите тип данных элементов коллекции, коллекция может хранить только элементы указанного типа. Избегайте использования приведения.
  2. Байт-код, сгенерированный компилятором Java, не содержит общей информации, и информация об универсальном типе будет обрабатываться во время компиляции. стирается, процесс, известный как стирание типа. Стирание типа можно просто понимать как преобразование общего кода Java в Замените его обычным кодом Java, но компилятор более прямолинеен и преобразует общий код Java непосредственно в обычный код Java. Java-байткод.

Основной процесс стирания типа выглядит следующим образом:

  1. Замените все универсальные параметры их самым левым ограничивающим (самым верхним супертипом) типом.
  2. Удалить все параметры типа.

В чем разница между Object и типами java, представленными этими тегами?

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

Разница между классом ошибок и классом исключений

  1. Родительские классы класса Error и класса Exception являются генерируемыми классами, разница между ними заключается в следующем: Класс Error обычно относится к проблемам, связанным с виртуальной машиной, таким как сбой системы, ошибка виртуальной машины, нехватка памяти, переполнение стека вызовов методов и т. д. Для прерывания работы приложения, вызванного ошибкой такого рода, сама программа не может восстановить и предотвратить ее.При обнаружении такой ошибки рекомендуется завершить работу программы. Класс Exception представляет исключение, которое программа может обрабатывать, перехватывать и, возможно, восстанавливать. При возникновении такого исключения его следует максимально обработать, чтобы программа возобновила работу. Он не должен быть прекращен произвольно с исключениями.
  2. Класс Exception дополнительно делится на исключения времени выполнения (Исключение времени выполнения) и проверенные исключения (Исключение проверки), исключения времени выполнения; ArithmaticException, IllegalArgumentException, компиляция может пройти, но она завершается сразу после запуска, программа не будет обрабатывать исключения времени выполнения , появятся такие исключения, программа завершится.Для проверенных исключений используйте try. . . Поймать захват, или объявить броски с предложением throws, и передать его родительскому классу для обработки, иначе компиляция не пройдет.

Разница между броском и броском

бросить: (для предметов)Генерирует исключение, которое может быть системным или самоопределяемым.

public void yichang(){
    NumberFormatException e = new NumberFormatException();
    throw e;
}

throws: (для исключений, выбрасываемых методом)Вызывает исключение, которое может быть определенным системой или самоопределяемым.

public void yichang() throws NumberFormatException{
    int a = Integer.parseInt("10L");
}
  1. throws появляется в заголовке функции метода, throw появляется в теле функции.
  2. Выбросы представляют собой возможность исключений, и эти исключения не обязательно возникают; throw означает, что генерируется исключение, а выполнение throw должно вызывать какое-то исключение.
  3. Оба являются способами негативной обработки исключений (негативность здесь не означает, что этот способ плохой), просто выбрасывание или, возможно, выбрасывание исключений, но не обработка исключений функцией, реальная обработка исключений вызывается верхним уровнем функции сделки с участием.

Какой тип файла является файлом .class

Файл класса представляет собой 8-битный двоичный потоковый файл.

Сериализованный подкласс в java наследует сериализацию родительского класса.

Родительский класс реализует Serializable, а подклассу не нужно реализовывать Serializable.

Связанные меры предосторожности 1. При сериализации сохраняется только состояние объекта, вне зависимости от метода объекта; 2. Когда родительский класс реализует сериализацию, подкласс автоматически реализует сериализацию, и нет необходимости явно реализовывать интерфейс Serializable;c) когда переменная экземпляра объекта ссылается на другие объекты, ссылочный объект также сериализуется при сериализации объекта;3. Не все объекты можно сериализовать, почему бы и нет, причин много, например: 1. Из соображений безопасности, например, объект имеет такие поля, как частные, общедоступные и т. д. Для объекта, подлежащего передаче, например записи в файл, или выполнения передачи rmi и т. д., в процессе сериализации и передачи , приват этого объекта и т.п. Домены не защищены. 2. По причинам выделения ресурсов, таких как классы сокетов и потоков, если они могут быть сериализованы, переданы или сохранены, они не могут быть перераспределены, и в этом нет необходимости.

2. В свою очередь, родительский класс не реализует Serializable, а подкласс.При сериализации экземпляра подкласса атрибуты родительского класса пропускаются и не сохраняются, или их можно сохранить, но не восстановить? (Ответ: значение не сохраняется)

Решение: после того, как родительский класс реализует интерфейс, все свойства производного класса будут сериализованы. Если подкласс реализует интерфейс, значение свойства суперкласса теряется.

Сериализованный подкласс в java наследует сериализацию родительского класса.

идентификатор

Идентификаторы могут включать эти 4 символа: буквы, символы подчеркивания, $, цифры; начало не может быть цифрой; это не может быть ключевое слово

Разница между Integer i=new Integer(127) и Integer i=127;

Когда Integer i = 127, технология константного пула Java используется для простого и быстрого создания определенных объектов.Когда вам нужен объект, перейдите в этот пул, чтобы найти его, а если вы не можете его найти, создайте его в пуле. Но следует соблюдать осторожность, если объект создается с помощью new. Тогда какой бы ни был объект, он не будет помещаться в пул, а будет претендовать на новое пространство хранилища из кучи. Классы-оболочки пяти целочисленных типов Byte, Short, Integer, Long и Character могут использовать пул объектов только в том случае, если соответствующее значение находится в диапазоне от -128 до 127. Если он превышает, он будет претендовать на место для создания объекта.

    int i1=128;
    Integer i2=128;
    Integer i3=new Integer(128);//自动拆箱
    
    System.out.println(i1==i2);//true
    System.out.println(i1==i3);//true
    
    Integer i5=127;
    Integer i6=127;
    System.out.println(i5==i6);//true
    
    
    Integer i5=127;
    Integer ii5=new Integer(127);
    System.out.println(i5==ii5);//false
    
    Integer i7=new Integer(127);
    Integer i8=new Integer(127);
    System.out.println(i7==i8);//false

Рукописный одноэлементный шаблон

Лучший одноэлементный шаблон - это статический внутренний класс, не пишите двойную проверку

private static class LazySomethingHolder {
  public static Something something = new Something();
}

public static Something getInstance() {
  return LazySomethingHolder.something;
}

Почему методы связи потоков wait(), notify() и notifyAll() определены в классе Object?

Каждый объект в Java имеет блокировку (монитор, который также может стать монитором), а методы wait(), notify() и другие используются для ожидания блокировки объекта или уведомления других потоков о доступности монитора объекта. Нет блокировок или синхронизаторов, доступных для любого объекта в потоке Java. Вот почему эти методы являются частью класса Object, так что каждый класс в Java имеет базовые методы для межпотокового взаимодействия.

Сравнение методов ожидания и сна в Java

  1. Эти два метода происходят из разных классов: Thread и Object соответственно.

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

  3. wait, notify и notifyAll можно использовать только в методах управления синхронизацией или блоках управления синхронизацией, а сон можно использовать где угодно (используйте область действия)

  4. Sleep должен перехватывать исключения, а wait, notify и notifyAll не должны перехватывать исключения.

  5. Метод sleep относится к методу класса Thread, это означает, что поток переводится в спящее состояние.После ожидания в течение определенного периода времени он автоматически проснется и перейдет в состояние runnable, а не войдет в рабочее состояние. немедленно, потому что механизму планирования потока также требуется время для восстановления работы потока.После того, как объект потока вызывает метод сна, он не освобождает все удерживаемые объектные блокировки, поэтому это не повлияет на работу других объектов процесса. Но в процессе сна его interrupt() может вызываться другими объектами, что приводит к InterruptedException. Если ваша программа не поймает это исключение, поток аварийно завершится и войдет в состояние TERMINATED. Если ваша программа перехватит это исключение, то программа продолжит выполнение блока catch (и, возможно, блока finally) и последующего кода.

  • Обратите внимание, что метод sleep() является статическим методом, что означает, что он действителен только для текущего объекта.Пусть объект t входит в спящий режим через t.sleep().Этот подход неверен, он только заставит текущий поток спать вместо т нить
  1. wait является методом-членом Object.Как только объект вызывает метод ожидания, методы notify() и notifyAll() должны использоваться для пробуждения процесса; если поток владеет блокировкой синхронизации одного или нескольких объектов, то после вызова wait() После этого поток освободит все удерживаемые им ресурсы синхронизации, не ограничиваясь объектом, для которого был вызван метод wait(). Метод wait() также будет генерироваться другими объектами, вызывающими метод interrupt() в процессе ожидания.

Связь между методами hashCode и equals

В некоторых случаях программисту необходимо переопределить метод equals при разработке класса, например класса String, но следует отметить, что при переопределении метода equals необходимо переопределить метод hashCode. То есть для двух объектов, если результат, полученный при вызове метода equals, истинен, значения хэш-кода двух объектов должны быть равны; Если результат, полученный методом equals, ложный, значения хэш-кода двух объектов не обязательно различны; Если значения хеш-кодов двух объектов не равны, результат, полученный методом equals, должен быть ложным; Если значения хэш-кода двух объектов равны, результат, полученный методом equals, неизвестен.

Какие методы есть в классе Object, перечислите больше 3-х (можете подсказать)

Методы объекта: equals(), toString(), finalize(), hashCode(), getClass(), clone(), wait(), notify(), notifyAll()

String s=new String("xyz") создает объект String в двух случаях:

  1. Если "xyz" был создан в пуле общего смысла строк, он больше не будет создаваться, и в это время будет создан только один объект new String("xyz");
  2. Если "xyz" не создан в пуле общего смысла строк, будут созданы два объекта, один со значением "xyz" и один объект new String("xyz").

Что такое передача по значению и передача по ссылке

пройти по значению

public class TempTest {

  private void test1(int a) {
    a = 5;
    System.out.println("test1方法中的a=" + a);
  }

  public static void main(String[] args) {
    TempTest t = new TempTest();
    int a = 3;
    t.test1(11);
    System.out.println("main方法中a=" + a);
  }

}

a=5 в методе test1 a=3 в основном методе Передача по значению: передается копия значения, и оно не связано друг с другом после передачи Передача по ссылке: передается адрес области памяти, соответствующей переменной.

public class TempTest {
  private void test1(A a) {
    a.age = 20;
    System.out.println("test1方法中a=" + a.age);
  }

  public static void main(String[] args) {
    TempTest t = new TempTest();
    A a = new A();
    a.age = 10;
    t.test1(a);
    System.out.println("main方法中a=" + a.age);
  }
}

class A {
  public int age = 0;
}

a=20 в методе test1 a=20 в основном методе Как до, так и после точки передачи на одну и ту же ссылку (такое же пространство памяти) Если они не влияют друг на друга, метод заключается в создании нового экземпляра в методе test1.

говорить о нетти

Netty получает и обрабатывает пользовательские запросы на основе мультиплексора через модель Reactor.Он внутренне реализует два пула потоков, поток-босс и пул рабочих потоков.Поток пула потоков-босса отвечает за обработку события принятия запроса.Когда получено событие принятия запроса, инкапсулируйте соответствующий сокет в NioSocketChannel и передайте его в пул рабочих потоков, где пул рабочих потоков отвечает за события чтения и записи запроса

Принцип Nio (синхронный неблокирующий)

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

这里写图片描述

Буфер Буфер, Канал Канал, Селектор Селектор

Буфер

  • Буфер на самом деле является объектом-контейнером, а точнее, массивом, в библиотеке NIO все данные обрабатываются с помощью буферов. При чтении данных они напрямую считываются в буфер, при записи данных они также записываются в буфер, каждый раз при доступе к данным в NIO они помещаются в буфер. В ориентированной на поток системе ввода/вывода все данные напрямую записываются или считываются непосредственно в объект Stream.

канал

  • Канал — это объект, через который данные могут быть прочитаны и записаны, и, конечно же, все данные обрабатываются через объект Buffer. Мы никогда не записываем байты напрямую в канал, вместо этого мы записываем данные в буфер, содержащий один или несколько байтов. Кроме того, вместо чтения байтов непосредственно из канала данные считываются из канала в буфер, а байт извлекается из буфера. Канал отличается от потока тем, что канал является двунаправленным. из. В то время как потоки просто движутся в одном направлении (поток должен быть InputStream или Подклассы OutputStream, такие как InputStream, могут выполнять только операции чтения, OutputStream только операции записи), в то время как канал является двунаправленным и может использоваться для чтения, записи или того и другого.

Селектор (Селектор)

  • NIO имеет основной класс Selector, который похож на наблюдателя, если нам нужно обнаружить Канал сокетов сообщает Селектору, что мы продолжаем делать другие вещи, и когда происходит событие, он Сообщите нам, верните набор SelectionKey, мы читаем эти ключи, мы получим то, что мы только что зарегистрировали прошел socketchannel, а затем, мы считываем данные из этого канала, будьте уверены, пакет точен Достаточно прочитать, тогда мы можем обработать данные.
  • Внутренний принцип Селектора фактически делает опрос доступа к зарегистрированному каналу, постоянно Опрос, после опроса на зарегистрированном канале, например при поступлении данных, он будет Встанет и доложит, сдайте ключ, давайте прочитаем содержимое этого канала через этот ключ Позволять.

Разница между БИО и НИО

  1. BIO: синхронный блокирующий IO, режим реализации сервера - одно соединение и один поток, то есть когда у клиента есть запрос на соединение, серверу необходимо запустить поток для обработки.Если соединение ничего не делает, это вызовет ненужные накладные расходы на потоки.Конечно, вы можете улучшить механизм пула потоков.
  2. NIO: синхронный неблокирующий ввод-вывод, режим реализации сервера — один запрос и один поток, то есть запрос на подключение, отправленный клиентом, будет зарегистрирован на мультиплексоре, и мультиплексор будет опрашивать при наличии подключенного запроса ввода-вывода. к соединению. Запустите поток для обработки.

Селекторная роль NIO

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

Чтобы реализовать селектор для управления несколькими SocketChannels, конкретный объект SocketChannel должен быть зарегистрирован в селекторе, а события, которые необходимо отслеживать (чтобы селектор знал, какие данные необходимо записывать), существуют 4 вида Мероприятия:

  1. connect: клиент подключается к событию сервера, соответствующее значение — SelectionKey.OP_CONNECT(8)
  2. accept: сервер получает событие подключения клиента, соответствующее значение — SelectionKey.OP_ACCEPT(16)
  3. чтение: событие чтения, соответствующее значение — SelectionKey.OP_READ(1)
  4. write: событие записи, соответствующее значение — SelectionKey.OP_WRITE(4)

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

Следовательно, когда в SocketChannel происходит соответствующее событие, селектор может наблюдать его и соответствующим образом обрабатывать.

компьютерная сеть

Разница между GET и POST

(ПОЛУЧИТЬ)Обратите внимание, что строка запроса (пара имя/значение) отправляется в URL-адресе запроса GET: /test/demo_form.asp?name1=value1&name2=value2

  1. GET-запросы могут кэшироваться

  2. GET-запросы остаются в истории браузера

  3. Запросы GET можно добавить в закладки

  4. Запросы GET не следует использовать при работе с конфиденциальными данными.

  5. Запросы GET имеют ограничение по длине

  6. Запросы GET следует использовать только для получения данных POST-метод(ПОЧТА)Обратите внимание, что строка запроса (пара имя/значение) отправляется в теле сообщения HTTP запроса POST: POST /test/demo_form.asp HTTP/1.1 Хозяин:w3schools.com name1=value1&name2=value2

  7. POST-запросы не кэшируются

  8. POST-запросы не сохраняются в истории браузера

  9. POST не может быть добавлен в закладки

  10. Запросы POST не требуют длины данных

протокол, используемый DNS

Используйте как TCP, так и UDP

  • Сначала поймите ограничение длины байтов передачи TCP и UDP:
  1. Максимальная длина пакета UDP составляет 512 байт, в то время как TCP позволяет использовать пакеты длиннее 512 байт. Когда запрос DNS превышает 512 байт, флаг TC протокола показывает флаг удаления, а затем использует TCP для отправки. Обычно традиционные UDP-пакеты обычно не превышают 512 байт.
  • При использовании TCP для передачи зоны необходимо учитывать два основных момента:
  1. Вторичный сервер доменных имен будет регулярно (обычно 3 часа) опрашивать первичный сервер доменных имен, чтобы узнать, изменились ли данные. Если есть какие-либо изменения, будет выполнена передача зоны для синхронизации данных. Передачи зоны будут использовать TCP вместо UDP, потому что объем данных, передаваемых синхронно, намного больше, чем запрос и ответ.
  2. TCP — это надежное соединение, гарантирующее точность данных.
  • Протокол UDP используется для разрешения доменного имени:
  1. Клиент запрашивает у DNS-сервера доменное имя, и возвращаемый контент обычно не превышает 512 байт, что может быть передано по протоколу UDP. Нет необходимости проходить трехстороннее рукопожатие TCP, поэтому нагрузка на DNS-сервер ниже, а ответ быстрее. Хотя теоретически клиент также может указать использование TCP при запросе DNS-сервера, но на самом деле многие DNS-серверы поддерживают только пакеты запросов UDP, когда они настроены.

идемпотент

Характерной чертой идемпотентной операции является то, что любое ее многократное выполнение имеет тот же эффект, что и однократное выполнение. Идемпотентная функция или идемпотентный метод — это функция, которая может многократно выполняться с одними и теми же параметрами и достигать одного и того же результата. Эти функции не влияют на состояние системы, и не нужно беспокоиться, что повторное выполнение вызовет изменения в системе. Например, функции getUsername() и setTrue() являются идемпотентными.

Разница между куки и сессиями

  1. Файлы cookie — это технология, которая позволяет серверу веб-сайта хранить небольшой объем данных на жестком диске или в памяти клиента или считывать данные с жесткого диска клиента. Файлы cookie — это очень маленькие текстовые файлы, размещаемые на вашем жестком диске веб-сервером при просмотре веб-сайта.Они могут записывать такую ​​информацию, как ваш идентификатор пользователя, пароль, посещенные веб-страницы и время пребывания. сеанс: когда пользователь запрашивает веб-страницу из приложения, веб-сервер автоматически создает объект сеанса, если у пользователя еще нет сеанса. Когда сеанс истекает или прекращается, сервер завершает сеанс. Механизм cookie: он принимает схему поддержания состояния на стороне клиента, а механизм сеанса использует схему поддержания состояния на стороне сервера. В то же время мы видим, что, поскольку решение сохранения состояния на стороне сервера также требует сохранения идентификатора на стороне клиента, механизму сеанса может потребоваться использовать механизм cookie для достижения цели сохранения идентификатора.

  2. Сеанс — это средство, используемое сервером для отслеживания пользователей.Каждый сеанс имеет уникальный идентификатор: идентификатор сеанса. Когда сервер создает сеанс, ответное сообщение, отправляемое клиенту, содержит поле Set-cookie, в котором есть пара ключ-значение с именем sid, которая является идентификатором сеанса ключ-значение. После того, как клиент получает файл cookie, он сохраняет файл cookie в браузере, а отчет о запросе, отправленный позже, содержит SessionID. HTTP предназначен для отслеживания статуса пользователя посредством взаимодействия сеанса и файла cookie. Сеанс используется для сервера, а файл cookie используется для клиента.

Причины залипания и распаковки TCP

  1. Размер в байтах данных, записываемых приложением, больше, чем размер буфера отправки сокета.
  2. Выполните сегментацию TCP размером с MSS. MSS — это сокращение от Максимальная длина сегмента. MSS — это максимальная длина поля данных в сегменте TCP. Поле данных плюс заголовок TCP равны всему сегменту TCP. Таким образом, MSS — это не максимальная длина сегмента TCP, а: MSS = длина сегмента TCP — длина заголовка TCP.
  3. Полезная нагрузка Ethernet больше, чем MTU для фрагментации IP. MTU означает: максимальный размер пакета, который может пройти через определенный уровень протокола связи. Если IP-уровень имеет пакет данных для передачи, и длина данных больше, чем MTU канального уровня, то IP-уровень будет выполнять фрагментацию, разделяя пакет данных на сухие части, чтобы каждая часть не превышать МТУ. Обратите внимание, что фрагментация IP-адресов может происходить на исходном хосте-отправителе или на промежуточных маршрутизаторах.

Стратегия решения приклеивания и распаковки TCP

  1. Сообщение имеет фиксированную длину. Например 100 байт.
  2. Добавьте специальные символы, такие как возврат каретки или символ пробела, в конце пакета для разделения, как правило, например, протокол FTP.
  3. Разделите сообщение на заголовок сообщения и трейлер сообщения.
  4. Другие сложные протоколы, такие как протокол RTMP и т. д.

трехстороннее рукопожатие

Первое рукопожатие: когда соединение установлено, клиент отправляет пакет синхронизации (syn=j) на сервер и переходит в состояние SYN_SEND, ожидая подтверждения от сервера;

Второе рукопожатие: сервер получает син-пакет и должен подтвердить SYN клиента (ack=j+1), и в то же время отправляет SYN-пакет (syn=k), то есть SYN+ACK-пакет, в это время время перехода сервера в состояние SYN_RECV;

Третье рукопожатие: клиент получает пакет SYN+ACK от сервера и отправляет на сервер пакет подтверждения ACK (ack=k+1).После отправки пакета клиент и сервер переходят в состояние ESTABLISHED и завершают трехстороннее рукопожатие.

После завершения трехэтапного рукопожатия клиент и сервер начинают передавать данные

помахал четыре раза

  1. Клиент сначала отправляет FIN и переходит в состояние FIN_WAIT1.
  2. Сервер получает FIN, отправляет ACK и переходит в состояние CLOSE_WAIT, клиент получает ACK и переходит в состояние FIN_WAIT2.
  3. Сервер отправляет FIN и переходит в состояние LAST_ACK.
  4. Клиент получает FIN, отправляет ACK и переходит в состояние TIME_WAIT, а сервер получает ACK и переходит в состояние CLOSE.

Состояние TIME_WAIT — это сторона, которая активно отключилась (здесь — клиент) и вошла в состояние после отправки последнего ACK. И длится довольно долго. Клиент TIME_WAIT длится в 2 раза больше времени MSL, что составляет около 60 с в системе Linux, и преобразуется в состояние CLOSE.

TIME_WAIT

TIME_WAIT формируется, когда ссылка активно закрывается, ожидая 2MSL времени, около 4 минут. В основном для предотвращения потери последнего ACK. Поскольку время TIME_WAIT будет очень большим, серверная сторона должна свести к минимуму активное закрытие соединения.

CLOSE_WAIT

CLOSE_WAIT — пассивно закрытое соединение. В соответствии с конечным автоматом TCP, когда сервер получает FIN, отправленный клиентом, он отправляет ACK в соответствии с реализацией TCP, поэтому он входит в состояние CLOSE_WAIT. Однако, если сервер не выполняет close(), он не может быть переведен из CLOSE_WAIT в LAST_ACK, и в системе будет много соединений в состоянии CLOSE_WAIT. В это время может случиться так, что система занята обработкой операций чтения и записи и не закрыла соединение, получившее FIN. В этот момент recv/read получает сокет соединения FIN и возвращает 0.

Зачем нужно состояние TIME_WAIT?

Предполагая, что окончательный ACK потерян, сервер повторно отправит FIN, а клиент должен сохранить информацию о состоянии TCP, чтобы можно было повторно отправить окончательный ACK, иначе будет отправлен RST, и сервер решит, что произошла ошибка. Реализации TCP должны надежно завершить соединение в обоих направлениях (полный дуплекс закрыт), а клиент должен войти в состояние TIME_WAIT, поскольку клиент может столкнуться с ситуацией, когда последний ACK отправляется повторно.

Почему состояние TIME_WAIT должно оставаться 2MSL так долго?

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

Слишком много сокетов в состояниях TIME_WAIT и CLOSE_WAIT

Если сервер неисправен, в 80–90% случаев возникают две следующие ситуации:

1. Сервер хранит много состояний TIME_WAIT

2. Сервер поддерживает большое количество состояний CLOSE_WAIT Короче говоря, чрезмерное количество CLOSE_WAIT вызвано неправильной обработкой пассивно закрытых соединений.

Полный процесс HTTP-запроса

Разрешение доменного имени --> Инициировать трехстороннее рукопожатие TCP --> Инициировать http-запрос после установления TCP-соединения --> Сервер отвечает на http-запрос, и браузер получает HTML-код --> Браузер анализирует html-код и запрашивает ресурсы в html-коде (такие как js, css, изображения и т. д.) --> браузер отображает страницу пользователю

Разговор о длинных соединениях

  • 1. Долгое соединение по протоколу http
  1. Существует поддержка длинных соединений в протоколах HTTP1.0 и HTTP1.1. Среди них HTTP1.0 должен добавить заголовок «Connection: keep-alive» к запросу для его поддержки, в то время как HTTP1.1 поддерживает его по умолчанию.
  • Процесс взаимодействия между запросом http1.0 и сервером:
  1. Клиент отправляет запрос с заголовком, содержащим: «Соединение: поддержание активности».
  2. После того, как сервер получит запрос, он определит, что это длинное соединение в соответствии с http1.0 и «Соединение: keep-alive», а также добавит «Соединение: keep-alive» в заголовок ответа, и он при этом не закроется.установленное tcp соединение.
  3. После того, как клиент получает ответ от сервера и обнаруживает, что он содержит «Соединение: keep-alive», он считает это длинным соединением и не закрывает соединение. И используйте соединение, чтобы снова отправить запрос.
  • Во-вторых, отправляйте пакеты сердцебиения. Отправлять пакет каждые несколько секунд

Как TCP гарантирует надежную передачу?

  1. Три рукопожатия.
  2. Сократите данные до разумной длины. Данные приложения разбиваются на куски, которые, по мнению TCP, наиболее подходят для отправки (нумеруются по байтам, разумно фрагментированы).
  3. Тайм-аут повторной передачи. Когда TCP отправляет сегмент, он запускает таймер, если нет. Отправить повторно, если вы можете получить подтверждение вовремя
  4. Для полученных запросов дайте подтверждающие ответы
  5. В проверочном пакете ошибка, сегмент отбрасывается, а ответа нет.
  6. Переупорядочивайте неупорядоченные данные перед их передачей на прикладной уровень.
  7. Для дубликатов данных возможность отбрасывать повторяющиеся данные
  8. управление потоком. Каждая сторона соединения TCP имеет фиксированный объем буферного пространства. Получатель ПТС Разрешить другому концу отправлять столько данных, сколько может вместить буфер получателя. Это предотвратит буферизацию более медленных хостов более быстрыми хостами. переполнение площади.
  9. контроль заторов. Когда сеть перегружена, уменьшите отправку данных.

Подробности о http

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

Функции

  1. Просто и быстро: когда клиент запрашивает услугу с сервера, ему нужно только передать метод запроса и путь. Обычно используемые методы запроса — GET, HEAD и POST. Каждый метод определяет другой тип контакта между клиентом и сервером. Поскольку протокол HTTP прост, программный масштаб сервера HTTP невелик, поэтому скорость связи высокая.

  2. Гибкость: HTTP позволяет передавать объекты данных любого типа. Передаваемый тип помечен Content-Type.

  3. Без установления соединения: Значение без установления соединения заключается в ограничении обработки только одного запроса на соединение. После того, как сервер обработает запрос клиента и получит ответ клиента, он отключится. Таким образом можно сэкономить время передачи.

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

  5. Поддержка режима B/S и C/S.

сообщение запроса

  1. Строка запроса, в которой указывается тип запроса, ресурс, к которому необходимо получить доступ, и используемая версия HTTP.
  2. Заголовок запроса, часть сразу после строки запроса (т. е. первая строка), используется для описания дополнительной информации, которая будет использоваться сервером. Начиная со второй строки, находится заголовок запроса, а HOST будет указывать место назначения запроса. User-Agent, к которому могут обращаться сценарии на стороне сервера и на стороне клиента, является важной основой для логики определения типа браузера.Эта информация используется вашим браузером, определяется сервером и автоматически отправляется при каждом запросе и т. д.
  3. Пустая строка, обязательна пустая строка после заголовка запроса
  4. Данные запроса также называются телом, и могут быть добавлены любые другие данные.

Ответное сообщение Ответ

  1. Строка состояния состоит из трех частей: номера версии протокола HTTP, кода состояния и сообщения о состоянии.
  2. Заголовок сообщения для описания некоторой дополнительной информации, которая будет использоваться клиентом.
  3. Пустая строка, пустая строка после заголовка сообщения обязательна
  4. Тело ответа — текстовая информация, которую сервер возвращает клиенту.

код состояния

  • 200 OK //Запрос клиента выполнен успешно
  • 301 Перемещено навсегда //Постоянное перенаправление, используйте переход по доменному имени
  • 302 Найдено // Временное перенаправление, пользователи, которые не вошли в систему, посещают центр пользователей и перенаправляются на страницу входа
  • 400 Bad Request //Запрос клиента имеет синтаксическую ошибку и не может быть понят сервером
  • 401 Unauthorized // Запрос не авторизован, этот код состояния должен использоваться с полем заголовка WWW-Authenticate
  • 403 Forbidden //Сервер получил запрос, но отказался предоставить услугу
  • 404 Not Found // Запрашиваемый ресурс не существует, например: введен неверный URL
  • 500 Internal Server Error // На сервере произошла непредвиденная ошибка
  • 503 Сервер недоступен // Сервер в настоящее время не может обработать запрос клиента и может вернуться в нормальное состояние через некоторое время.

http-метод

  1. get: клиент инициирует запрос на сервер для получения ресурса. Запрос на получение ресурса по URL-адресу.
  2. post: отправить новое поле запроса на сервер. Добавьте новые данные после запроса ресурса URL.
  3. head: запрос на получение отчета об ответе ресурса URL, то есть получение заголовка ресурса URL
  4. patch: запрос на частичное изменение элемента данных ресурса, где находится URL
  5. put: запрос на изменение элемента данных ресурса, в котором находится URL-адрес.
  6. удалить: запрос на удаление данных ресурса URL

Разница между URI и URL

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

URI обычно состоит из трех частей:

  1. Механизм именования для доступа к ресурсам
  2. Имя хоста, на котором хранится ресурс
  3. Имя самого ресурса, представленное путем, с акцентом на ресурсе.

URL — это унифицированный локатор ресурсов, унифицированный локатор ресурсов, это конкретный URI, то есть URL может использоваться для идентификации ресурса, а также указывает, как найти этот ресурс. URL-адрес — это строка, используемая для описания информационных ресурсов в Интернете, в основном используемая в различных клиентских и серверных программах WWW, особенно в знаменитой Mosaic. С помощью URL можно использовать единый формат для описания различных информационных ресурсов, включая файлы, адреса серверов и каталоги.

URL обычно состоит из трех частей:

  1. Соглашение (или метод обслуживания)
  2. IP-адрес хоста, на котором хранится ресурс (а иногда и номер порта)
  3. Конкретный адрес хост-ресурса. такие как имена каталогов и файлов

Разница между HTTPS и HTTP

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

Как https обеспечивает безопасность передачи данных

https на самом деле добавляет SSL/TLS между уровнем TCP и уровнем http для обеспечения безопасности верхнего уровня.Он в основном использует симметричное шифрование, асимметричное шифрование, сертификаты и другие технологии для шифрования передачи данных между клиентом и сервером, и наконец добиться Обеспечьте безопасность всего общения.

  • Роль протокола SSL/TLS:
  1. Аутентифицировать пользователей и серверы, чтобы гарантировать, что данные отправляются на правильный клиент и сервер;
  2. Шифрование данных для предотвращения кражи данных на полпути;
  3. Поддерживайте целостность данных и следите за тем, чтобы данные не изменялись при передаче.
    这里写图片描述

Структуры данных и алгоритмы

Идея динамического программирования

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

Идеи быстрой сортировки

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

Быстрая сортировка — нестабильный алгоритм

27 23 27 3 Принимая первые 27 в качестве центральной точки поворота, затем 27 заменяются последними 3, чтобы сформировать 3 23 27 27, сортировка заканчивается после одного прохода, но последние 27 предшествуют 27 в исходной позиции 3 в начале сортировки, поэтому она нестабильна.

Идея кучной сортировки

Используя свойство, заключающееся в том, что верхняя запись большой верхней кучи (small top heap) является самым большим ключом (самым маленьким ключом), легко каждый раз выбирать самую большую запись (самую маленькую запись) из неупорядоченных. Основная идея (большая верхняя куча): 1) Встроить исходную последовательность ключей для сортировки (R1, R2....Rn) в большую верхнюю кучу, которая является исходной ненужной областью; 2) Поменять местами верхний элемент R[1] кучи с последним элементом R[n] и получить новую неупорядоченную область (R1, R2,... Rn-1) и новую упорядоченную область ( Rn), и удовлетворить R[1,2...n-1]

словарное дерево

Дерево словаря в основном имеет следующие три свойства:

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

реверс связанного списка

  1. Сначала отсоедините головной узел от первого узла элемента, но обратите внимание, что перед отключением вам нужно использовать указатель p, чтобы указать на первый узел элемента, чтобы сохранить положение первого узла элемента, а затем отключиться. Здесь указатель q указывает на узел с пустым полем указателя, который используется как последний узел после обращения связанного списка.
  2. Пусть указатель узла второго элемента изменится с указания на узел третьего элемента на указатель на узел первого элемента и так далее, пока указатель p не укажет на последний элемент исходного связанного списка.
  3. Когда указатель p указывает на NULL, пусть поле указателя исходного головного узла указывает на исходный узел последнего элемента. На этом инверсия связанного списка завершена.
linkList reverse(linkList head){
  linkList p,q,pr;
  p = head->next;
  q = NULL;
  head->next = NULL;
  while(p){
    pr = p->next;
    p->next = q;
    q = p;
    p = pr;
  }
  head->next = q;
  return head;
}

Операционная система/Линукс

В каком состоянии процесс

Вообще говоря, процесс имеет три состояния, а именно состояние готовности, состояние выполнения и состояние блокировки.

  1. Состояние выполнения: процесс занимает ЦП и выполняется на ЦП.
  2. Состояние готовности: процесс готов к запуску, но ЦП не выделен.
  3. Состояние блокировки: процесс временно не может быть запущен, так как он ожидает, что что-то произойдет.
    这里写图片描述

Конечно, теоретически переход между тремя вышеуказанными состояниями делится на шесть ситуаций;

  1. Выполняется -> Готово: 1. Основная причина в том, что процесс слишком долго занимает ЦП, и время, которое система выделяет процессу для занятия ЦП, ограничено 2. В системе, использующей алгоритм планирования с упреждающим приоритетом, когда есть более высокие. Когда процесс с приоритетом хочет запуститься, процесс вынужден отказаться от ЦП, и процесс переходит из состояния выполнения в состояние готовности.
  2. Готово -> Выполняется: временной интервал запущенного процесса истекает, и планирование переходит в очередь готовности, чтобы выбрать соответствующий процесс для выделения ЦП.
  3. Запуск -> Блокировка: исполняемый процесс не может быть выполнен из-за события ожидания, и процесс переходит из состояния выполнения в состояние блокировки, например запрос ввода-вывода.
  4. Блокировка -> готовность: событие, которого ожидает процесс, уже произошло, он ставится в очередь готовности

Следующие два состояния невозможны:

  1. Блокировка -> Выполняется: даже если ЦП выделен блокирующему процессу, он не может быть выполнен.Операционная система не выбирает из очереди блокировки при планировании, а выбирает из очереди готовности

  2. Готовность -> Блокировка: Состояние готовности вообще не выполняется, и войти в состояние блокировки невозможно.

межпроцессного взаимодействия

  1. Pipe: Pipe — это полудуплексный метод связи.Данные могут передаваться только в одном направлении и могут использоваться только между процессами со сходством. Сродство процесса обычно относится к отношениям процесса родитель-потомок.
  2. Именованный канал FIFO: Именованный канал также является методом полудуплексной связи, но позволяет обмениваться данными между несвязанными процессами.
  3. Очередь сообщений MessageQueue: Очередь сообщений — это связанный список сообщений, хранящийся в ядре и определяемый идентификатором очереди сообщений. Очередь сообщений преодолевает недостатки меньшего количества информации в сигнализации, каналы могут передавать только неформатированные потоки байтов и ограниченный размер буфера.
  4. Общая память SharedMemory: Общая память предназначена для сопоставления части памяти, к которой могут получить доступ другие процессы.Эта общая память создается одним процессом, но может быть доступна нескольким процессам. Общая память — это самый быстрый способ IPC, и он разработан с учетом неэффективности других методов межпроцессного взаимодействия. Он часто используется в сочетании с другими механизмами связи, такими как сигнал два, для достижения синхронизации и связи между процессами.
  5. Семафор Семафор: семафор — это счетчик, который можно использовать для управления доступом к общим ресурсам несколькими процессами. Он часто используется в качестве механизма блокировки для предотвращения доступа других процессов к общему ресурсу, в то время как процесс обращается к ресурсу. Поэтому он в основном используется как метод синхронизации между процессами и между разными потоками в одном процессе.
  6. Сокет: сокет также является механизмом межпроцессного взаимодействия, в отличие от других механизмов взаимодействия его можно использовать для различных и межпроцессных взаимодействий.
  7. Сигнал ( sinal ): сигнал — это относительно сложный метод связи, используемый для уведомления принимающего процесса о том, что произошло событие.

Разница между программными ссылками и жесткими ссылками в Linux

ln -s source dist # установить мягкое соединение ln source dist # Установить жесткую ссылку При установке жесткой ссылки файл ссылки и связанный файл должны находиться в одной и той же файловой системе, и нельзя установить жесткую ссылку на каталог.

  1. Жесткая ссылка похожа на файл с несколькими именами файлов,
  2. Мягкая ссылка предназначена для создания нового файла (содержимое этого файла на самом деле является информацией, которая должна быть связана с исходным путем к файлу), этот файл указывает на местоположение другого файла.

Мультиплексирование ввода/вывода

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

select, poll, epoll — все это конкретные реализации мультиплексирования ввода-вывода.

Шаблоны проектирования

Существует три основных типа шаблонов проектирования: творческие, структурные и поведенческие.

  1. Творчествоимеют:
  • Singleton, шаблон singleton: гарантирует, что класс имеет только один экземпляр и предоставляет к нему глобальную точку доступа

  • Абстрактная фабрика, абстрактная фабрика: Предоставляет интерфейс для создания ряда связанных или взаимозависимых объектов без указания их конкретных классов.

  • Фабричный метод, Фабричный метод: определите интерфейс для создания объектов, позвольте подклассам решать, какой класс создавать экземпляр, Фабричный метод задерживает создание экземпляра класса для подклассов.

  • Строитель, шаблон построения: отделяет построение сложного объекта от его представления, так что один и тот же процесс построения может создавать разные представления.

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

  1. поведенческийимеют:
  • Итератор, шаблон итератора: предоставляет метод для последовательного доступа к элементам агрегатного объекта без раскрытия внутреннего представления объекта.
  • Наблюдатель, режим наблюдателя: определите зависимость между объектами «один ко многим».При изменении состояния объекта все зависящие от него объекты уведомляются об автоматическом обновлении.
  • Метод шаблона, метод шаблона: определение скелета алгоритма в операции и передача некоторых шагов подклассам TemplateMethod позволяет подклассам переопределять определенные шаги алгоритма без изменения структуры алгоритма.
  • Команда, шаблон команды: инкапсулирует запрос как объект, позволяя вам параметризовать клиентов с различными запросами, ставить в очередь и регистрировать запросы, а также поддерживать отзывные операции.
  • Состояние, шаблон состояния: позволяет объекту изменять свое поведение при изменении его внутреннего состояния. Объект, кажется, изменил свой класс.
  • Стратегия, режим стратегии: определите ряд алгоритмов, инкапсулируйте их один за другим и сделайте взаимозаменяемыми.Этот режим делает алгоритмы независимыми от клиентов, которые их используют.
  • China of Responsibility, Chain of Responsibility Pattern: позволяет нескольким объектам иметь возможность обрабатывать запрос, тем самым избегая связи между отправителем и получателем запроса.
  • Посредник, шаблон посредника: инкапсулирует серию взаимодействий объекта с объектом-посредником.
  • Посетитель, шаблон посетителя: представляет операцию, воздействующую на каждый элемент в структуре объекта, что позволяет определить новые операции, воздействующие на этот элемент, без изменения класса элемента.
  • Интерпретатор, шаблон интерпретатора: для данного языка определите представление его грамматики и определите интерпретатор, который использует это представление для интерпретации предложений на языке.
  • Memento, Memento Pattern: зафиксируйте внутреннее состояние объекта и сохраните это состояние вне объекта, не разрушая объект.
  1. структурныйимеют:
  • Composite, шаблон композиции: объект объединяется в древовидную структуру, чтобы представить отношение части к целому. Composite позволяет пользователям согласованно использовать один объект и составной объект.
  • Facade, Facade Pattern: Предоставляет согласованный интерфейс для набора интерфейсов в подсистеме, Fa?ade предоставляет высокоуровневый интерфейс, упрощающий использование подсистемы.
  • Прокси, режим прокси: предоставить прокси для других объектов, чтобы контролировать доступ к этому объекту
  • Адаптер, режим адаптера: преобразует один тип интерфейса в другой интерфейс, который хочет клиент.Режим адаптера позволяет тем классам, которые не могут работать вместе из-за несовместимых интерфейсов, работать вместе.
  • Декоратор, режим декорирования: динамически добавляйте объекту дополнительные обязанности.С точки зрения дополнительных функций режим декоратора более гибок, чем создание подклассов.
  • Мост, шаблон моста: абстрактная часть и ее часть реализации разделены, так что они могут меняться независимо.
  • Наилегчайший вес, режим наилегчайшего веса

В чем разница между динамическим прокси и статическим прокси

статический прокси

Этот прокси-метод требует, чтобы прокси-объект и целевой объект реализовывали один и тот же интерфейс. Перед запуском программы файл .class прокси-класса уже существует.

преимущество:

  1. Функциональность целевого объекта может быть расширена без изменения целевого объекта.

недостаток:

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

Динамический прокси

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

Динамический прокси — это метод вызова, который реализует интерфейс InvocationHandler в JDK, но обратите внимание, что прокси — это интерфейс, то есть ваш бизнес-класс должен реализовать интерфейс и получить прокси-объект через newProxyInstance в Proxy.

преимущество:

  1. Динамический прокси-объект не обязательно должен реализовывать интерфейс, но целевой объект должен реализовывать интерфейс, иначе динамический прокси-сервер использовать нельзя.

Основное различие между статическим прокси и динамическим прокси

  1. Статический прокси-сервер уже реализован во время компиляции, а прокси-класс является фактическим файлом класса после компиляции.
  2. Динамический прокси генерируется динамически во время выполнения, то есть после компиляции нет фактического файла класса, но байт-код класса динамически генерируется во время выполнения и загружается в JVM.
  3. Статический прокси обычно проксирует только один класс, динамический прокси предназначен для проксирования нескольких классов реализации в одном интерфейсе.
  4. Статические прокси заранее знают, что проксировать, в то время как динамические прокси не знают, что проксировать, только во время выполнения.

Динамические прокси и CGLIB в JDK

Динамический прокси

  1. Динамический прокси в JDK: реализован через класс отражения Proxy и интерфейс обратного вызова InvocationHandler,

  2. Недостатки динамического прокси: класс для динамического проксирования в JDK должен реализовывать интерфейс, то есть он может проксировать только методы, определенные в интерфейсе, реализованном классом, который имеет определенные ограничения в реальном программировании и использует эффективность отражения. не очень высок.

CGLIB

  1. Принцип CGLIB: динамически генерировать подкласс класса для проксирования, и подкласс переопределяет все неокончательные методы класса для проксирования. В подклассе используется технология перехвата методов для перехвата всех вызовов методов родительского класса, и в нее вплетена сквозная логика. Это быстрее, чем динамический прокси JDK с использованием отражения Java.

  2. Нижний уровень CGLIB: используйте структуру обработки байт-кода ASM для преобразования байт-кода и создания новых классов. Прямое использование ASM не рекомендуется, так как оно требует от вас знакомства с внутренней структурой JVM, включая формат и набор инструкций файлов классов.

  3. Преимущества CGLIB: Он предоставляет прокси для классов, которые не реализуют интерфейсы, обеспечивая хорошее дополнение к динамическим прокси JDK. Обычно можно создавать прокси-серверы с использованием динамических прокси-серверов Java, но CGLIB является хорошим выбором, когда класс, который должен быть проксирован, не реализует интерфейс или для повышения производительности.

  4. Недостаток CGLIB: для конечных методов проксирование невозможно.

Вопросы по сценарию и вопросы по дизайну

Вопрос сценария: разработка системы для оценки плагиата в статьях

  1. Один метод основан на сравнении строк, другой — на статистике частотности слов.
  2. Метод, основанный на сравнении строк, также называется методом цифровых отпечатков.Этот тип метода берет некоторые строки в документе как «отпечатки пальцев» с помощью определенной стратегии выбора, сопоставляет отпечатки пальцев с таблицей хэшей и, наконец, подсчитывает хэши.
  3. Одно и то же количество или соотношение отпечатков пальцев в таблице используется в качестве основы для подобия текста.
  4. Методы, основанные на статистике частотности слов, также известны как методы, основанные на семантике. Метод статистики частотности слов возник из технологии поиска информации.векторная космическая модель, этот тип метода сначала подсчитывает количество вхождений каждого слова в каждом документе, затем формирует вектор признаков документа в соответствии с частотой слов и, наконец, использует скалярное произведение, косинус или аналогичные методы для измерения вектора признаков двух документов, как степень подобия документа.

Разработайте систему живого чата

  1. Пользователь входит в систему через клиент, отправляет сообщение на сервер и запрашивает авторизацию.
  2. После того, как сервер получает запрос, он возвращает клиенту ответное сообщение, указывающее, что он согласен принять присоединение пользователя, а также информирует пользователя о номере порта прослушивания, где находится его служебный поток.
  3. Клиент устанавливает стабильное соединение с сервером по номеру порта, указанному в ответе сервера.
  4. Сервер передает информацию списка текущих онлайн-пользователей вновь добавленному клиенту через соединение.
  5. После того, как клиент получит список онлайн-пользователей, он может самостоятельно общаться с другими онлайн-пользователями.
  6. Когда пользователь выходит из системы, сервер должен быть уведомлен вовремя.

Решение для согласованности транзакций распределенной системы

Решение для согласованности транзакций распределенной системы MQ (транзакционное сообщение)

Например, если Боб переводит деньги Смиту, мы сначала отправляем сообщение или сначала выполняем вычет?

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

Ниже в качестве примера рассматривается промежуточное программное обеспечение Alibaba RocketMQ для анализа его идей проектирования и реализации.

Когда RocketMQ отправляет сообщение Prepared на первом этапе, он получает адрес сообщения, второй этап выполняет локальные транзакции, а третий этап обращается к сообщению через адрес, полученный на первом этапе, и изменяет состояние. Внимательные читатели могут снова обнаружить проблему, что делать, если сообщение с подтверждением не отправляется? RocketMQ будет периодически сканировать сообщения о транзакциях в кластере сообщений, в это время он находит сообщение «Подготовлено» и подтверждает отправителю сообщения, уменьшились ли деньги Боба или нет? Если понижение то откатиться или продолжить присылать подтверждающее сообщение? RocketMQ решит, следует ли откатиться или продолжить отправку подтверждающих сообщений в соответствии с политикой, установленной отправителем. Это гарантирует, что отправка сообщения будет успешной или неудачной одновременно с локальной транзакцией. Как показано ниже:

这里写图片描述

Проектируете систему с высокой степенью параллелизма?

  1. Статическая HTML-страница Частота доступа высока, но изменения контента невелики, а для оптимизации скорости доступа используется статическая HTML-схема веб-сайта. общество Это также широко используемая стратегия, позволяющая сделать посты и статьи на веб-сайте статичными в режиме реального времени, а затем снова статичными при обновлении. Преимущество: Во-первых, снизить нагрузку на сервер. 2. Ускорить скорость открытия страниц, статическим страницам не нужен доступ к базе данных, а скорость открытия значительно улучшена по сравнению с динамическими страницами; 3. Многие поисковые системы будут отдавать приоритет индексации статических страниц, которые не только быстро индексируются, но и полностью индексируются, по которым легко осуществлять поиск. поисковая система найдена; В-четвертых, статические HTML-страницы не будут подвержены уязвимостям, связанным с программами, что уменьшит количество атак и повысит безопасность.
  2. Сервер изображений и сервер приложений разделены Многие веб-сайты сейчас используют большое количество изображений, а изображения являются основным объемом данных при передаче веб-страниц. Главный фактор, влияющий на производительность сайта. Поэтому многие веб-сайты отделяют хранилище изображений от веб-сайта и создают еще одно хранилище. или несколько серверов для хранения изображений, помещайте изображения в виртуальный каталог, а изображения на веб-страницах хранятся с URL-адресом address указывать на адрес изображений на этих серверах, поэтому производительность веб-сайта будет значительно улучшена. Преимущество: 1. Разделите нагрузку ввода-вывода веб-сервера, разделив ресурсоемкие сервисы изображений, чтобы повысить производительность сервера. и стабильность. 2. Он может специально оптимизировать сервер изображений — настроить целевую схему кэширования для службы изображений, чтобы уменьшить пропускную способность. стоимость и повысить скорость доступа. 3. Улучшите масштабируемость веб-сайта - за счет увеличения сервера изображений увеличьте пропускную способность изображения.
  3. база данных См. раздел "База данных --- Если имеется особенно большой объем доступа к базе данных, как провести оптимизацию?".
  4. тайник Максимально используйте кеш, включая пользовательский кеш, информационный кеш и т. д., и тратьте больше памяти на кеш, что может значительно уменьшить и Взаимодействие с базой данных для повышения производительности. Если мы сможем уменьшить частые обращения к базе данных, это определенно пойдет на пользу системе. Например, отдел электронной коммерции. Если продукт по определенному ключевому слову часто ищут, вы можете рассмотреть возможность сохранения этой части списка продуктов в кеше. Хранить (в памяти), чтобы не нужно было каждый раз обращаться к БД, и производительность сильно увеличилась.
  5. зеркало Зеркалирование — это тип избыточности, при котором данные на одном диске имеют точную копию на другом диске. является зеркальным отражением.
  6. балансировки нагрузки В сценарии с большим одновременным доступом к веб-сайту используйте технологию балансировки нагрузки (сервер балансировки нагрузки) для создания приложения. Кластер серверов, состоящий из нескольких серверов, распределяет одновременные запросы доступа на несколько серверов для обработки, избегая единичных запросов. Сервер медленно отвечает из-за чрезмерной нагрузки, поэтому запросы пользователей имеют лучшие характеристики задержки ответа.
  7. управление параллелизмом Блокировка, такая как оптимистическая блокировка и пессимистическая блокировка.
  8. очередь сообщений Очередь по очереди через mq, то же, что и 12306.

Проектирование высоконагруженных систем

  1. Приложение не имеет статуса
  2. Эффективное использование кэша
  3. Применить разделение
  4. Разделение базы данных
  5. Асинхронная связь
  6. Неструктурированное хранилище данных (TFS, NOSQL)
  7. Система мониторинга и раннего предупреждения
  8. Настройка единого управления

В системе бронирования билетов на определенный поезд есть только один билет на поезд.Предполагается, что 1w человек одновременно открывают сайт 12306 для бронирования билетов.Как решить проблему параллелизма? (Можно распространить на любые параллельные проблемы чтения и записи, которые будут учитываться веб-сайтами с высокой степенью параллелизма.

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

В чем разница между распределенным и кластерным

Распределенный: бизнес разделен на несколько подбизнесов и развернут на разных серверах. Кластер: тот же бизнес, развернутый на нескольких серверах

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

  1. прием данных
  • Чтобы уменьшить нагрузку на сервер, клиент выберет задержку комбинированного запроса кликов для пакетной отправки.
  • На сервере определенно будет несколько компьютеров и несколько процессов, развернутых для приема запроса клика, и полученный запрос будет отправлен в хранилище после анализа параметров. Чтобы уменьшить нагрузку на хранилище, каждый процесс может использовать небольшое окно для агрегирования данных, а данные в этом окне агрегируются и отправляются в единицу хранения через короткие промежутки времени.
  1. хранилище данных
  • Используя хранилище kafka, механизм ZeroCopy обеспечивает высокий уровень параллелизма, а стоимость сохранения данных на диске низкая. Однако у данных kafka обычно есть время истечения срока действия.Если вы хотите полностью запомнить клик пользователя для долгосрочного анализа данных, вам нужно использовать hdfs
  1. Распределенный алгоритм TopN
  • Слишком много пользователей, и таблица пользователей разделена на 1024 подтаблицы в соответствии с хешем идентификатора пользователя. В таблице пользователей есть поле score, в котором указано количество баллов данного пользователя. Теперь мы хотим рассчитать 100 лучших пользователей с наибольшим количеством баллов и количеством баллов Как сделать запрос?
  • Если это одна таблица, будет выполнен один SQL,
  • Если имеется несколько подтаблиц, необходимо выполнить запрос TopN для каждой подтаблицы, а затем выполнить еще один запрос TopN для агрегированных результатов. Запросы к подтаблицам могут быть распараллелены несколькими потоками для повышения эффективности агрегирования.
  1. раздвижное окно
  • 8-часовое скользящее окно означает, что новые данные поступают непрерывно, старые данные постоянно удаляются, а бизнес может находиться в нескольких минутах ходьбы.
  • Мы делим квант времени, считаем один слот в минуту, удаляем первый, когда он истекает через 8 часов, вычисляем первое сообщение, сохраняем окно, удаляем просроченный слот, а затем подсчитываем первое время, 30-60-секундный вызов один раз.
  1. задача на время
  • У каждого дочернего узла будет запланированная задача, отвечающая за ведение статистического окна, просроченные и просроченные статистические данные, а также подсчет локальных топовых горячих сообщений.
  • Теперь, когда каждый дочерний узел имеет свои собственные локальные горячие сообщения, главный узел необходим для суммирования этих локальных горячих сообщений, а затем для вычисления глобальных горячих сообщений.
  1. Нажмите, чтобы дедуплицировать
  • Первое, что нужно сделать, это начать с клиента, который сам может фильтровать некоторые недействительные клики. Текущий пользователь неоднократно нажимает на одну и ту же статью за слишком короткий промежуток времени, и эту закономерность все еще легко обнаружить. Если интервал относительно длинный, это щелчок послевкусия читателя, который относится к положительному отзыву о статье и должен быть записан.
  • Сервер также должен предотвращать поведение пользователя, препятствующее пролистыванию. Если вам не хватает антибраш-контроля, вы можете использовать эту лазейку, чтобы ваша статья незаконно набирала много кликов, попадала в список популярных статей, ставила популярный тег и была замечена большим количеством пользователей, вы получите большую экономическую выгоду, даже если сама статья по содержанию недостаточно привлекательна.

Как решить проблему перепроданности веб-сайта электронной коммерции

что перепродано

  • Поскольку операция записи и операция чтения в нижней части базы данных могут выполняться одновременно, хотя операция записи по умолчанию имеет неявную блокировку (то есть одни и те же данные не могут быть записаны одновременно), операция чтения не имеет блокировки по умолчанию, поэтому, когда пользователь 1 изменяет инвентарь, пользователь 2 все еще может прочитать, что инвентарь равен 1, в результате чего два пользователя одновременно сокращают запасы, поэтому возникает явление перепроданности.

решение

  1. Используйте Redis для предварительного сокращения запасов
  2. Когда инвентарь больше 0, инвентарь можно обновитьupdate sk_goods_seckill set stock_count = stock_count - 1 where goods_id = #{goodsId} and stock_count > 0
  3. Добавьте уникальный индекс, UNIQUE KEYu_uid_gid (user_id,goods_id) ИСПОЛЬЗОВАНИЕ BTREE, чтобы запретить одному и тому же пользователю размещать два заказа на один и тот же продукт.
  4. Оптимистическая блокировка заключается в разработке поля номера версии в базе данных и добавлении его в +1 при каждом изменении, чтобы при отправке вы могли сравнить номер версии перед отправкой, чтобы узнать, отправляется ли она одновременно, но есть недостаток что его можно применить только к приложению. Если есть оптимистическая блокировка для изменения одних и тех же данных в разных приложениях, нет возможности ее контролировать. В настоящее время можно рассматривать пессимистичные блокировки.
  5. Пессимистическая блокировка предназначена для прямой блокировки данных на уровне базы данных, аналогично использованию select xxxxx from xxxx, где xx=xx для обновления в устной форме, чтобы другие потоки не могли отправлять данные.
  6. Асинхронное размещение заказов с использованием очередей сообщений

Сбой асинхронного вызова MQ, как обеспечить согласованность данных?

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

Несколько реализаций распределенных блокировок

  1. На основе таблицы базы данных
  • Для реализации распределенных блокировок проще всего создать таблицу блокировок напрямую, а затем сделать это, манипулируя данными в таблице.

  • Мы сделали уникальное ограничение на method_name (имя метода).Если в базу данных одновременно отправляется несколько запросов, база данных гарантирует, что только одна операция может быть успешной, тогда мы можем считать, что поток, который успешно выполнил операцию, получена блокировка метода. , содержимое тела метода может быть выполнено. После выполнения метода, если вы хотите снять блокировку, удалите запись

  1. Эксклюзивная блокировка базы данных
  • Распределенные блокировки могут быть реализованы через эксклюзивные блокировки базы данных.
  • Если for update добавляется после оператора запроса, база данных добавит эксклюзивную блокировку к таблице базы данных во время процесса запроса (здесь следует упомянуть еще одну вещь: когда механизм InnoDB заблокирован, он будет использовать только блокировки на уровне строк при извлечении). через индекс, иначе будут использоваться блокировки на уровне таблицы.Здесь мы хотим использовать блокировки на уровне строки, поэтому нам нужно добавить индекс к method_name
  • Стоит отметить, что этот индекс должен быть создан как уникальный индекс, иначе возникнет проблема, связанная с невозможностью одновременного доступа к нескольким перегруженным методам. Если вы перегружаете метод, рекомендуется также добавить тип параметра. ). Когда монопольная блокировка добавляется к записи, другие потоки не могут добавить монопольную блокировку к строке.
  1. на основе кэша
  • Например, метод put Таира, метод setnx redis и т.д. Кроме того, эти службы кэширования также обеспечивают поддержку автоматического удаления данных с истекшим сроком действия, и вы можете напрямую установить тайм-аут для управления снятием блокировок.
  1. На основе зоопарка
  • Когда каждый клиент блокирует метод, в каталоге указанного узла создается уникальный мгновенный упорядоченный узел, соответствующий методу на zookeeper. Способ определить, следует ли приобретать блокировку, очень прост, вам нужно только определить блокировку с наименьшим порядковым номером в заказанном узле. При снятии блокировки просто удалите переходный узел. В то же время это может избежать проблемы взаимоблокировки, когда блокировка не может быть снята из-за простоя службы.

очередь сообщений

Четыре отличия MQ

这里写图片描述

Как обеспечить высокую доступность очереди сообщений

  1. Кластер, взяв в качестве примера rcoketMQ, имеет режим множественного ведущего, режим асинхронной репликации множественного ведущего, множественного ведомого и режим синхронной двойной записи с множественным ведущим, множественным ведомым.

这里写图片描述
Производитель устанавливает постоянное соединение с одним из узлов (случайно выбранным) в кластере NameServer, периодически получает информацию о маршрутизации Topic от NameServer, устанавливает постоянное соединение с мастером-брокером, который предоставляет услуги Topic, и регулярно отправляет пульс на сервер. Маклер. Производитель может отправлять сообщения только Мастеру-брокеру, но Потребитель отличается от него, он устанавливает длительное соединение с Мастером и Слейвом, которые одновременно предоставляют услуги Темы, Он может подписываться на сообщения от Мастера-брокера и от Слейва-брокера. .

Как убедиться, что сообщения не используются повторно

причина:

  • После того, как потребитель потребляет, он отправит подтверждающее сообщение в очередь сообщений.После того, как очередь сообщений получит его, он удалит сообщение из очереди сообщений.Например, RabbitMQ отправляет подтверждающее сообщение ACK, а RocketMQ возвращает флаг успеха CONSUME_SUCCESS , Каждое сообщение kafka имеет смещение.После того, как Kafka использует сообщение, ему необходимо отправить смещение, чтобы сообщить очереди сообщений, что оно было использовано. Из-за сетевой передачи и других сбоев информация подтверждения не передается в очередь сообщений, поэтому очередь сообщений не знает, что она использовала сообщение, и снова распределяет сообщение среди других потребителей.

Решение:

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

популярная рамка

Как работает SpringMVC

这里写图片描述
Процесс SpringMVC

  1. Пользователь отправляет запрос на DispatcherServlet фронт-контроллера.
  2. DispatcherServlet получает запрос и вызывает обработчик отображения HandlerMapping.
  3. Преобразователь процессора находит конкретный процессор (который можно искать в соответствии с конфигурацией xml и аннотациями), генерирует объект процессора и перехватчик процессора (если есть) и возвращает его DispatcherServlet.
  4. DispatcherServlet вызывает адаптер обработчика HandlerAdapter.
  5. HandlerAdapter адаптирован для вызова определенного обработчика (контроллера, также называемого внутренним контроллером).
  6. Выполнение контроллера завершается и возвращается в ModelAndView.
  7. HandlerAdapter возвращает результат выполнения контроллера ModelAndView в DispatcherServlet.
  8. DispatcherServlet передает ModelAndView преобразователю представлений ViewReslover.
  9. ViewReslover возвращает определенное представление после синтаксического анализа.
  10. DispatcherServlet визуализирует представление в соответствии с представлением (то есть заполняет представление данными модели).
  11. DispatcherServlet отвечает пользователю.

Запрос ---> DispatcherServlet (интерфейсный контроллер) ---> вызов HandlerMapping (сопоставитель обработчика) ---> DispatcherServlet вызывает HandlerAdapter (адаптер обработчика) ---> адаптация вызова конкретного контроллера ---> return ModelAndView --- > Передать его ViewReslover View Parser ---> Вернуться к определенному представлению после анализа ---> Визуализировать представление в соответствии с представлением, чтобы ответить пользователю

Принцип MyBatis

MyBatis выполняет 2 вещи

  1. Инкапсулирует операции JDBC
  2. Используйте отражение, чтобы выполнить преобразование между классами Java и операторами SQL.

Ключевые участники MyBatis

  1. Конфигурация Вся информация о конфигурации MyBatis хранится в объекте Configuration, и большая часть конфигурации в файле конфигурации будет храниться в этом классе.
  2. SqlSession, как основной API верхнего уровня для работы MyBatis, представляет сессию при взаимодействии с базой данных и выполняет необходимые функции добавления, удаления, модификации и запросов к базе данных.
  3. Executor Executor MyBatis — это ядро ​​планирования MyBatis, отвечающее за генерацию операторов SQL и обслуживание кэша запросов.
  4. StatementHandler инкапсулирует операции операторов JDBC и отвечает за операции операторов JDBC, такие как установка параметров и т. д.
  5. ParameterHandler отвечает за преобразование параметров, переданных пользователем, в тип данных, соответствующий оператору JDBC.
  6. ResultSetHandler отвечает за преобразование объекта набора результатов ResultSet, возвращаемого JDBC, в коллекцию типа List.
  7. TypeHandler отвечает за сопоставление и преобразование между типами данных java и типами данных jdbc (или типами столбцов таблицы данных).
  8. MappedStatement MappedStatement поддерживает инкапсуляцию узла select|update|delete|insert
  9. SqlSource отвечает за динамическую генерацию операторов SQL в соответствии с параметромObject, переданным пользователем, инкапсуляцию информации в объект BoundSql и возврат
  10. BoundSql представляет динамически генерируемые операторы SQL и соответствующую информацию о параметрах.

这里写图片描述

Кэш MyBatis

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

这里写图片描述

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

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

<settings>
    <setting name="cacheEnabled" value="true"/>
</settings>

постскриптум

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