1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/Kould-kache

Клонировать/Скачать
Внести вклад в разработку кода
Синхронизировать код
Отмена
Подсказка: Поскольку Git не поддерживает пустые директории, создание директории приведёт к созданию пустого файла .keep.
Loading...
README.md

Что такое Kache

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

Kache подчёркивает разделение между бизнес-логикой и кэшированием, реализуя обходной путь кэширования с помощью динамического проксирования. Фреймворк имеет специальный кодировщик параметров, скрывающий детали кодирования ключей и значений, а также четыре основных аннотации CRUD и перечисление Status или соответствие имени метода для управления действиями Kache, ориентированными на абстракцию и автоматизацию обработки.

Реализация кэша Kache включает Guava Cache, Redis и Lua, что снижает потребление сетевого ввода-вывода. Кэширование разделено на индексированный кэш и метаданные кэша. При сохранении данных в кэш выполняется операция «Эхо», которая сохраняет только те данные, которые ещё не были удалены из кэша, уменьшая необходимость повторной сериализации. В сценариях с большими объёмами данных, сосредоточенными на горячих точках, можно достичь почти бессериализованного уровня кэширования.

Фреймворк Kache универсален и имеет абстрактную реализацию компонентов, позволяя заменять стандартные компоненты пользовательскими реализациями через конструктор. Поддерживаются такие бэкенды, как MongoDB, IndexDB и даже MySQL. Кроме того, предоставляются дополнительные стратегии интерфейса, позволяющие пользователям настраивать стратегии для распределённых и одноузловых сред.

Отличия от других фреймворков кэширования

GuavaCache — выдающийся фреймворк кэширования от Google, предлагающий рациональное толкование и реализацию различных определений и операций кэширования. Существуют и другие популярные фреймворки кэширования, такие как J2Cache, Memcache и Ehcache, которые прошли проверку практикой и являются отличными открытыми проектами.

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

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

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

При использовании в качестве кэша процессов, например, в Java, где данные хранятся в структурах данных, таких как HashMap, значения и ключи представлены в виде ссылок, и при разумных операциях не происходит дублирования объектов, занимающих пространство памяти. Однако это не относится к NoSQL базам данных, таким как Redis.

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

Цитата из статьи Tencent на Zhihu о кэшировании подчёркивает важность размера ключа в Redis: «Поскольку максимальный размер одного пакета передачи по сети составляет 1500 байт, рекомендуется, чтобы размер каждого ключа-значения не превышал 1 КБ для обеспечения эффективной производительности. Это позволяет избежать многократных сетевых взаимодействий».

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

Идея заключается в том, чтобы использовать ссылки, подобные тем, которые используются в процессах Java для объектов, и хранить отдельные данные в Redis, используя id в качестве ссылки. Эта структура отделяет конкретные данные от параметров, распределяя их по Redis.

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

  • При чтении данных с условиями:

    • Параметр кодируется кодировщиком для использования в качестве ключа индексированного кэша.
    • Если соответствующий ключ индексированного кэша отсутствует:
      • Анализируются количество элементов в наборе данных и первичный ключ.
      • Создаётся скрипт Echo для запроса Redis на наличие необходимых метаданных кэша.
      • Если все метаданные отсутствуют или присутствуют только частично:
        • Метаданные извлекаются из набора данных и сохраняются вместе с соответствующими данными в Redis.
      • Если все метаданные присутствуют:
        • Ключ индексированного кэша сохраняется напрямую, избегая повторной сериализации и сохранения данных в Redis. Это снижает затраты на обновление кэша при изменении данных.
  • Если ключ индексированного кэша присутствует:

    • Соответствующий ключ индексированного кэша извлекается с помощью кодировщика.
    • Скрипт Lua используется для пакетного извлечения соответствующих метаданных с использованием команды mget в Redis и их заполнения. Затем возвращается обработанный ключ индексированного кэша (полная сериализация данных).

Эта структура кэширования имеет следующие особенности:

  • Данные и отдельные элементы разделены.
  • Удаление данных становится менее затратным, поскольку при обновлении данных можно повторно использовать ранее сохранённые метаданные.
  • Метаданные используют id в качестве ключа, предоставляя прямые ключи для поиска конкретных данных.
  • Индексированный кэш содержит только контейнерный класс и состояние с набором идентификаторов метаданных.
  • Удалив индексированный кэш, метаданные остаются нетронутыми, устраняя избыточность данных.

Этот тип кэширования подходит для следующих сценариев:

  • Зависимость от кэша сильна, и данные часто изменяются.
  • Базовая инфраструктура Redis слабая, сервер имеет ограниченные настройки, и доступное пространство кэша ограничено.
  • Процессор приложения имеет низкую производительность, а ввод-вывод интенсивный.
  • Методы получения данных по id используются часто.
  • Узким местом является работа с базой данных.
  • Существует большое количество повторяющихся данных.
  • Отдельные данные имеют большой объём.
  • Объём данных большой.

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

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

Вот перевод этого текста на русский язык:

Использование | Use

Данный Kache предназначен для управления компонентами с использованием родных JDK для поддержки Kotlin или Scala и других языков JDK. Если вы используете Spring Framework, перейдите по ссылке: https://gitee.com/kroup/kache-spring.

Примеры использования Kache в исходном виде можно найти в test/java/com.kould.test/KacheTest.

1. Введение зависимостей Kache

2. Наследование сущности кэша от интерфейса KacheEntity и реализация метода getPrimaryKey

3. Проксирование Kache

4. Добавление аннотаций к слою Dao

Пример:

1. Введение зависимости в файл pom:

<dependency>
  <groupId>io.gitee.kould</groupId>
  <artifactId>Kache</artifactId>
  <version>1.8.9.INFORMAL_VERSION</version>
</dependency>

2. Наследование сущности кэша от интерфейса KacheEntity:

@Data
@EqualsAndHashCode(callSuper = true)
@TableName("kork_article")
public class Article extends BasePO implements KacheEntity {

    private static final long serialVersionUID = -4470366380115322213L;

    @DataFactory(minLen = 10)
    private String title;

    private String summary;

    @JsonAdapter(IdAdapter.class)
    private Long authorId;

    @JsonAdapter(IdAdapter.class)
    private Long bodyId;

    @JsonAdapter(IdAdapter.class)
    private Long categoryId;

    private Integer commentCounts;

    private Long viewCounts;

    private ArticleType weight;

    @Override
    public String getPrimaryKey() {
        return getId().toString();
    }
}

3. Проксирование Mapper с помощью Kache:

Kache kache = Kache.builder().build();

// Необходимо инициализировать и уничтожить Kache для загрузки скрипта и освобождения соединения
kache.init();
kache.destroy();

// Динамическое проксирование Mapper для получения нового Mapper с функциями кэширования
// Пример:
ArticleMapper proxy = kache.getProxy(articleMapper, Article.class);

4. Соответствующие аннотации слоя Dao:

  • Аннотации для методов сохранения: @DaoMethod
    • Type: тип метода:
      • value = Type.SELECT : метод поиска
      • value = Type.INSERT : метод вставки
      • value = Type.UPDATE : метод обновления
      • value = Type.DELETE : метод удаления
    • Status: статус параметров метода (по умолчанию Status.BY_Field):
      • status = Status.BY_FIELD : метод поиска без ID
      • status = Status.BY_ID : метод поиска по ID
    • Class<?>[] involve: действует только при Type.SELECT Status.BY_Field: используется для того, чтобы индекс данного метода поиска мог влиять на другие классы кэша
@Repository
public interface TagMapper extends BaseMapper<Tag> {

    @Select("select t.* from klog_article_tag at "
            + "right join klog_tag t on t.id = at.tag_id "
            + "where t.deleted = 0 AND at.deleted = 0 "
            + "group by t.id order by count(at.tag_id) desc limit #{limit}")
    @DaoMethod(value = Type.SELECT,status = Status.BY_FIELD)
    // Получение данных через условный поиск
    List<Tag> listHotTagsByArticleUse(@Param("limit") int limit);

    @DaoMethod(Type.INSERT)
    // Метод пакетной вставки (может привести к изменению данных)
    Integer insertBatch(Collection<T> entityList);
}

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

  1. Класс объекта страницы: Page.class
  2. Имя свойства коллекции сущностей: «records»
  3. Класс свойства коллекции сущностей: List.class

Комментарии ( 0 )

Вы можете оставить комментарий после Вход в систему

Введение

Максимизация повторного использования кеша, автоматизированный минималистичный облегчённый кеш-прокси для персистентности. Развернуть Свернуть
Apache-2.0
Отмена

Обновления (1)

все

Участники

все

Недавние действия

Загрузить больше
Больше нет результатов для загрузки
1
https://api.gitlife.ru/oschina-mirror/Kould-kache.git
git@api.gitlife.ru:oschina-mirror/Kould-kache.git
oschina-mirror
Kould-kache
Kould-kache
master