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

Но сначала убедитесь, что вы можете подключиться к Redis.

Время, необходимое для прохождения модуля: 60 минут



Шаг 4.1

(Нажмите, чтобы увеличить изображение.)

Шаг 4.1
Шаг 4.2

(Нажмите, чтобы увеличить изображение.)

Шаг 4.2

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

Шаг 4.3

(Нажмите, чтобы увеличить изображение.)

Шаг 4.3

syntax: shell

$ python

Если выполнение этих команд приводит к зависанию, см. примечание после примера. 

syntax: python

syntax: python
>>> import redis
>>> client = redis.Redis.from_url('redis://endpoint:6379')
>>> client.ping()

True

Примечание: зависание означает, что выполнение блокируется параметрами группы безопасности. Убедитесь, что у инстанса EC2 есть доступ к группе безопасности, назначенной инстансу ElastiCache. Допустим, ваш инстанс EC2 был назначен стандартной группе безопасности. Теперь вы можете изменить группу безопасности инстанса Amazon ElastiCache и добавить пользовательское правило TCP, которое разрешает подключения через порт 6379 от любого инстанса из стандартной группы безопасности:

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

Шаг 4.5

(Нажмите, чтобы увеличить изображение.)

Шаг 4.5

В репозитории есть код Python, который можно запустить в инстансе EC2. Но сначала необходимо настроить некоторые переменные среды:

syntax: shell

$ export REDIS_URL=redis://your_redis_endpoint:6379/
$ export DB_HOST=your_mysql_endpoint
$ export DB_USER=admin
$ export DB_PASS=your_admin_password
$ export DB_NAME=tutorial

Обратите внимание, что для параметров mysql_endpoint, redis_endpoint и password используются значения, сохраненные на предыдущих этапах.


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

syntax: python

def fetch(sql):

  result = cache.get(sql)
  if result:
    return deserialize(result)
  else:
    result = db.query(sql)
    cache.setex(sql, ttl, serialize(result))
    return result

Сначала оператор SQL используется в качестве ключа в Redis, а кэш проверяется на наличие значения. Если значение отсутствует, оператор SQL используется для отправки запроса к базе данных. Результат запроса к базе данных сохраняется в Redis. Для переменной ttl должно быть задано уместное значение, соответствующее характеру приложения. По истечении времени, заданного переменной ttl, Redis вытесняет ключ и освобождает соответствующую память. Этот код доступен в репозитории учебного пособия, и его можно запускать без изменений. Однако вы можете добавлять в него операторы print, если вам нужно увидеть значение переменной в определенный момент времени.

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

Пример использования функции fetch:

syntax: python

print(fetch("SELECT * FROM planet"))

Результат:

syntax: python

[{'id': 10, 'name': 'Mercury'},
 {'id': 11, 'name': 'Venus'},
 {'id': 12, 'name': 'Earth'},
 {'id': 13, 'name': 'Mars'},
 {'id': 14, 'name': 'Jupiter'},
 {'id': 15, 'name': 'Saturn'},
 {'id': 16, 'name': 'Uranus'},
 {'id': 17, 'name': 'Neptune'}]

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


Во втором примере мы сопоставим запись базы данных с хэшем Redis:

syntax: python

def planet(id):

  key = "planet:" + str(id)
  result = cache.hgetall(key)

  if result:
      return result

  else:
      sql = "SELECT `id`, `name` FROM `planet` WHERE `id`=%s"
      result = db_record(sql, (id,))

      if result:
          cache.hmset(key, result)
          cache.expire(key, ttl)
      return result

В Redis используется плоское пространство ключей, но действует соглашение об имитации структуры с помощью строк, разделенных двоеточиями. В этом примере ключом записи с идентификатором 1 будет "planet:1". Этот фрагмент кода неплохо иллюстрирует распространенный шаблон, но возможно большее абстрагирование: один модуль может отвечать за генерирование ключей, другой – за составление строки SQL и т. д. Кроме того, наверняка существуют инструменты для выполнения этой задачи на используемом вами языке программирования.
В этом примере показано, как получить записи из кэша или базы данных. Аналогично, здесь можно реализовать функцию для сохранения объекта в базу данных.


В двух примерах мы использовали время жизни, или ttl, по истечении которого Redis вытесняет ключ. Хотя в большинстве случаев этого достаточно, вам может потребоваться как можно скорее удалять устаревшие данные из кэша. В таком случае обязательно ознакомьтесь с другими вариантами, например стратегией кэширования со сквозной записью. Ссылки на дополнительные сведения представлены в конце этого учебного пособия. На всякий случай стоит упомянуть, что хотя в примерах используется команда EXPIRE, в Redis также доступна команда EXPIREAT, с помощью которой можно задать точные дату и время вытеснения ключа. Она принимает в качестве параметра абсолютную метку времени Unix (т. е. количество секунд, прошедших с 1 января 1970 г.).


Когда объем данных превышает заданное значение maxmemory, Redis может реагировать по-разному в зависимости от выбранной политики вытеснения. По умолчанию ElastiCache for Redis настраивается на удаление из памяти самых старых ключей с заданным значением ttl. Параметр политики вытеснения называется maxmemory-policy, а в ElastiCache по умолчанию задано значение volatile-lru. Другой интересный вариант для этого сценария использования – политика volatile-ttl, которая указывает Redis, что необходимо освободить память, удалив ключи с самым низким значением ttl.


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