Основные производители используют EhCache, чем он лучше Redis?

Java задняя часть

предыстория истории

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

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

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

Введение в EhCache

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

EhCache является CacheProvider по умолчанию в Hibernate, и Spring Boot также поддерживает его.Абстракция кэша, предоставляемая в Spring, также поддерживает привязку к среде кэширования EhCache и поддерживает использование на основе аннотаций. Таким образом, EhCache — это широко используемый фреймворк кэширования на основе Java, который к тому же очень удобен в использовании.

EhCache предоставляет множество стратегий кэширования, в основном разделенных на уровни памяти и диска.Это среда кэширования для кэширования общего назначения, Java EE и облегченных контейнеров.

Возможности EhCache

Кратко опишите особенности этого фреймворка:

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

EhCache можно использовать отдельно, но обычно он используется в сочетании со сторонними библиотеками, такими как Mybatis и Shiro. Я использую EhCache в своем проекте с Широ.

Помимо преимуществ, у EhCache есть и недостатки. Например,Занимает много места на диске, это потому, что алгоритм DiskCache прост, он просто добавляет хранилище непосредственно к элементу. Это повышает эффективность, но в интенсивно используемых системах диск быстро заполняется.

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

ЭхКэш и Редис

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

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

Поэтому, если это монолитное приложение или предъявляются высокие требования к доступу к кешу, можно рассмотреть EhCache; если это крупномасштабная система с совместным использованием кеша, распределенным развертыванием и большим содержимым кеша, рекомендуется Redis..

Схема архитектуры EhCache

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

Ehcache-architecture

Раздел Cache Replication предоставляет механизм репликации кэша для распределенных сред. EhCache изначально был независимым компонентом инфраструктуры локального кэша. В более поздних разработках в сочетании с моделью массива служб Terracotta он может поддерживать кластеры распределенного кэша. В основном существуют методы распространения RMI, JGroups, JMS и Cache Server для межузловой связи.

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

Сетевые API обеспечивают внешнюю поддержку на основе RESTful API, JMS API, Cache Server и т. д.

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

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

Управление тройкой можно представить следующей схемой:

CacheManager

Политика истечения срока действия кэша

На диаграмме архитектуры вы также можете увидеть алгоритмы хранения памяти, такие как Memory Store LRU, Memory Store LFU и Memory Store FIFO. То есть, когда объем кэш-памяти близок к критическому значению, для очистки части данных будет использована описанная выше стратегия исключения.

EhCache предлагает три алгоритма исключения:

  • FIFO: «первым пришел, первым вышел», «первым пришел, первым ушел». Судя по времени хранения, данные, наиболее далекие от настоящего, будут удалены в первую очередь.
  • LRU: наименее недавно использованный, наименее недавно использовавшийся. Судя по последнему использованному времени, самые дальние данные на данный момент будут исключены первыми.
  • LFU: Наименее часто используемый, Наименее часто используемый. В течение определенного периода времени данные, которые использовались меньше всего раз, будут удалены первыми.

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

Боевой анализ EhCache

Ознакомившись с приведенными выше базовыми знаниями, давайте поэкспериментируем с тем, как используется EhCache. Среди них использование EhCache2.x и EhCache3.x сильно различается.

Здесь используется относительно новая версия 3.9.6, и разные версии имеют разное использование API.

Использование EhCache на основе API

EhCache обеспечивает создание CacheManger и Cache на основе API и xml. Давайте сначала посмотрим на форму на основе API:

Внесите зависимость EhCache в файл pom:

<dependency>
      <groupId>org.ehcache</groupId>
      <artifactId>ehcache</artifactId>
      <version>3.9.6</version>
</dependency> 

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

public class EhCacheTest {
​
  @Test
  public void test() {
    // 1、先创建一个CacheManagerBuilder;
    // 2、使用CacheManagerBuilder创建一个预配置(pre-configured)缓存:第一个参数为别名,第二个参数用来配置Cache;
    // 3、build方法构建并初始化;build中true参数表示进行初始化。
    CacheManager cacheManager = CacheManagerBuilder.newCacheManagerBuilder()
        .withCache("preConfigured",
            CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class,
                ResourcePoolsBuilder.heap(100)).build())
        .build(true);
​
    // 取回在设定的pre-configured,对于key和value值类型,要求是类型安全的,否则将抛出ClassCastException异常。
    Cache<Long, String> preConfigured = cacheManager.getCache("preConfigured", Long.class, String.class);
​
    System.out.println("从缓存中获取key为preConfigured:" + preConfigured);
​
    // 根据需求,通过CacheManager创建出新的Cache。实例化和完整实例化的Cache将通过CacheManager.getCache API返回。
    Cache<Long, String> myCache = cacheManager.createCache("myCache",
        CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class,
            ResourcePoolsBuilder.heap(100)).build());
    // 使用put方法存储数据
    myCache.put(1L, "da one!");
    // 使用get方法获取数据
    String value = myCache.get(1L);
    System.out.println("从缓存中获取key为1L:" + value);
    // close方法将释放CacheManager所管理的缓存资源
    cacheManager.close();
  }
}

В приведенном выше коде показано, как создать CacheManager и Cache на основе API, а также установить и получить Cache.

Использование EhCache на основе XML

Пакет зависимостей Jar остается без изменений, а файл конфигурации ehcache.xml создается в каталоге src/main/resources/.

<config
        xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
        xmlns='http://www.ehcache.org/v3'
        xsi:schemaLocation="http://www.ehcache.org/v3 http://www.ehcache.org/schema/ehcache-core.xsd">
​
    <cache alias="foo">
        <key-type>java.lang.String</key-type>
        <value-type>java.lang.String</value-type>
        <resources>
            <heap unit="entries">20</heap>
            <offheap unit="MB">10</offheap>
        </resources>
    </cache>
​
    <cache-template name="myDefaults">
        <key-type>java.lang.Long</key-type>
        <value-type>java.lang.String</value-type>
        <heap unit="entries">200</heap>
    </cache-template>
​
    <cache alias="bar" uses-template="myDefaults">
        <key-type>java.lang.Number</key-type>
    </cache>
​
    <cache alias="simpleCache" uses-template="myDefaults" />
​
</config>

Версия 3.x отличается от версии 2.x, что очень заметно в файле конфигурации xml. В 2.x корневым узлом является элемент ehcache, а в 3.x корневым узлом является config.

В приведенном выше xml есть три части:

  • Общий кеш cache-foo: кеш с псевдонимом foo и типом значения кеша "ключ-значение" — String. Если не указано, по умолчанию используется тип объекта.
  • шаблон кеша cache-template: реализует абстракцию конфигурации, чтобы ее можно было расширить в будущем;
  • Кэш-бар на основе шаблона кеша: используется шаблон шаблона кеша myDefaults, тип key-type перезаписывается, тип key-type myDefaults — тип Long, который после перезаписи становится типом Number;

Другие атрибуты и элементы в кеше:

  • имя это имя;
  • псевдоним - это псевдоним;
  • key-type — тип ключа;
  • value-type — тип значения;
  • куча указывает формат объекта, который может быть создан в куче, где unit="entries" означает, что следующие 20 объектов являются объектами;
  • Offheap означает, что может быть выделено до 10 Мб памяти в куче, прежде чем начинать вытеснять элементы кэша с истекшим сроком действия;
  • uses-template указывает имя используемого шаблона;

Конечно, каталог кеша также можно настроить с помощью элемента persistence. Использование других свойств можно исследовать медленно.

Использование EhCache на основе Spring Boot

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

Введите соответствующий стартер в Spring Boot:

<!-- ehcache依赖-->
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
  <groupId>org.ehcache</groupId>
  <artifactId>ehcache</artifactId>
  <version>3.9.6</version>
</dependency>

Добавьте следующую конфигурацию в конфигурацию в application.properties:

spring.cache.ehcache.config=ehcache.xml

Добавьте аннотацию @EnableCaching в класс запуска Spring Boot:

@EnableCaching
@SpringBootApplication
@MapperScan("com.secbro.mapper")
public class SpringBootMainApplication {
  public static void main(String[] args) {
    SpringApplication.run(SpringBootMainApplication.class, args);
  }
}

Создайте пользовательский кешированный класс сущностей Person:

@Data
public class Person {
​
  public Person(int id,String name){
    this.id = id;
    this.name = name;
  }
​
  private int id;
​
  private String name;
}

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

public interface PersonService {
  Person getById(int id);
}
​
@Slf4j
@Service("personService")
public class PersonServiceImpl implements PersonService {
​
  @Cacheable(value = "personCache", key = "#id")
  @Override
  public Person getById(int id) {
    log.info("查询id={}的用户", id);
    if (id == 1) {
      return new Person(1, "Tom");
    } else if (id == 2) {
      return new Person(2, "Jim");
    }
    return new Person(3, "Other");
  }
}

Spring предоставляет аннотацию @Cacheable для указания имени кеша как personCache и ключа как id. Журнал печатается внутри метода, и если он вызывается в методе, он будет напечатан.

Напишите класс модульного теста:

@Slf4j
@SpringBootTest
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
class PersonServiceTest {
​
  @Resource
  private PersonService personService;
​
  @org.junit.jupiter.api.Order(1)
  @Test
  void testCache() throws InterruptedException {
    log.info("第1次查询id=1的数据");
    personService.getById(1);
    log.info("第2次查询id=1的数据");
    personService.getById(1);
    Thread.sleep(3000);
  }
}

Соответствующий метод вызывается дважды, и журнал печати выглядит следующим образом:

c.s.s.PersonServiceTest                  : 第1次查询id=1的数据
c.s.s.i.PersonServiceImpl                : 查询id=1的用户
c.s.s.PersonServiceTest                  : 第2次查询id=1的数据

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

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

резюме

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

Профиль блоггера: автор технической книги SpringBoot Technology Insider, который любит изучать технологии и писать технические статьи.

Публичный аккаунт: "Новые горизонты программ", публичный аккаунт блогера, прошу обратить внимание~

Технический обмен: пожалуйста, свяжитесь с блогером WeChat ID: zhuan2quan