JAVA Октагон

опрос

1 основы Java

1.1 Основы

  1. Почему String определяется как final.

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

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

1.2 HashMap

  1. Какие методы обычно используются в HashMap и когда будет запускаться древовидная структура?
  2. Разница между реализацией jdk1.7 и 1.8, почему возникает тупик в реализации 1.7, пожалуйста, нарисуйте картинку для пояснения.
  3. Разница между HashMap и TreeMap.

1.3 Параллелизм

  1. Способ создания потока, жизненный цикл потока
  2. Принцип реализации ThrrealLocal, почему происходит утечка памяти
  3. Принцип ключевого слова volatile, как оно используется в проекте
  4. Разница между синхронизацией и блокировкой, лежащий в основе принцип реализации
  5. Принцип реализации очереди AQS, какие шаблоны проектирования используются. Как реализуются справедливые и нечестные блокировки, монопольные и разделяемые блокировки, а также блокировки чтения-записи и почему несправедливые блокировки выше, чем справедливые блокировки?
  6. Описание параметров пула потоков Java, как работает пул потоков, как настроить пул потоков
  7. Когда основной поток достигает состояния, ему требуется несколько подпотоков для выполнения задачи, а затем он отключается после выполнения подзадач (CountDownLatch).
  8. Напишите программу, которая печатает числа от 1 до 100 в двух потоках, что требует нескольких реализаций.

2 JVM

Сборщик мусора нового поколения zgc:Специальности.Meituan.com/2020/08/06/…

2.1 Область данных времени выполнения JVM и описание модели памяти, почему jdk8 удаляет область методов

jdk8 выходит из области метода:

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

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

2.2 Четыре вида различий в цитировании

  • Сильная ссылка: обычный новый объект является строгой ссылкой.Когда памяти недостаточно, JVM скорее выдаст исключение, чем вернет объект со строгой ссылкой.
  • Мягкая ссылка (SoftReference): Жизненный цикл мягкой ссылки ниже, чем у строгой ссылки.Когда памяти недостаточно, объект мягкой ссылки будет переработан. Мягкие эталонные объекты часто используются вместе с эталонной очередью ReferenceQueue.После того, как объект, на который ссылается программная ссылка, будет возвращен GC, эта ссылка будет добавлена ​​в эталонную очередь.
  • Слабая ссылка (WeakReference): Жизненный цикл слабой ссылки короче, чем у мягкой ссылки.В следующем GC есть такой объект в подведомственной ей области: на объект указывает только слабая ссылка, но не указывает to по любой другой строгой ссылке, объект будет переработан независимо от того, достаточно ли текущей памяти. Слабые ссылки, как и мягкие ссылки, часто используются вместе с очередью ссылок ReferenceQuene.После того, как объект, на который ссылается слабая ссылка, истребуется сборщиком мусора, эта ссылка будет добавлена ​​в очередь ссылок.
  • Фантомная ссылка (PhantomReference): Также известная как фантомная ссылка, в отличие от мягкой ссылки и слабой ссылки, объект, на который указывает виртуальная ссылка, очень хрупок, и мы не можем получить объект, на который указывает метод get. Его единственная функция заключается в том, что когда объект, на который он указывает, становится недостижимым, он добавляется в очередь ссылок, чтобы записать, что объект, на который указывает ссылка, был уничтожен. Поэтому независимо от того, переопределяет ли объект метод finalize, виртуальный эталонный объект не может быть восстановлен.Виртуальная ссылка была добавлена ​​в очередь ссылок, поэтому, естественно, нет возможности поместить ее в очередь F-Queue, и метод finalize больше не может выполняться.

2.3 GC

  1. Алгоритм сборки мусора и сборщик мусора описывают, какие сборщики мусора используются в новом поколении и в работе старого поколения.

    немного.

  2. Когда молодое поколение и старое поколение вызовут GC.

    • Новое поколение: MinorGC будет запускаться при нехватке памяти в области Eden
    • Старость:
    • Запускается, когда объекты нового поколения устаревают, что приводит к нехватке места
    • Когда большой объект напрямую входит в старость, он срабатывает, когда в старости не хватает места.

    Выбрасывает OOM, когда в старом поколении не хватает места

  3. Описание процесса сборки мусора CMS, в чем недостатки CMS по сравнению с G1.

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

  4. Вы практиковали этапы настройки GC?

    Просмотр GC и другого связанного статуса с помощью таких инструментов, как jstat

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

2.4 Описать процесс загрузки классов JVM и способы настройки загрузчика классов.

Процесс загрузки класса JVM

Загрузить ----> Подключить -----> Инициализировать.

  • Загрузка: чтение двоичных данных из файла .class в область метода в памяти, создание объекта класса в куче, указание на данные класса в области метода
  • соединять:
    • Проверка: корректность бинарных файлов
    • Подготовка: Выделить место, значения по умолчанию для статических переменных класса, присвоить значения константам
    • Решение: символические ссылки заменены указателями.
  • Инициализация: присвоить начальные значения статическим переменным класса

пользовательский загрузчик классов

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

  • Наследовать класс ClassLoader
  • Переопределите метод findClass(String className).В методе findClass вызовите метод defineClass родительского класса CLassLoader, чтобы передать байт-код виртуальной машине.

2.5 Опишите модель родительского делегирования и зачем она нужна.

немного.

2.6 Как реализуются дженерики.

Дженерики Java являются дженериками только во время компиляции.После компиляции в байт-код, дженерики стираются, что совпадает с байт-кодом, навязанным Object.

2.7 Анализ побега

Анализ побега — это анализ побега объекта с помощью JVM, который бывает двух типов:

1. Выход из метода: когда объект определен в методе, он передается в качестве параметра другим методам; 2. Выход из потока: например, переменные класса или переменные экземпляра, к которым могут обращаться другие потоки;

Когда JVM определяет, что объект не будет экранирован, она выполняет следующие оптимизации: исключение синхронизации, скалярную замену и выделение стека.

Устранение синхронизации

Синхронизация потоков сама по себе является относительно затратной, если определено, что объект не выйдет из потока и не будет доступен другим потокам, то конкуренции за чтение и запись объекта не будет, и синхронизирующая блокировка объекта может быть снята. устранено.-XX:+EliminateLocksСинхронизацию можно включить.

скалярная замена

1. Скаляр относится к неделимой величине, такой как базовый тип данных и ссылочный тип в Java, а относительные данные могут продолжать разлагаться, что называется совокупной величиной; 2. Если объект демонтируется и его переменные-члены восстанавливаются до базового типа для доступа, это называется скалярной заменой; 3. Если escape-анализ обнаружит, что к объекту не будет доступа извне и объект можно будет демонтировать, то после оптимизации объект не будет генерироваться напрямую, а в стеке будет создано несколько переменных-членов; пройти через-XX:+EliminateAllocationsможно включить скалярную замену,-XX:+PrintEliminateAllocationsПроверьте скалярную замену.

выделение стека

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

2.8 Как устранять неполадки OOM и утечки памяти, какие инструменты используются и как их найти, если никакие инструменты не используются.

Наиболее распространенная ошибка OOM заключается в том, что использование памяти в куче достигло максимального значения, установленного -Xmx.Решение по-прежнему состоит в том, чтобы сначала проверить на уровне кода, подозревая утечку памяти, и найти проблему с помощью jstack и карта Если все в норме, необходимо расширить память, отрегулировав значение Xmx.

  • В общем случае укажите -XX:+HeapDumpOnOutOfMemoryError в параметрах запуска для автоматического сохранения файла дампа во время OOM.
  • Вы также можете использовать JMAP для экспорта файла дампа, а затем использовать jvisualvm, чтобы открыть файл дампа, проверить количество экземпляров класса, коэффициент использования памяти экземпляра класса для проверки утечек памяти кучи, а также просмотреть потоки в дампе кучи.

jmap -dump:format=b,file=filename pid

  • использоватьjmap -heap pidПросмотр информации о куче, статусе GC илиjmap -histo:live pidПросмотр использования памяти, количество экземпляров класса, размер.

jconsole — это инструмент, который может отслеживать JVM в режиме реального времени, как и jvisualvm, это инструмент, который поставляется с jdk.

Основными причинами утечек памяти являются: неправильное закрытие файлового потока, статическая хеш-карта, элементы в объекте List не будут переработаны, а выделение кеша ByteBuffer является необоснованным.

2.9 Как устранить неполадки, когда нагрузка на машину становится высокой

Загрузка ЦП становится высокой: бесконечный цикл, частый сборщик мусорабесконечная петля

  • Команда Top для просмотра процессов с высокой загрузкой процессора
  • Просмотреть все потоки соответствующего процесса:top -Hp pid-H отображать информацию о потоке -p указать pid
  • Дамп jstack в файл для удобного просмотра.jstack pid/nid > myjstack.log

нужно сосредоточиться на"java.lang.Thread.State", WAITING, TIMED_WAITING, BLOCKED, представляют потоки, которые заблокированы и находятся в ожидании. Как правило, потоки с бесконечным циклом находятся в состоянии RUNNABLE, а информация о стеке будет отображаться как циклические вызовы.

GC

  • Проверить статус GC:jstat -gc pid 1000, 1000 представляет интервал выборки.
    S0C    S1C    S0U    S1U      EC       EU        OC         OU       MC     MU    CCSC   CCSU   YGC     YGCT    FGC    FGCT     GCT
    2560.0 2560.0 385.7   0.0    4096.0   1078.1   11264.0     7476.1   14848.0 14366.9 1792.0 1679.0     12    0.057   0      0.000    0.057
    12

Первая информация о выборке, как указано выше, означает:

  • Для S0C S1C S0U S1U EC EU OC OU MC MU CCSC CCSU завершающий символ C указывает емкость, а U указывает использование. S0/S1 — это две области Survivor, E представляет собой область Eden, O — старость, а M — область метаданных.
  • Для YGC YGCT FGC FGCT GCT конечный символ C представляет количество GC, T представляет время, затраченное на GC, YG представляет Young GC, FGC представляет собой Full GC, а GCT представляет общее время, затраченное на все GC.

3 Весенний фреймворк

3.1 Какие шаблоны проектирования используются в среде Spring

  • Шаблон прокси: Spring AOP
  • Режим Singleton: компоненты, созданные контейнером Spring IOC, по умолчанию находятся в режиме singleton.
  • Фабричный шаблон: BeanFactory используется для создания экземпляров объектов.
  • Режим наблюдателя: например, ApplicationListener, ContextEventListener
  • Режим оболочки: классы с суффиксом Wrapper используют режим оболочки для динамического добавления дополнительных обязанностей к bean-компонентам.
  • Режим адаптера: класс в конце адаптера принимает режим адаптера, который делает совместимыми изначально несовместимые интерфейсы.

3.2 Подробное описание жизненного цикла Spring

Когда начинается весна, сначала загружается beanFactory, создается класс factory, а затем создается компонент.Жизненный цикл компонента в основном:инстанцирование, заполнение свойств, инициализация, использовать, уничтожить.

3.3 Как Spring разрешает циклические зависимости

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

  • Кэш первого уровня: bean-компонент инициализирован, успешно создан
  • Кэш второго уровня: создание экземпляра компонента завершено, свойства еще не заполнены
  • Кэш третьего уровня: singletonFactories, в котором хранятся бины singleton factory.
一级缓存:
/** 保存所有的singletonBean的实例 */
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>(64);

二级缓存:
/** 保存所有早期创建的Bean对象,这个Bean还没有完成依赖注入 */
private final Map<String, Object> earlySingletonObjects = new HashMap<String, Object>(16);
三级缓存:
/** singletonBean的生产工厂*/
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<String, ObjectFactory<?>>(16);
 
/** 保存所有已经完成初始化的Bean的名字(name) */
private final Set<String> registeredSingletons = new LinkedHashSet<String>(64);
 
/** 标识指定name的Bean对象是否处于创建状态  这个状态非常重要 */
private final Set<String> singletonsCurrentlyInCreation =
    Collections.newSetFromMap(new ConcurrentHashMap<String, Boolean>(16));

3.4 Что такое точки расширения Spring и как они применяются в проекте

Когда контейнер запустится, выполните refreshContext:

  • При загрузке beanFactory вы можете добавитьBeanFactoryPostProcessor, чтобы перехватить создание beanFactory.
  • После загрузки beanFactory начните создавать экземпляр компонента и вызывать его до и после создания экземпляра компонента.InstantiationAwareBeanPostProcessorметоды до и после.
  • До и после инициализации компонента вызовитеBeanPostProcessorметоды до и после
  • После завершения инициализации контейнера вызывается ContextEventListener.

3.5 Spring IOC, описание АОП

немного.

3.6 Разница между транзакцией Spring и транзакцией MySQL, введение механизма распространения транзакций Spring, сбой транзакции Spring и решения

3.7 Как написать глобальный захват исключений Spring

3.8 Реализация динамического прокси AOP: различия между динамическим прокси jdk и реализацией cglib, почему производительность cglib выше, чем производительность динамического прокси jdk, и какие методы не могут быть динамически проксированы в соответствии с описанием механизма Fastclass.

jdk и cglib:

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

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

механизм фаслкласса:

Прокси jdk находит указанный метод через рефлексию, а cglib напрямую вызывает метод через механизм fastclass.При создании класса прокси для метода в нем устанавливается хэш-индекс, и вызов осуществляется через хэш-индекс, который повышает эффективность.

Какие методы нельзя динамически проксировать:

равно, хэш-код, getClass.

3.9 Примеры сбоев АОП, почему и как их решить

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

Решение: используйте @Autowired для внедрения прокси-объекта текущего класса и вызовите метод через этот объект.

3.10 Разница между BeanFactory и FactoryBean

- BeanFactory是个bean 工厂,是一个工厂类(接口), 是spring用来管理和装配普通bean的ioc容器。ApplicationContext实现并扩展了该接口,ApplicationContext是扩展后的ioc容器。
- FactoryBean是个bean,在IOC容器的基础上给Bean的实现加上了一个简单工厂模式和装饰模式,是一个可以生产对象和装饰对象的工厂bean,由spring管理后,生产的对象是由getObject()方法决定的,主要用来实现复杂的bean的创建(比如连接工厂等),类似于@Bean配置。

3.11 Spring создает одноэлементный объект Если несколько потоков одновременно присваивают значения свойствам, что приводит к взаимному покрытию, как с этим бороться

通过ThreadLocal去解决线程安全的方法,ThreadLocal为每个线程保存线程私有的数据。

3.12 Разница между SpringMVC и SpringBoot

Spring Boot实现了自动配置,降低了项目搭建的复杂度。

3.13 Поговорим об автоматической настройке Springboot

通过@EnableAutoConfiguration注解实现自动化配置,过程分为三步:

- 获取配置工厂类的全限定名,由EnableAutoConfigurationImportSelector扫描各组件jar的META-INF目录下的spring.factories文件中的配置工厂类(*Configuration.class)的全限定名。
- 配置工厂类的加载,在refreshContext时,SpringFactoriesLoader加载第一步扫描到的工厂类,实例化,将工厂配置bean置于ioc容器中。
- 在springContext环境中,使用beanFactory创建bean实例

3.14 Процесс запуска Springboot

Springboot的启动,主要创建了配置环境(environment)、事件监听(listeners)、应用上下文(applicationContext),并基于以上条件,在容器中开始实例化我们需要的Bean。

(1)创建一个SpringApplication对象实例,然后调用这个实例的run方法
(2)创建了应用的监听器SpringApplicationRunListeners,启动监听器
(3)创建并配置environment,environment主要负责读取spring的application.yml配置
(4)创建applicationContext
(5)prepareContext方法将listeners、environment、applicationArguments、banner等重要组件与上下文对象applicationContext关联
(6)refreshContext方法负责spring自动化配置,包括spring.factories的加载,beanFactory的创建,bean的实例化
(7)最后,运行springContext

4 MySQL

4.1 КИСЛОТА Транзакции

Транзакция — это набор атомарных операторов SQL, которые либо выполняются полностью, либо не могут откатиться.

Транзакция — это 4 условия, которые должны быть выполнены (ACID):

  • атомарность: Все операции в транзакции либо завершены, либо не завершены, и не будут заканчиваться определенной ссылкой посередине.
  • Последовательность: Целостность базы данных не была нарушена до начала транзакции и после завершения транзакции
  • Изоляция: при одновременном выполнении несколько транзакций изолированы друг от друга.
  • Долговечность: После завершения транзакции изменение данных является постоянным.

Изоляция достигается с помощью MVCC, MVCC достигается с помощью отмены регистрации, а постоянство достигается с помощью повторной регистрации.

4.2 Уровень изоляции транзакции

MySQL имеет четыре уровня изоляции транзакций:Read uncommited、Read commited、Repeatable read、Serializable, по умолчаниюRepeatable read

4.2.1 Механизм MVCC

Уровень изоляции транзакций зависит от реализации MVCC (Multi-Version Concurrency Control), которая используется для улучшения параллелизма операций чтения.

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

  • create_version: номер версии транзакции, которая создала строку.
  • delete_version: номер версии транзакции для удаления строки данных.

Взяв в качестве примера уровень RR, MVCC читает, вставляет, удаляет и обновляет:

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

  • Вставка: создайте новую запись и запишите номер версии текущей транзакции в create_version.

  • Удалить: установите текущий номер версии системы в значение версии_удаления этой строки.

  • Обновление: скопируйте старую запись, создайте новую копию данных строки, установите номер версии текущей транзакции на create_version новой строки и delete_version старой строки.

На уровне RR Mysql делает снимок номера версии строки в начале транзакции и только считывает снимок в будущем. На уровне изоляции RC MySQL считывает только номер последней версии. Один называется чтением моментального снимка, а другой — текущим чтением.

Преимущества MVCC: поддерживает параллельное чтение без блокировки и улучшает параллелизм.

Недостатки MVCC: необходимо поддерживать несколько версий для одной и той же строки записей, что занимает больше места.

4.2.2 Фантомные чтения и повторяющиеся чтения

Repeatable readПроблема с уровнями изоляции заключается в том, что могут возникать фантомные чтения. Фантомное чтение и повторяемое чтение — совершенно разные понятия.

В базе есть несколько записей, среди которых 10 данных с appId как testappid.

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

  • Заблокируйте всю таблицу, пока открыта транзакция, которая считывает данные. Это самый высокий уровень изоляции транзакций: Serializable, сериализация.
  • На уровне повторного чтения добавьте разделяемые блокировки или эксклюзивные блокировки, и механизм innoDB будет активно добавлять блокировки пробелов, чтобы избежать фантомных чтений.

Поэтому лучший способ избежать фантомного чтения — второй: RR+gap lock

4.2.3 Что такое гэп-лок и как его избежать?

Блокировка промежутка: блокирует диапазон, но не включает саму запись. Действует на уровне >RR. При работе с блокировками (чтение, обновление и удаление с блокировками) InnoDB будет активно использовать блокировки промежутка. условия, диапазон блокировки следующим образом:

  • Условие соответствия - это диапазон, заблокируйте диапазон
  • Условие сопоставления равно "==", результат сопоставления не пуст, а открытый интервал, в котором находится совпадающая запись, заблокирован
  • Условие сопоставления равно значению "==", результат сопоставления пуст, а открытый интервал слева и справа от записи заблокирован.

Данные дочерних узлов листа индекса B+ располагаются по порядку, а данные между двумя листами называются пробелом.При чтении с блокировкой на уровне RR Mysql блокирует пробел, соответствующий условиям запроса, чтобы избежать других транзакции между листами Вставка новых данных между ними уничтожает RR.

Как избежать гэп-блокировок:

  • Используя уникальный индекс, Mysql больше не будет добавлять гэп-блокировки при совпадении одинаковых значений
  • Уровень изоляции установлен на RC
  • Mysql активно использует блокировки намерения вставки. Для операций вставки mysql сначала пытается добавить блокировку намерения вставки, которая не будет блокировать операции вставки других транзакций, повышая эффективность параллельных вставок. Предпосылка получения блокировки намерения вставки состоит в том, что нет блокировки промежутка, как только естьselect ... for update、select ... lock in share mode、delete、updateзаявление, блокировка намерения вставки недействительна.

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

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

Вложенные подзапросы неэффективны: при выполнении подзапросов MYSQL необходимо создавать временные таблицы, а затем удалять эти временные таблицы после завершения запроса, добавляя процесс создания и уничтожения временных таблиц

Схема оптимизации вложенных подзапросов: 1. Использование объединения, объединение более эффективно, чем вложенные подзапросы. Когда объем данных велик, нет необходимости вводить разные параметры для итерации цикла. 2. Разделение на несколько операторов запроса.

4.4 Как найти и решить медленный запрос

  1. Временно включить журнал медленных запросовset global slow_query_log=1

  2. Найдите путь к файлу журнала медленных запросовshow variables like 'slow_query_log_file

  3. Используйте инструмент анализа журнала, предоставляемый msql.mysqldumpslow Проанализируйте и найдите десять sql с самым медленным временем запроса:

    mysqldumpslow -s 10 /mysql/mysql01_slow.log

  4. Используйте объяснение для анализа этих 10 SQL-запросов, таких как:explain SQL_NO_CACHE select * from emp where name = 'Jefabc'

    SQL_NO_CACHE указывает, что запрос не отправляется в кеш, что позволяет избежать высокой и низкой скорости запроса, что влияет на оценку.

    img

    возможных_ключей: указывает индексы, которые могут использоваться при запросе

    ключ: указывает фактический используемый индекс

    rows: количество просканированных строк (оценочное количество строк)

    Дополнительно: Описание и описание реализации

    ps: используйте объяснение, чтобы убедиться, что индекс используется правильно, и постарайтесь не возвращаться к таблице.

  5. Дальнейший анализ по профилю,show profile for query id, вы можете ясно видеть все этапы выполнения sql, такие как ожидание блокировки, выполнение, оптимизация, отправка данных и сортировка памяти.На рисунке ниже видно, что отправка данных занимает 1,39 с. Основной причиной медленных запросов является сетевой ввод-вывод.

    img

4.5 binlog и репликация master-slave

Репликация master-slave используется для разделения чтения и записи, записи главной библиотеки и чтения подчиненной библиотеки, что реализуется binlog.

4.5.1 формат двоичного журнала

Бинлог в MySQL представляет собой двоичный файл, в котором записываются все добавления, удаления и модификации. Репликация между узлами зависит от binlog для завершения

binlog имеет три режима:

  • Рядный режим Журнал будет записывать журнал каждой изменяемой строки данных, а затем изменять те же данные на ведомой стороне.
  • режим оператора Запишите каждый sql, который изменяет данные. Когда раб копируетsql ThreadВыполните sql, выполненный мастером, снова
  • смешанный режим Смешанный означает смешанный режим.MySQL различает форму журнала для записи в соответствии с каждым конкретным выполняемым оператором SQL, то есть выбирает один из операторов и строк.

4.5.2 Процесс репликации ведущий-ведомый

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

mysql-master-slave

4.5.3 Задержка и потеря данных репликации ведущий-ведомый

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

решение:полусинхронная репликация, используется для решения проблемы потери данных в основной базе данных;Параллельная репликация, используется для решения проблемы задержки синхронизации master-slave

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

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

Если параллелизм по-прежнему высок, необходимо рассмотреть возможность разделения основной библиотеки на несколько основных библиотек (подбиблиотеки и подтаблицы).Как правило, параллелизм записи одной основной библиотеки контролируется на уровне 2000/с.

4.6 Подбиблиотека и подтаблица.

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

4.6.1 Вертикальная и горизонтальная сегментация

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

Горизонтальная сегментация: Разделение таблиц по строкам.Данные одной таблицы разбиваются на несколько таблиц, например, одна таблица с данными по 3000 Вт делится на 3 таблицы, по 1000 Вт в каждой.

4.6.2 Способ подбиблиотеки и подтаблицы

В некоторой степени похоже на стратегию сегментирования кластера MongoDB.

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

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

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

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

4.6.3 Промежуточное ПО для суббазы данных и субтаблицы

Sharding-jdbc

Dangdang имеет открытый исходный код и относится к схеме клиентского уровня, которая поддерживает подбазу данных и подтаблицу, разделение чтения и записи, распределенную генерацию идентификатора, гибкую транзакцию (транзакция с доставкой по максимуму, транзакция TCC)

Mycat

Он относится к схеме прокси-уровня, и поддерживаемые функции очень полны.

Сравнение двух:

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

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

4.6.4 Как плавно переходить между подбиблиотеками и подтаблицами

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

Схема миграции с двойной записью

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

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

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

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

Разделите 32 виртуальные логические библиотеки одновременно, каждая с 32 таблицами, и реализуйте динамическое расширение и сжатие, управляя отношениями отображения между виртуальной библиотекой и реальной физической машиной.Остальное — проблема переноса данных. Обратитесь к идее Hash Slot для redis.

4.5.6 Как работать с идентификатором первичного ключа подбазы данных и подтаблицы

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

4.7 Указатель

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

4.7.1 Проталкивание индекса

Предположим, что имеется совместный индекс abc. Существует следующий оператор SQL:

select * from itemcenter where a like 'aa%' and b=22 and c = 20;

В соответствии с правилом сопоставления слева для извлечения данных можно использовать только "a", а два поля bc использовать нельзя. До MySQL 5.6 вы могли возвращаться к таблице только один за другим, находить строку данных в индекс первичного ключа, а затем сравните значения полей b и c.

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

4.7.2 буфер изменений и уникальный индекс

change buffer: уменьшить дисковый ввод-вывод

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

ps: буфер изменений имеет копию в памяти и также будет записан на диск

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

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

4.7.3 Как оптимизировать индекс для очень длинных полей

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

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

4.7.4 Что еще может повысить эффективность индексации

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

4.8 Вылетает при сбросе, как восстановить

Когда mysql записывает данные, он сначала записывает данные в буфер, а затем сбрасывает их на диск.Если в процессе сброса происходит время простоя, как восстановить данные.

Механизм WAL (Write-Ahead Logging) и журнал повторов гарантируют, что при открытии транзакции операции в транзакции будут сначала записаны в буфер журнала механизма хранения, а журнал повторов будет сохранен до того, как транзакция будет зафиксирована.

На любом шаге 1-8 система не работает и транзакция не зафиксирована, и транзакция не окажет никакого влияния на данные на диске.

Если система вылетает после 9 и измененные данные в карте памяти не сбрасываются обратно на диск, то после восстановления системы можноСбросить данные обратно на диск в соответствии с журналом повторов

1.start transaction;
2.记录 A=1 到undo log;
3.update A = 3;
4.记录 A=3 到redo log;
5.记录 B=2 到undo log;
6.update B = 4;
7.记录B = 4 到redo log;
8.将redo log刷新到磁盘
9.commit

5 Redis

  1. Тип данных Redis, скажем, как реализована таблица переходов и какую структуру данных можно использовать для ее замены.
  2. Каковы политики удаления ключей с истекшим сроком действия, политики удаления памяти и когда они срабатывают?
  3. Модель потоков Redis и модель памяти.
  4. Механизм сохранения Redis.
  5. Кластерное решение Redis.
  6. Позвольте вам разработать Redis, что бы вы сделали, если бы вы видели исходный код Redis?
  7. Знаете ли вы последовательный алгоритм хеширования?Опишите его.
  8. Реализуйте распределенную блокировку с помощью Redis.
  9. Проникновение кеша, разбивка кеша, различия лавин кеша и решения.
  10. Вы знаете фильтр Блума, расскажите принцип.
  11. принцип реализации zset. Какова функция пропуска таблицы и функция dict?

5.1 Сколько узлов у вашего Redis Sentinel?

3, дозорный Redis обычно выбирает нечетное число, ему нужно проголосовать за принятие решения, а нечетное число может соответствовать требованию «большинства».

5.2 Распределенные блокировки Redis и zookeeper

RedLock используется онлайн как распределенный замок

RedLock

Диссоны распределенных замков redisson.getLock(): Блокировка потеряна. Блокировка получена на главном узле Redis, но заблокированный ключ не был синхронизирован с подчиненным узлом; мастер выходит из строя, происходит аварийное переключение, и подчиненный узел обновляется до главного узла, что приводит к потере блокировки Автор Redis предложил более продвинутый метод реализации распределенных блокировок:Redlock.

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

RLock lock1 = redisson1.getLock("lock1");
RLock lock2 = redisson2.getLock("lock2");
RLock lock3 = redisson3.getLock("lock3");

RLock redLock = anyRedisson.getRedLock(lock1, lock2, lock3);

// traditional lock method
redLock.lock();

// or acquire lock and automatically unlock it after 10 seconds
redLock.lock(10, TimeUnit.SECONDS);

// or wait for lock aquisition up to 100 seconds 
// and automatically unlock it after 10 seconds
boolean res = redLock.tryLock(100, 10, TimeUnit.SECONDS);
if (res) {
   try {
     ...
   } finally {
       redLock.unlock();
   }
}

zk распределенный замок

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

N клиентов конкурируют за распределенную блокировку zk, и принципы аналогичны.

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

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

img

Сравнение распределенных замков redis и распределенных замков zk

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

  • Если клиент, который перераспределил блокировку, имеет ошибку или зависает, блокировка может быть снята только по истечении периода ожидания; для zk, поскольку создается временный znode, пока клиент зависает, znode исчезает. автоматически освобождается.

Короче говоря, распределенная блокировка zk более надежна, чем распределенная блокировка redis, а модель проста и удобна в использовании.

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

5.3 Проблема bigKey в Redis

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

Максимальный размер ключа и значения в Redis – 512 МБ. Если размер значения превышает 512 МБ, Redis сообщит об ошибке. Если значение слишком велико, это приведет к: недостаточному объему памяти, длительному сетевому вводу-выводу и длительному времени блокировки.

Решение: разбить данные (большое значение), хранящиеся в большом ключе, на значение1, значение2... значениеN.

Например: если большое значение представляет собой большой список, вы можете разделить список на: список_1, список_2, список3, списокN.

5.4 Проблема горячих клавиш Redis

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

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

  • Горячий новостной контент в новостных приложениях;
  • Конфигурация действия, в котором пользователь активно участвует в системе действий;
  • В системе seckill торгового центра самая привлекательная и рентабельная информация о продукте;

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

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

5.5 Лавина кеша, пробой, проникновение

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

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

разбивка кеша: Для хоткея просто истекает срок действия кеша, и большое количество запросов будет падать на базу (хоткей не истечет во время настройки)

6 Dubbo

  1. Описать процесс вызова rpc
  2. Позвольте вам реализовать структуру rpc, как бы вы это сделали.
  3. Понимаете ли вы механизм отслеживания и слияния ссылок, а также то, как реализован уровень фреймворка.
  4. Знайте, какие есть протоколы сериализации, в чем их отличия и какой протокол используется в проекте.
  5. Расскажите о Netty, о разнице между bio, nio и aio, о разнице между select, poll и epoll и о механизме нулевого копирования.

7 MQ

7.1 Пакетная обработка сообщений

7.1 1. Как улучшить пропускную способность mq

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

channel.addConfirmListener(new ConfirmListener() {
  @Override
  public void handleNack(long deliveryTag, boolean multiple) throws IOException {
    System.out.println("nack: deliveryTag = " + deliveryTag + " multiple: " + multiple);
  }

  @Override
  public void handleAck(long deliveryTag, boolean multiple) throws IOException {
    System.out.println("ack: deliveryTag = " + deliveryTag + " multiple: " + multiple);
  }  
});

Когда производитель получает сообщение подтверждения, отправленное Брокером, он вызывает метод handleAck, а когда он получает подтверждение, он вызывает метод handleNack.

7.1.2 Как rabbitmq контролирует трафик?

Используйте параметр prefetch_count, чтобы указать количество сообщений, предварительно выбранных потребителями. Когда это значение превышено, rabbitMQ не будет отправлять сообщения потребителям. Для каждого отправленного сообщения prefetch_count вычитается на 1, а prefetch_count увеличивается на 1 для каждого ACK сообщение потребителя.

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

8 Zookeeper

  1. тип узла zookeeper, роль сервера, механизм наблюдения
  2. Опишите протокол ZAB.
  3. сценарии применения.
  4. Используйте zookeeper для реализации распределенных блокировок и блокировок чтения-записи.

9 Netty

9.1 Представьте NIO и подробно объясните разницу между select, poll и epoll

9.1.1 NIO

NIO — это мультиплексирование ввода-вывода, а нижний уровень основан наselect、poll、epoll、kqueueвыполнить. Мультиплексирование блокировки нескольких IO на блокировку одного и того же select, чтобы система могла одновременно обрабатывать несколько клиентских запросов в случае одного потока, что экономит системные ресурсы по сравнению с созданием потока для одного запроса.

select/epollПреимущество состоит в том, что один поток может одновременно обрабатывать ввод-вывод нескольких сетевых соединений.Его основной принцип заключается в том, чтоselect、poll、epollОн будет непрерывно опрашивать все сокеты, за которые он отвечает, и если какой-либо из сокетов имеет данные для перехода в состояние готовности, он уведомит пользовательский процесс, и пользовательский процесс вызовет его снова.recvfromОперация копирования данных из ядра в пользовательский процесс (epoll использует нулевое копирование)

Нулевое копирование: подробности см. в разделе 9.3.1.. Через отображение памяти mmap пространство пользователя может совместно использовать данные в пространстве ядра, уменьшая пространство ядра -> копирование памяти пространства пользователя. Это решает дилемму, связанную с необходимостью копирования файловых данных в JVM для работы. Вместо этого он работает непосредственно в пространстве ядра, устраняя необходимость копировать пространство ядра в пространство пользователя. DirectByteBuffer в JAVA является ссылкой на эту память.

9.1.2 Различия между select, poll и epoll

epollСравниватьselect/pollОн более эффективен и имеет следующие преимущества:

  • epoll поддерживает большее количество одновременных подключений:selectСамый большой недостаток в том, что открывается один процессsocket_fdОграничение есть, значение по умолчанию 1024, а у epoll этого ограничения нет, верхний предел поддерживаемого им FD — это максимальное количество дескрипторов файлов операционной системы, которое намного больше 1024, и имеет относительно большие отношения с памятью. это дескриптор 10w, и конкретное значение может быть передано черезcat /proc/sys/fs/file-maxПроверить.
  • Эффективность ввода-вывода epoll не будет уменьшаться линейно с увеличением количества FD.:select/pollКаждый вызов будет линейно сканировать всю коллекцию, что приведет к линейному снижению эффективности.epollРеализуется через обратные вызовы интерфейса, в каждомsocket_fdдобавитьcallbackинтерфейс, только готовыйsokcetпозвонитcallback, эффективность ввода-вывода не будет обратно пропорциональна количеству FD.
  • epoll использует mmap для ускорения передачи сообщений между ядром и пользовательским пространством.:Будь тоselect、pollвсе ещеepollОба требуют, чтобы ядро ​​уведомляло сообщение FD в пространство пользователя, очень важно, как избежать ненужного копирования памяти,epollчерез ядро ​​и пространство пользователяmmapреализованы в той же памяти.

9.2 Модель потоков Netty

Зарегистрируйте обработчик события accepter в пуле потоков mainReactor, чтобы mainReactor прослушивал запросы на подключение от клиента к серверу.

img

Когда клиент инициирует запрос на подключение к серверу, mainReactor прослушивает запрос и отправляет событие обработчику события acceptor для обработки.Connection socketChannel можно получить через метод accept, а затем socketChannel передается в поток subReactor бассейн.

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

9.3 Подробное описание DirectByteBuffer

9.3.1 DirectByteBuffer и нулевая копия JAVA

Когда операция чтения файла инициируется в Java, последовательность потока данных следующая:磁盘 ---> 内核态 ---> 堆外内存 ---> JVM内存

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

На самом деле суть в том, чтобы уменьшить количество копий между памятью, DirectByteBuffer выделяет память вне кучи, на одну меньше堆外内存 ---> JVM内存копия, это просто оптимизация для пользовательского режима.

Копирование между пользовательским режимом и режимом ядра также оптимизировано, суть в том, чтобы сопоставить логический адрес пользовательского режима и логический адрес режима ядра с одним и тем же физическим адресом через mmap, поэтому оптимизирован DirectByteBuffer.内核态 ---> 堆外内存копировать.

9.3.2 Когда освобождается память вне кучи, на которую указывает directByteBuffer?

После восстановления объекта DirectByteBuffer виртуальной машиной JVM освобождается память вне кучи.

принцип: при создании объекта DirectByteBuffer виртуальная ссылка будет добавлена ​​к объекту DirectByteBuffer: Cleaner.Когда объект DirectByteBuffer будет переработан, JVM добавит его в очередь ссылок, а затем JVM определит из очереди ссылок, что DirectByteBuffer имеет виртуальную ссылаться как Cleaner, и JVM будет активно вызывать метод clean для очистки памяти вне кучи.

cleaner = Cleaner.create(this, new Deallocator(base, size, cap));

9.3.3 Утечка памяти DirectByteBuffer вне кучи

Как упоминалось ранее, непосредственная память, выделенная DirectByteBuffer, может быть освобождена только после освобождения объекта DirectByteBuffer. Если большая часть объектов DirectByteBuffer перемещена в старую возрастную категорию, а полный сборщик мусора не был запущен, возможно исчерпана физическая память вне кучи, поэтому во избежание этого укажите максимальный размер вне кучи с помощью -XX :MaxDirectMemorySize Размер памяти. При создании объекта DirectByteBuffer для применения к памяти вне кучи он определяет, достиг ли объем памяти вне кучи пороговое значение. утилизировать устаревший объект DirectByteBuffer.Освобождение неиспользуемой памяти вне кучи.

9.4 Наклеивание и распаковка

TCP — это «потоковый» протокол, так называемый поток — это последовательность данных без границ и разделений. TCP будет разделять пакеты в соответствии с фактическим состоянием буфера.Полный пакет может быть разделен на несколько пакетов для передачи или несколько небольших пакетов могут быть инкапсулированы в большой пакет данных для передачи. Это залипание/распаковка TCP.

Например: предположим, что операционная система получила три пакета следующим образом:

在这里插入图片描述

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

img

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

Распаковка решений, предоставленных Netty:

  • FixedLengthFrameDecoder: сообщение имеет фиксированную длину, длина сообщения фиксирована, и для его завершения недостаточно места.Отправитель и получатель следуют одному и тому же соглашению, так что даже если липкий пакет получен программой-получателем , можно различить сообщение фиксированной длины.
  • DelimiterBasedFrameDecoder: добавьте специальный разделитель в конце пакета. Например, добавьте возврат каретки и перевод строки в конце каждого пакета (например, протокол FTP) или укажите специальный символ в качестве разделителя пакета. Получатель использует специальный разделитель для разделения пакетов.
  • LengthFieldBasedFrameDecoder: разделите сообщение на заголовок сообщения и тело сообщения.Заголовок сообщения содержит поле, представляющее общую длину информации (или длину тела сообщения).

9.5 Bytebuf

Чтобы уменьшить количество частых операций ввода-вывода, вводится концепция буфера для организации большого количества мелкомасштабных операций ввода-вывода в стабильно небольшое количество крупномасштабных операций ввода-вывода. Java NIO инкапсулирует компонент ByteBuffer:

  • position: указатель чтения и записи, представляющий позицию текущей операции чтения или записи, это значение всегда меньше или равно пределу.
  • отметка: отметьте позицию восстановления позиции.
  • емкость: размер памяти, занимаемой всем байтовым буфером.
  • limit: при записи представляет самую большую позицию для записи, а при чтении — самую большую позицию для чтения.
    • Вызов очистить перед записью: дайте текущее значение емкости для ограничения
    • Вызовите flip перед операцией чтения: укажите текущее значение позиции для ограничения

ByteBuffer имеет следующие недостатки

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

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

9.6 Объединение в Netty

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

10 HTTPS

10.1 Процесс установки SSL/TLS

На первом этапе клиент сообщает номер версии протокола, случайное число, сгенерированное клиентом (Client random), и метод шифрования, поддерживаемый клиентом.

На втором этапе сервер подтверждает метод шифрования, используемый обеими сторонами, и предоставляет цифровой сертификат и случайное число (Server random), сгенерированное сервером.

На третьем этапе клиент подтверждает, что цифровой сертификат действителен, затем генерирует новое случайное число (Premaster secret) и использует открытый ключ в цифровом сертификате для шифрования случайного числа и отправки его на сервер.

На четвертом этапе сервер использует свой собственный закрытый ключ для получения случайного числа (т. е. секрета Premaster), отправленного клиентом.

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

10.2 Роль открытого ключа сервера и закрытого ключа

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

10.3 Зашифрован ли процесс рукопожатия?

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

10.4 Оптимизация https-соединений

1.OCSP Stapling

Браузер может проверить сертификат сервера двумя способами: CRL, OSCP.

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

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

Сшивание OCSP: сервер периодически отправляет запросы OCSP в ЦС. Когда клиент и сервер квитируют с помощью SSL (второй шаг), сервер отправляет результат запроса OCSP в браузер через сообщение о статусе сертификата, чтобы браузер мог перейти Сам ответ OCSP имеет подпись и не может быть подделан, поэтому сшивание OCSP повышает эффективность, не влияя на безопасность.

2.Мультиплексирование клиентских портов

Вообще говоря, после освобождения порта клиент будет ждать 2MSL, прежде чем его можно будет использовать снова.SO_REUSEADDR позволяет снова использовать порт сразу после его освобождения.

3.Мультиплексирование соединений с помощью SESSION

Этап рукопожатия используется для установления SSL-соединения. Если по какой-то причине разговор прерывается, требуется новое рукопожатие.

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

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

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

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

11 микросервисов

  1. Шлюз микросервисов
  2. Служба управления
  3. Надежность интерфейса

12 Алгоритм программирования

  1. Старшая косая строка без повторяющихся символов
  2. диаметр бинарного дерева
  3. Максимальная ширина бинарного дерева
  4. Найти минимальное значение в повернутом отсортированном массиве
  5. вращающийся связанный список
  6. Механизм кэширования LRU
  7. Медиана потока данных
  8. поиск повернутого отсортированного массива

12.1 Нерекурсивный обход бинарных деревьев

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

12.1.1 Обход предварительного заказа

  • Извлеките текущий узел из стека и сохраните его в списке
  • Поместите правый узел текущего узла в стек, а левый узел в стек (сначала справа, затем слева, сначала слева, а затем справа при извлечении из стека)
public List<Integer> orderTraversal(TreeNode root) {
  List<Integer> list = new ArrayList<>();
  if(root == null) return list;

  Stack<TreeNode> stack = new Stack<>();
  stack.push(root);

  while(!stack.isEmpty()) {
    TreeNode cur = stack.pop();
    if(cur.right != null) stack.push(cur.right);
    if(cur.left != null) stack.push(cur.left);
    list.add(cur.val);
  }

  return list;
}

12.1.2 Обход постпорядка

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

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

list.add(0, корень); // [корень]

list.add(0, справа); // [справа, корень]

list.add(0, слева);// ​​[слева, справа, корень]

public List<Integer> postorderTraversal(TreeNode root) {
  // 省略代码,与前序遍历一致
  
  while(!stack.isEmpty()) {
    TreeNode cur = stack.pop();
    // 因为是按照 根-右-左 进行前序遍历,所以要将先把左节点入栈
    if(cur.left != null) stack.push(cur.left);
    if(cur.right != null) stack.push(cur.right);
    // list头部插入
    list.add(0, cur.val);
  }

  return list;
}

12.1.3 Непоследовательный обход

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

public List<Integer> inorderTraversal(TreeNode root) {
    Stack<TreeNode> stack = new Stack<>();
    List<Integer> list = new ArrayList<>();
    if(root == null) return list;
    
    TreeNode cur = root;
    while(!stack.isEmpty() || cur != null) {
        while(cur != null) {
          stack.push(cur);
          cur = cur.left;
        }

        cur = stack.pop();
        list.add(cur.val);
        cur = cur.right;
    }

    return list;
}

14 шаблонов проектирования

  1. Режим Singleton: несколько методов реализации, принцип реализации двойной проверки, реализация класса перечисления (почему нельзя отразить класс перечисления)
  2. Шаблоны шаблонного метода проектирования: приложения в инженерии
  3. Шаблоны проектирования статических и динамических прокси-серверов
  4. Шаблон декоратора
  5. режим адаптера
  6. шаблон инженерного метода
  7. Модель цепочки ответственности