colinmollenhour/cache-backend-redis

支持标签的完整功能的Redis作为后端的Zend_Cache。

安装次数: 17,889,417

依赖关系: 10

建议者: 1

安全性: 0

星标: 389

关注者: 46

分支: 142

公开问题: 22

类型:magento-module

1.17.1 2023-12-21 21:56 UTC

README

这个 Zend_Cache 后端允许您使用Redis服务器作为中央缓存存储。完全支持标签,无需使用 TwoLevels 缓存,因此此后端非常适合在单台机器或集群中使用。与所有版本的Magento!任何Zend Framework项目兼容!

特性

  • 使用phpredis PECL扩展以获得最佳性能(需要master分支或2011年8月19日之后的新版本)。
  • 如果phpredis不可用,则回退到独立的PHP,使用Credis库。
  • 完全支持标签,使用Redis的"set"和"hash"数据类型实现,以有效地管理标签。
  • 键过期由Redis自动处理。
  • 支持Unix套接字连接,在单台机器上提供更好的性能。
  • 支持可配置的压缩以节省内存。可以选择gzip、lzf和snappy,并且可以在不刷新缓存的情况下更改配置。
  • 使用事务来防止保存、清理或删除操作之间的竞态条件,避免产生意外的结果。
  • 支持可配置的"自动过期寿命",如果设置,将用作键未过期时的TTL。与"自动加载时刷新过期"结合使用,为Magento的Enterprise_PageCache模块提供更合理的缓存管理策略。
  • 单元测试!

需求

由于此后端使用Credis,没有额外的需求,但为了提高性能,您可以安装phpredis,这是一个编译的扩展。

  • 为了支持2.4版本,您必须使用"master"分支或2011年8月19日之后的新版本。
  • phpredis是可选的,但它的速度比独立模式快得多
  • 目前phpredis不支持设置读取超时(请参阅拉取请求#260)。如果您收到读取错误("连接读取错误"),这可能就是原因。

安装

使用Composer将包添加为项目的依赖项。

composer require colinmollenhour/cache-backend-redis

modman

这不是推荐的方法,但您可以通过modman进行安装

modman clone https://github.com/colinmollenhour/Cm_Cache_Backend_Redis

配置

以下示例假设您正在使用Magento,但配置可以以与示例中相同的键名传递给构造函数作为PHP数组。

编辑app/etc/local.xml进行配置

    <!-- This is a child node of config/global -->
    <cache>
      <backend>Cm_Cache_Backend_Redis</backend>
      <backend_options>
        <server>127.0.0.1</server> <!-- or absolute path to unix socket -->
        <port>6379</port>
        <persistent></persistent> <!-- Specify unique string to enable persistent connections. E.g.: sess-db0; bugs with phpredis and php-fpm are known: https://github.com/nicolasff/phpredis/issues/70 -->
        <database>0</database> <!-- Redis database number; protection against accidental data loss is improved by not sharing databases -->
        <password></password> <!-- Specify if your Redis server requires authentication -->
        <force_standalone>0</force_standalone>  <!-- 0 for phpredis, 1 for standalone PHP -->
        <connect_retries>1</connect_retries>    <!-- Reduces errors due to random connection failures; a value of 1 will not retry after the first failure -->
        <read_timeout>10</read_timeout>         <!-- Set read timeout duration; phpredis does not currently support setting read timeouts -->
        <automatic_cleaning_factor>0</automatic_cleaning_factor> <!-- Disabled by default -->
        <compress_data>1</compress_data>  <!-- 0-9 for compression level, recommended: 0 or 1 -->
        <compress_tags>1</compress_tags>  <!-- 0-9 for compression level, recommended: 0 or 1 -->
        <compress_threshold>20480</compress_threshold>  <!-- Strings below this size will not be compressed -->
        <compression_lib>gzip</compression_lib> <!-- Supports gzip, lzf, lz4 (as l4z), snappy and zstd -->
        <use_lua>0</use_lua> <!-- Set to 1 if Lua scripts should be used for some operations (recommended) -->
        <load_from_slave>tcp://redis-slave:6379</load_from_slave> <!-- Perform reads from a different server --> 
      </backend_options>
    </cache>

    <!-- This is a child node of config/global for Magento Enterprise FPC -->
    <full_page_cache>
      <backend>Cm_Cache_Backend_Redis</backend>
      <backend_options>
        <server>127.0.0.1</server> <!-- or absolute path to unix socket -->
        <port>6379</port>
        <persistent></persistent> <!-- Specify unique string to enable persistent connections. E.g.: sess-db0; bugs with phpredis and php-fpm are known: https://github.com/nicolasff/phpredis/issues/70 -->
        <database>1</database> <!-- Redis database number; protection against accidental data loss is improved by not sharing databases -->
        <password></password> <!-- Specify if your Redis server requires authentication -->
        <force_standalone>0</force_standalone>  <!-- 0 for phpredis, 1 for standalone PHP -->
        <connect_retries>1</connect_retries>    <!-- Reduces errors due to random connection failures -->
        <lifetimelimit>57600</lifetimelimit>    <!-- 16 hours of lifetime for cache record -->
        <compress_data>0</compress_data>        <!-- DISABLE compression for EE FPC since it already uses compression -->
        <auto_expire_lifetime></auto_expire_lifetime> <!-- Force an expiry (Enterprise_PageCache will not set one) -->
        <auto_expire_refresh_on_load></auto_expire_refresh_on_load> <!-- Refresh keys when loaded (Keeps cache primed frequently requested resources) -->
      </backend_options>
    </full_page_cache>

高可用性和负载均衡支持

Redis Sentinel

您可以使用Redis Sentinel实现高可用性和负载均衡。要启用Redis Sentinel的使用,指定的server应该是一个逗号分隔的Sentinel服务器列表,并且应该指定sentinel_master选项来表示Sentinel主集的名称(例如,'mymaster')。如果使用sentinel_master,还可以指定load_from_slaves,在这种情况下,将随机选择一个从属服务器进行读取,以在多个Redis实例之间进行负载均衡。使用值'1'表示只从从属服务器中加载数据,而使用'2'则包括主服务器在随机读取从属服务器选择中。

示例配置

    <!-- This is a child node of config/global -->
    <cache>
      <backend>Cm_Cache_Backend_Redis</backend>
      <backend_options>
        <server>tcp://10.0.0.1:26379,tcp://10.0.0.2:26379,tcp://10.0.0.3:26379</server>
        <timeout>0.5</timeout>
        <sentinel_master>mymaster</sentinel_master>
        <sentinel_master_verify>1</sentinel_master_verify>
        <load_from_slaves>1</load_from_slaves>
      </backend_options>
    </cache>

负载均衡器或服务发现

您还可以通过指定主服务器和从服务器(如果有)的单独连接地址来使用其他方法实现高可用性。为此,已添加了load_from_slave选项,此选项与上面的示例不同,它不连接到Sentinel服务器,尽管您可能仍然会从Sentinel设置中受益,因为这样可以更容易地进行复制和故障转移。

示例包括使用具有主服务器和从服务器不同端口的TCP负载均衡器(例如,HAProxy),或使用基于DNS的系统,该系统使用服务发现健康检查通过不同的DNS名称公开主服务器和从服务器。

示例配置

    <!-- This is a child node of config/global -->
    <cache>
      <backend>Cm_Cache_Backend_Redis</backend>
      <backend_options>
        <server>tcp://redis-master:6379</server>
        <load_from_slave>tcp://redis-slaves:6379</load_from_slave>
        <master_write_only>0</master_write_only>  <!-- Use 1 to prevent reads from master -->
        <timeout>0.5</timeout>
      </backend_options>
    </cache>

静态配置

您还可以通过将数组传递给load_from_slave或使用逗号分隔的多个地址的字符串来静态指定主服务器和从服务器。

    <!-- This is a child node of config/global -->
    <cache>
      <backend>Cm_Cache_Backend_Redis</backend>
      <backend_options>
        <server>tcp://redis-master:6379</server>
        <load_from_slave>tcp://redis-slave1:6379,tcp://redis-slave2:6379</load_from_slave>
        <master_write_only>0</master_write_only>  <!-- Use 1 to prevent reads from master -->
        <timeout>0.5</timeout>
      </backend_options>
    </cache>

ElastiCache

以下示例配置允许您使用ElastiCache Redis(禁用集群模式),其中写入发送到主节点,读取发送到副本。这可以让您在不同的节点之间分配读取流量。

查找主节点和读取副本端点的说明在此

    <!-- This is a child node of config/global/cache -->
    <backend_options>
      <server>primary-endpoint.0001.euw1.cache.amazonaws.com</server>
      <port>6379</port>
      <database>0</database>                    <!-- Make sure database is 0 -->
      <master_write_only>1</master_write_only>
      <load_from_slave>
        <node-001>
          <server>replica-endpoint-1.jwbaun.0001.euw1.cache.amazonaws.com</server>
          <port>6379</port>
        </node-001>
        <node-002>
          <server>replica-endpoint-2.jwbaun.0001.euw1.cache.amazonaws.com</server>
          <port>6379</port>
        </node-002>
      </load_from_slave>
    </backend_options>

弃用通知

以前,ElastiCache配置说明建议设置一个<cluster>节点,但这种功能有缺陷,现已不再支持。配置仍然被解析和加载以保持向后兼容性,但选择随机从属服务器进行读取,而不是使用键的md5散列。

调整

  • 建议的“maxmemory-policy”是“volatile-lru”。所有标签元数据都是非易失性的,因此除非非易失性键绝对必要,否则建议使用键过期,这样标签数据就不会被清除。因此,请确保“maxmemory”足够高,可以容纳所有标签数据和非易失性数据,并且留有足够的空间用于易失性键数据。
  • 自动清理是可选的,不建议使用,因为它很慢,并且使用大量的内存。
  • 如果整个缓存很少清除且未启用自动清理,则建议进行定期的(例如每天一次)垃圾收集。最佳解决方案是运行一个cron作业进行垃圾收集。(请参阅下面的“垃圾收集示例脚本”。)
  • 压缩将产生额外的CPU开销,但可能值得为了节省内存和减少流量。对于高延迟网络,它甚至可能提高性能。使用Magento Cache Benchmark来分析您的实际压缩性能并测试系统使用不同压缩库的性能。
    • gzip — 压缩率最高但最慢。您可能不会希望使用级别1以上的压缩。
    • lzf — 压缩最快,解压缩也快。安装:sudo pecl install lzf
    • snappy — 解压缩最快,压缩也快。下载并安装:snappyphp-snappy
  • 使用我修改过的 munin 插件 监控你的 Redis 缓存统计信息。
  • 启用持久连接。确保如果有多重配置连接,持久字符串对于每个配置都是唯一的,以避免“select”命令引起冲突。
  • 如果你的服务器出现“BUSY”错误,请增加 lua-time-limit 设置。这个设置也可以导致 Redis Sentinel 在你更希望让 Lua 脚本完成并让客户端稍等一下的情况下调用故障转移。
  • 使用 stats.php 脚本检查你的缓存,以查找过大的或浪费的缓存标签。

垃圾回收脚本示例(用于 Magento)

<?php PHP_SAPI == 'cli' or die('<h1>:P</h1>');
ini_set('memory_limit','1024M');
set_time_limit(0);
error_reporting(E_ALL | E_STRICT);
require_once 'app/Mage.php';
Mage::app()->getCache()->getBackend()->clean('old');
// uncomment this for Magento Enterprise Edition
// Enterprise_PageCache_Model_Cache::getCacheInstance()->getFrontend()->getBackend()->clean('old');

开发中

请随时发送 Pull Requests 以将您的改进回馈给社区!

如果您已安装 Docker,只需使用简单的别名即可在本地运行单元测试。

alias cm-cache-backend-redis='docker run --rm -it -e REDIS_SERVER=host.docker.internal -u $(id -u):$(id -g) -v ${COMPOSER_HOME:-$HOME/.composer}:/tmp -v $(pwd):/app --workdir /app cm-cache-backend-redis'
docker build . -t cm-cache-backend-redis

然后启动 Redis 服务器,安装 Composer 依赖并按如下方式运行测试

  docker run --rm -d -p 6379 --name cm-cache-backend-redis redis --maxmemory 20m --maxmemory-policy noeviction
  cm-cache-backend-redis composer install
  cm-cache-backend-redis composer run-script test
  cm-cache-backend-redis composer run-script php-cs-fixer -- --dry-run
@copyright  Copyright (c) 2022 Colin Mollenhour
This project is licensed under the "New BSD" license (see source).