Вы научитесь двум методикам хранения и получения данных. В приложении следует использовать тот способ, который помогает упростить архитектуру в соответствии с шаблонами доступа к данным.
Но сначала убедитесь, что вы можете подключиться к Redis.
Время, необходимое для прохождения модуля: 60 минут
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 (Источник) можно начать вводить имя группы безопасности, а затем выбрать ее идентификатор из списка. Дополнительные сведения о группах безопасности можно найти в документации или справочнике по правилам групп безопасности.
В репозитории есть код 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 и лучшую стратегию вытеснения. Проверьте производительность приложения с пустым и с полным кэшем.