缓存服务

缓存服务 (Cache) 可以为您提供高性能的缓存集群,目前支持 Redis standalone, Redis cluster 和 Memcached 缓存。本指南旨在介绍如何创建、使用及管理缓存服务(Cache)。

总览

在青云上,您可以很方便的创建和管理一个缓存集群。一个缓存集群包含多个缓存节点,Redis 支持一主多从、多主多从架构,Memcached 支持多个独立缓存节点。 另外,我们提供在线扩容、自动备份和监控告警等功能来帮助您更好的管理集群。集群将运行于私有网络内,结合青云提供的高性能硬盘,在保障高性能的同时兼顾您的数据安全。

注解

为了保障数据安全,缓存服务需要运行在受管的私有网络中。 所以在创建一个缓存服务之前,您至少需要拥有一个路由器和一个受管私有网络,受管私有网络需要和路由器连接,并开启 DHCP 服务(默认开启)。

Redis Standalone

Redis 是一个基于内存、键值对的开源存储系统,并且支持数据持久化。本例中,将介绍如何使用和管理 Redis standalone (一主多从)缓存服务, Redis cluster (多主多从)服务请见下一章节。目前 Redis standalone 支持版本 2.8.17 和 3.0.5。

创建

第一步:选择基本配置

在创建的对话框中,您需要指定缓存服务的类型为 Redis 及版本。 每个 Redis standalone 缓存服务都会包含 1 个主节点和 N 个从节点 (N 可以为 0 即没有从节点),其中 1 + N 等于您选择的缓存节点个数。 在这里,我们指定节点个数为 2,即这个 Redis 缓存服务将拥有一个主节点和一个从节点,选择缓存大小、配置组以及自动备份策略,然后点击提交。

注解

主节点是可读可写的,而从节点是只读的。并且 Redis standalone 不支持主从切换。

第二步:配置网络

在配置网络的过程中,我们首先需要选择缓存服务要加入的私有网络,然后我们可以为缓存服务中的每个缓存节点指定 IP,例如我们指定 主节点的 IP 为 192.168.100.10,从节点的 IP 为 192.168.100.11,您也可以选择”自动分配”,让系统自动指定 IP。

注解

如果之前指定的 IP 并不是您预期的,您也可以在缓存服务运行过程中随时更改 IP, 另外 3.0.5 版本暂不支持运行中更改 IP 功能。

第三步:创建成功

当缓存服务创建完成之后,我们可以查看缓存节点的运行状态。 如图所示,缓存节点的 IP 为我们指定的 IP 地址,同时为 “活跃” 状态,表示各缓存节点连接正常。

注解

在缓存服务运行过程中,您可以随时添加和删除缓存从节点,但是不能删除或添加主节点。

第四步:连接缓存

当缓存服务创建完成之后,我们可以进行连接测试。 如图所示,我们可以连接到主节点查询服务状态,并尝试写入数据。

注解

默认情况下,缓存服务将使用系统的默认配置,但您可以随时对配置项进行更改并应用到缓存服务中。

扩容

在缓存服务运行过程中,会出现服务能力不足或者容量不够的情况,您都可以通过扩容来解决。

1)增加缓存节点

Redis standalone 缓存服务支持一主多从的架构。当读的能力不足时,您可以通过增加缓存从节点来提升读性能。 如图所示,我们在原有 Redis 基础上新增两个节点,并在创建时为新节点指定 IP。

注解

如果服务能力过剩,您也可以删除多余的缓存从节点。

下图为扩容之后的节点列表。

2)增加缓存容量

当缓存容量不足时,您可以通过扩容操作来提升缓存容量。 如下图所示,我们可以将原有缓存服务的容量从 1 GB 提升到 2 GB。

注解

存储容量只能扩容,不支持减少存储容量。在线扩容期间,缓存服务会被重启。

备份

Redis standalone 缓存服务本身支持数据持久化,您还可以通过备份功能对缓存服务进行定期备份,从而对关键时间点的数据进行保护。 缓存服务支持自动备份、手动备份、基于备份创建新缓存等功能。 备份功能是块级别的 (block level),最大程度保证数据安全, 同时备份过程不会影响正在运行的缓存服务。

1)配置自动备份

缓存服务支持定期自动备份,目前为每天一次,您可以从一天中选择一个合适的时间段来进行自动备份。 一般会选择凌晨或者业务压力小的时候进行备份操作。

注解

如果之前设置的备份时间不符合预期,您可以随时变更,同时您也可以随时关闭自动备份功能。

  1. 手动备份

除了自动备份,您可以在需要的时候随时对缓存服务进行手动备份。

和青云其他资源的备份相同,每个缓存最多有两条备份链,每条备份链可以有多个备份节点,包含一个全量节点和多个增量节点。 更多关于备份功能的介绍可以参见 备份与恢复指南

  1. 通过备份创建新的缓存服务

您可以基于任意一个备份点创建新的缓存服务,这样新的缓存服务将拥有和备份点一样的数据。

监控

我们提供了强大的监控和告警功能,帮助用户更好的管理和维护运行中的 Redis 缓存服务。

1)监控服务

我们提供了多达十几项的监控数据,来帮助用户随时了解缓存服务的运行状态和各项指标。 每一项监控都提供了历史监控和实时监控,最短时间间隔可以达到 10s。 Redis 服务的监控数据是通过 Redis 的 Info 命令来进行采集的。 我们提供的监控项目为如下:

  1. 节点资源监控
  • 带宽监控: 监控缓存节点的网卡出/入流量。
  • 基础资源监控: 包括 CPU、内存、硬盘等监控
  1. 缓存服务监控
  • 内存监控: 缓存服务的实际内存使用率,对应 used_memory 字段。
  • Get操作: Get 相关操作的总数。
  • Set操作: Set 相关操作的总数。
  • Key类型操作数: Key类型操作数的总数。
  • String类型操作数: String类型操作数的总数。
  • List类型操作数: List类型操作数的总数。
  • String类型操作数: String类型操作数的总数。
  • Hash类型操作数: Hash类型操作数的总数。
  • Set类型操作数: Set类型操作数的总数。
  • Sorted Set类型操作数: Sorted Set类型操作数的总数。
  • 总连接数: 建立总连接数,对应 total_connections_received 字段。
  • 当前连接数: 活跃的连接数,对应 connected_clients 字段。
  • 查询命中数: 查询的命中个数,对应 keyspace_hits 字段。
  • 查询未命中数: 查询的未命中个数,对应 keyspace_misses 字段。
  • 查询命中率: 查询命中率,对应 keyspace_hits / ( keyspace_hits + keyspace_misses )。
  • 总Key个数: 缓存中总的 key 个数,所有 db 的 key 个数总和。
  • 已过期Key个数: 缓存中已过期 Key 个数,对应 expired_keys 字段。
  • 被拒绝Key个数: 缓存中被拒绝 Key 个数,对应 evicted_keys 字段。当缓存内存不足时,会根据用户配置的 maxmemory-policy 来选择性地删除一些 key 来保护内存不溢出。

下图显示了一些监控的图表:

2)告警服务

我们支持对每个缓存节点配置监控告警策略,当发生异常时,会触发用户设定的告警阈值,并发送短信和邮件通知给用户。 缓存目前支持的监控告警规则有”内存使用率”、”被拒绝的 key 个数”等:

更多关于告警服务的内容可以参见 监控告警

配置

我们通过缓存配置组来管理缓存服务的配置。缓存服务和缓存配置组是解耦的,您可以创建多个独立的缓存配置组,并应用到不同缓存服务。 缓存服务在运行过程中,也可以随时变更缓存配置组。

1)创建新的缓存配置组

默认情况下,我们会为每个用户创建一个缺省配置组。用户也可以创建新的配置组,如图所示:

注解

缺省配置组不可以被删除。

  1. 修改配置项

点击该新建的缓存配置组,我们可以对每项配置项进行修改,如图所示:

修改完后,我们需要进行 “保存”,并点击 “应用” 让新的配置生效。

注解

当配置发生变化时,将会重启对应的缓存服务。

  1. 常用配置项
  • port: 缓存服务端口,默认为 6379。
  • appendonly: 是否开启可持久化功能,yes 表示开启(默认),no 表示禁用。注意,当未启用可持久化时,缓存数据会因为缓存服务重启而丢失。
  • appendfsync: 可持久化方式,everysec 表示每秒主动将数据刷新到磁盘(默认),always 表示每次插入操作都会刷新到磁盘(强一致性, 但是性能会差),no 表示依赖操作系统来刷新磁盘。
  • maxmemory-policy: 指定当内存满时对 key 的删除策略,默认为 volatile-lru,从过期的数据集中挑选最近最少使用的数据淘汰。
  • requirepass: 指定 redis 的访问密码。设置该参数后,整个 redis 中每个节点的访问都需要该密码,该密码也作为节点之间同步的密码。当该参数为空时,表示不需要密码。
  • slowlog-log-slower-than: 慢日志阈值设置,-1为禁止,0为记录所有的命令,正数值为记录执行时间大于该值的操作。详情见 Redis 官方文档
  • slowlog-max-len: 记录慢日志长度。
  • latency-monitor-threshold: 延迟监控阈值设定,0为禁止监控。详情见 Redis 官方文档
  • disable-commands: 指定需要禁用的 redis 命令,需要禁用的多个命令之间用”,”号分隔。

其他更多的配置项解释请参见 Redis 官方文档

迁移

为了方便用户将已有的 Redis 数据迁移至青云的 Redis 中,或者从旧版本升级到新版本,我们提供了一个特殊的缓存配置项 “slaveof-host” 来实现这一目标。 首先假设用户已有的 Redis 服务为一台青云外部的主机,服务 IP 为 1.2.3.4,端口为默认端口 6379 (源 Redis 服务端口必须是 6379)。 新创建的缓存的节点位于某私有网络中,主机 IP 为 192.168.100.2,端口也为 6379。

注解

slaveof-host 方式只对 Redis standalone 有效,对 Redis cluster 无效

  1. 将新节点配置为已有节点的从节点

我们需要修改新节点对应的配置项 “slaveof-host”,填入已有节点的 IP。这样新节点可以作为已有节点的从节点,进行数据同步。

注解

为了让迁移之后的数据能在新节点上持久化,需要保证新节点启用了持久化的配置,即 “appendonly” 选项需要为 “yes”.

修改完后,我们需要进行 “保存”,并点击 “应用” 让新的配置生效。

  1. 确认同步状态
通过 Redis 命令来查看新节点的数据是否已经和已有节点数据同步,一种简单的方式是比较两者的键值个数是否相等。
  1. 恢复新节点配置

恢复新节点对应的配置项 “slaveof-host”,重新设置为空 “”,断开同步关系,让新节点重新成为缓存服务的主节点。

注解

修改完后,我们需要进行 “保存”,并点击 “应用” 让新的配置生效。

性能

我们可以通过 Redis 自带的性能测试工具 redis-benchmark 来进行性能测试。

我们的测试对象为 8GB 内存的 Redis 缓存服务,如下为性能型 Redis 测试结果:

# redis-benchmark -q -n 1000000
PING_INLINE: 89919.97 requests per second
PING_BULK: 83049.58 requests per second
SET: 82365.54 requests per second
GET: 85207.91 requests per second
INCR: 80211.76 requests per second
LPUSH: 86117.80 requests per second
LPOP: 86355.79 requests per second
SADD: 93414.30 requests per second
SPOP: 101040.72 requests per second
LPUSH (needed to benchmark LRANGE): 92165.90 requests per second
LRANGE_100 (first 100 elements): 41301.83 requests per second
LRANGE_300 (first 300 elements): 11453.05 requests per second
LRANGE_500 (first 450 elements): 7625.67 requests per second
LRANGE_600 (first 600 elements): 6178.48 requests per second
MSET (10 keys): 49193.23 requests per second

我们的测试对象为 8GB 内存的 Redis 缓存服务,如下为超高性能型 Redis 测试结果:

# redis-benchmark -q -n 1000000
PING_INLINE: 146348.59 requests per second
PING_BULK: 138350.86 requests per second
SET: 141743.45 requests per second
GET: 142918.39 requests per second
INCR: 146993.97 requests per second
LPUSH: 148367.95 requests per second
LPOP: 145201.11 requests per second
SADD: 124455.51 requests per second
SPOP: 112637.98 requests per second
LPUSH (needed to benchmark LRANGE): 107642.62 requests per second
LRANGE_100 (first 100 elements): 51392.74 requests per second
LRANGE_300 (first 300 elements): 18827.07 requests per second
LRANGE_500 (first 450 elements): 12450.97 requests per second
LRANGE_600 (first 600 elements): 9635.77 requests per second
MSET (10 keys): 73292.29 requests per second

其他

为了更好的管理 Redis 服务,我们默认禁用一些 Redis 的命令,禁用的命令列表如下:

  • BGREWRITEAOF
  • BGSAVE
  • DEBUG
  • CONFIG
  • SAVE
  • SHUTDOWN
  • SLAVEOF

Redis Cluster (集群)

青云 Redis 集群提供原生的开源 Redis 3.x,除了继续支持以前的一主多从外,还支持多主多从,每个主所在分片 (shard) 平均分摊 16384 个 slots, 增加或删除主节点系统会自动平衡 slots (因为需要迁移数据,时间会有点长)。并且集群支持 HA, 即当某个主节点异常,它的从节点会自动切换成主节点。

创建

在本例中,我们将介绍如何创建一个具有多主多从架构的 Redis 集群缓存服务。

第一步:选择基本配置

在创建的对话框中,您需要指定缓存服务的类型为 Redis3.0.5(集群)。 每个 Redis 集群服务都会包含至少 3 个节点组, 每个节点组包括 N 个从节点(replicate, 即每个节点组的从节点个数, 可以是 0 个)。 默认情况下,指定 3 个节点组, 每组 1 个从节点,即这个 Redis 集群缓存服务将创建 6 个节点,选择每个节点的缓存大小及配置组,然后点击提交。

注解

主节点是可读可写的,而从节点是只读的。

第二步:配置网络

在配置网络的过程中,我们首先需要选择缓存服务要加入的私有网络。 然后我们可以为缓存服务中的每个节点指定 IP,例如我们指定 主节点的 IP 为 192.168.100.10,192.168.100.11,192.168.100.12,从节点的 IP 为 192.168.100.13,192.168.100.14,192.168.100.15。 您也可以选择”自动分配”,让系统自动指定 IP。

第三步:创建成功

当缓存服务创建完成之后,我们可以查看缓存节点的运行状态。 如图所示,缓存节点的 IP 为我们指定的 IP 地址,同时为 “活跃” 状态,表示各缓存节点连接正常。

测试

当缓存服务创建完成之后,我们可以进行连接测试。

1)检查集群状态

在同一私网中创建一台 Linux 主机,您可能需要先装一些依赖包 (如Ubuntu下apt-get install tcl ruby 和 gem install redis), 然后请 下载 Redis 3.x, 解压后进入 Redis src目录,执行以下命令 (假设 Redis cluster 其中一个节点的 IP 为 192.168.100.13, 端口为 6379)。

./redis-trib.rb check 192.168.100.13:6379

然后您能看到如下的集群信息

Connecting to node 192.168.100.13:6379: OK
Connecting to node 192.168.100.11:6379: OK
Connecting to node 192.168.100.10:6379: OK
Connecting to node 192.168.100.14:6379: OK
Connecting to node 192.168.100.12:6379: OK
Connecting to node 192.168.100.15:6379: OK
>>> Performing Cluster Check (using node 192.168.100.13:6379)
S: f6092dbdb25b6d80416232e50ccd2022860086b0 192.168.100.13:6379
   slots: (0 slots) slave
   replicates b2d75900b6427f6fbf8ec1a61ee301a2c8f73a6d
M: d3377079e01391b9d16ea699c79453e15f5aa132 192.168.100.11:6379
   slots:0-5460 (5461 slots) master
   1 additional replica(s)
M: b2d75900b6427f6fbf8ec1a61ee301a2c8f73a6d 192.168.100.10:6379
   slots:5461-10922 (5462 slots) master
   1 additional replica(s)
S: 9774f5ff6477eaecb6794395ed726d0f06257c60 192.168.100.14:6379
   slots: (0 slots) slave
   replicates d3377079e01391b9d16ea699c79453e15f5aa132
M: 704514eb7fa135dd003533568ae9f7babda9464e 192.168.100.12:6379
   slots:10923-16383 (5461 slots) master
   1 additional replica(s)
S: 22b3f49a6b87403faeeb1219881e63096802eb6a 192.168.100.15:6379
   slots: (0 slots) slave
   replicates 704514eb7fa135dd003533568ae9f7babda9464e
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.

如果发现集群出现异常,比如出现 [ERR] Nodes don’t agree about configuration! 可以尝试用如下命令修复

./redis-trib.rb fix 192.168.100.13:6379

如果发现各分片的 slots 分配不平均,也可以用如下命令平衡一下 (从两个分片迁移 1000 个 slots 到第三个分片里)

./redis-trib.rb reshard --from d3377079e01391b9d16ea699c79453e15f5aa132,b2d75900b6427f6fbf8ec1a61ee301a2c8f73a6d
--to 704514eb7fa135dd003533568ae9f7babda9464e --slots 1000 --yes 192.168.100.13:6379

2)Java 客户端读写数据示例

首先 下载 Jedis 库和 Apache Commons Pool 依赖库。 把下载下来的 commons-pool2-2.0.jar 和 jedis-2.7.3.jar 放到同一目录下如 lib/, 创建 TestRedisCluster.java,内容如下。 然后编译、执行该 Java 程序(假设一个分片的主从节点分别是 192.168.100.10, 192.168.100.13, 端口均为 6379)。

javac -cp :./lib/* TestRedisCluster.java
java -cp :./lib/* TestRedisCluster 192.168.100.10, 192.168.100.13 6379
import java.util.Set;
import java.util.HashSet;
import redis.clients.jedis.JedisCluster;
import redis.clients.jedis.HostAndPort;

public class TestRedisCluster {
    public static void main(String[] args) {
        Set<HostAndPort> jedisClusterNodes = new HashSet<HostAndPort>();
        //Jedis Cluster will attempt to discover cluster nodes automatically
        jedisClusterNodes.add(new HostAndPort(args[0], Integer.valueOf(args[2])));
        jedisClusterNodes.add(new HostAndPort(args[1], Integer.valueOf(args[2])));
        JedisCluster jc = new JedisCluster(jedisClusterNodes);

        String str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
        int len = str.length();
        int loop = 0;
        while (loop <= 100) {
            loop += 1;
            for (int i = 1; i < len; i++) {
                int end = len - i;
                for (int j = 0; j < end; j++) {
                    for (int k = j+1; k < end; k++) {
                        String key = str.substring(j, j+1) +
                                     str.substring(k, k+i) + "_" +
                                     str.substring(i, i+1);
                        String value = key + "_value";
                        jc.set(key, value);
                        String v = jc.get(key);
                        if (!value.equals(v)) {
                            System.out.println("Not equal: key[" + key + "], value[" +
                                               value + "], v[" + v + "]");
                        }
                        System.out.println(key + "," + value);
                    }
                }
            }
        }

        jc.close();
    }
}

注解

这是示例代码,不承担任何责任。更多的 Redis 客户端请见 Redis 官方网站

3) Hash Tags Keys

Redis 集群采用 CRC16 算法对 key 值哈希到 16384 个 slots 中的一个,因此不同的 key 可能分散到不同的节点中,对于想固定一类 key 值到某一个节点,如按业务分类,可以采用 Hash Tags,下面是从 Redis 文档 摘录的解释。

In order to implement hash tags, the hash slot is computed in a different way. Basically if the key contains a “{...}” pattern only the substring between { and } is hashed in order to obtain the hash slot. However since it is possible that there are multiple occurrences of { or } the algorithm is well specified by the following rules:

  • If the key contains a { character
  • There is a } character on the right of {
  • There are one or more characters between the first occurrence of { and the first occurrence of } after the first occurrence of {.

Then instead of hashing the key, only what is between the first occurrence of { and the first occurrence of } on its right are hashed.

Examples:

  • The two keys {user1000}.following and {user1000}.followers will hash to the same hash slot since only the substring user1000 will be hashed in order to compute the hash slot.
  • For the key foo{}{bar} the whole key will be hashed as usually since the first occurrence of { is followed by } on the right without characters in the middle.
  • For the key foo{{bar}}zap the substring {bar will be hashed, because it is the substring between the first occurrence of { and the first occurrence of } on its right.
  • For the key foo{bar}{zap} the substring bar will be hashed, since the algorithm stops at the first valid or invalid (without bytes inside) match of { and }.
  • What follows from the algorithm is that if the key starts with {}, it is guaranteed to be hashes as a whole. This is useful when using binary data as key names.

在线伸缩

在缓存服务运行过程中,会出现服务能力不足或者容量不够的情况,可以通过扩容来解决,或者服务能力过剩时可以删除节点。在纵向扩容中, 服务需要重启,所以这个时候业务需要停止。在横向伸缩中,数据会发生迁移,但并不影响业务的正常运行。

1)增加集群分片 (shard)

Redis 集群服务每个主节点写的能力与容量都有上限,当写的能力不满足业务需求或达到容量上限时,您可以通过增加节点组即缓存分片来提升写性能以及容量。 每增加一个节点组时将创建一个主节点和其它主节点同样的从节点数。青云 Redis 集群服务会自动平衡各分片之间的 slots,即会发生 数据迁移,因此增加节点组的时间会有点长。如果事先知道需要增加的分片数建议一次性完成,这样比一次只加一个分片效率更高。 如图所示,我们在原有集群基础上新增一个节点组,并在创建时为新节点指定 IP。

下图为扩容之后的节点列表。

2)增加集群从节点

Redis 集群服务每个主节点可以支持多个从节点。当读的能力不足时,您可以通过增加缓存从节点来提升读性能。 如图所示,我们在原有集群基础上新增一个从节点,并在创建时为新节点指定 IP,这个新增节点数 (replicate) 是针对于每个主节点而言, 因此该示例中总共要创建 4 个从节点(每主一个)。

下图为扩容之后的节点列表。

3)删除集群分片 (shard)

如果写服务能力或容量过剩,也可以删除多余的节点组,即删除主节点和它的所有从节点,删除的过程中系统会自动迁移数据到其它节点中,因此时间会稍长一点。

4)删除集群从节点

如果读服务能力过剩,您也可以删除多余的从节点。删除的时候需要从每个主节点下选择同样数目的从节点,从而保证整个集群不会是一个“畸形”。

5)增加缓存容量

当缓存容量不足时,您可以通过纵向扩容来提升缓存容量,右键点击缓存,选择扩容。 如下图所示,我们可以将原有缓存服务的容量从 1 GB 提升到 2 GB。

注解

存储容量只能扩容,不支持减少存储容量。在线扩容期间,缓存服务会被重启。

迁移

迁移数据既包括 Redis standalone 之间也包括从 Redis Standalone 到 Redis Cluster。

1)从 Redis standalone 迁移数据到 Redis cluster

Redis 3.x 提供了一个从 Redis standalone (包括旧版本 2.8.17) 迁移数据到 Redis cluster 的工具 redis-trib.rb, 请 下载 Redis 3.x, 解压后进入 Redis src目录, 执行以下命令 (假设 Redis standalone 的主节点 IP 为 192.168.100.11,端口为 6379, Redis cluster 其中一个 节点的 IP 为 192.168.100.20, 端口为 6379。
./redis-trib.rb import --from 192.168.100.11:6379 192.168.100.20:6379

注解

在做迁移之前建议对原 Redis standalone 做备份,因为上述操作是对数据进行迁移而不是拷贝。

2)从 Redis 2.8.17 迁移数据到 Redis 3.0.5

青云 Redis 服务也支持从旧版本 Redis standalone 迁移数据到新版本 Redis standalone, 具体操作参见 迁移, 您也可以用slaveof-host的方式同步数据,详情请见 slaveof-host 迁移

升级

目前升级是通过迁移数据实现的,详细操作见上述 迁移部分

备份

Redis 集群由于是多节点分片且支持 HA,因此目前不支持备份功能,如果有需要用户需自行备份数据。

监控

Redis 集群的监控提供 Redis standalone 完全一样的监控信息,详情请见 监控

图形化操作

青云提供了集群的图形化展示,方便用户更直观的查看集群状态和进行各项操作。部分截图如下:

用户可以在图形中进行以下操作:

  • 查看节点的监控信息
  • 查看节点的基本信息
  • 绑定节点的监控告警策略,并查看监控告警历史
  • 添加、删除从节点
  • 添加、删除节点组

Memcached 缓存

Memcached 是一个开源、分布式的内存缓存系统。本例中,将介绍如何使用和管理 Memcached 缓存服务。

创建

在本例中,我们将介绍如何创建一个 Memcached 缓存服务。

第一步:选择基本配置

在创建的对话框中,您需要指定缓存服务的类型为 Memcached。 每个 Memcached 缓存服务都会包含 N 个独立的节点,N 最小为1。 在这里,我们指定节点个数为 2,即这个 Memcached 缓存服务将拥有两个用于存储和访问的节点,然后点击提交。

注解

Memcached 的所有节点是可读可写的。另外,由于 Memcached 不支持持久化,当 Memcached 节点重启时,位于内存的缓存空间会被重置。

第二步:配置网络

步骤同 创建 Redis 缓存服务 ,不再赘述。

第三步:创建成功

步骤同 创建 Redis 缓存服务 ,不再赘述。

第四步:连接缓存

当缓存服务创建完成之后,我们可以进行连接测试。 如图所示,我们可以同时连接到多节点进行查询和写入,Memcached 的客户端会根据 Hash 算法来自动计算数据的存放节点位置。

注解

默认情况下,缓存服务将使用系统的默认配置,但您可以随时对配置项进行更改并应用到缓存服务中。

扩容

在缓存服务运行过程中,会出现服务能力不足或者容量不够的情况,您都可以通过扩容来解决。

1)增加缓存节点

Memcached 缓存服务支持多个缓存节点。当容量或者性能不足时,您可以通过增加缓存节点来提升。 如图所示,我们在原有集群基础上新增两个节点,并在创建时为新节点指定 IP。

注解

如果服务能力过剩,您也可以删除多余的缓存节点。

注解

默认的 Memcached 客户端使用简单 Hash 来进行数据分片,当增加或删除节点时可能会造成大量的缓存失效。可以采用支持一致性 Hash 算法的 Memcached 客户端来避免这个问题,例如 hash_ring

2)增加缓存容量

当缓存容量不足时,您可以通过扩容操作来提升缓存容量。 如下图所示,我们可以将原有缓存服务的容量从 1 GB 提升到 2 GB。

注解

在线扩容期间,缓存服务会被重启,因为 Memcached 不支持持久化,当重启之后,内存中缓存的数据将因为被重置而失效。

监控

我们提供了强大的监控和告警功能,帮助用户更好的管理和维护运行中的 Memcached 缓存集群。

1)监控服务

我们提供了多达十几项的监控数据,来帮助用户随时了解缓存服务的运行状态和各项指标。 每一项监控都提供了历史监控和实时监控,最短时间间隔可以达到10s。 Memcached 服务的监控数据是通过 Memcached 的 stats 命令来进行采集的。 我们提供的监控项目为如下:

  1. 节点监控
  • 带宽监控: 监控缓存节点的网卡出/入流量。
  1. 缓存服务监控
  • 内存监控: 缓存服务的实际内存使用率,对应 bytes 字段。
  • Get操作: Get 相关操作的总数。
  • Set操作: Set 相关操作的总数。
  • Delete操作:Delete 相关操作的总数。
  • Incr操作: Incr 相关操作的总数。
  • Decr操作: Decr 相关操作的总数。
  • Touch操作: Touch 相关操作的总数。
  • Cas操作: Cas 相关操作的总数。
  • Flush操作: Flush 相关操作的总数。
  • 总连接数: 建立总连接数,对应 total_connections 字段。
  • 当前连接数: 活跃的连接数,对应 curr_connections 字段。
  • 查询命中数: 查询的命中个数,对应 get_hits 字段。
  • 查询未命中数: 查询的未命中个数,对应 get_misses 字段。
  • 查询命中率: 查询命中率,对应 get_hits / ( get_hits + get_misses )。
  • 总Key个数: 缓存中总的 Key 个数,对应 curr_item 字段。
  • 使用召回内存的Key个数: 缓存中使用召回内存的 Key 个数,对应 reclaimed 字段。
  • 被拒绝Key个数: 缓存中被拒绝 Key 个数,对应 evictions 字段。当缓存内存不足时,会根据 LRU 算法来删除一些 key。

下图显示了一些监控的图表:

2)告警服务

我们支持对每个缓存节点配置监控告警策略,当发生异常时,会触发用户设定的告警阈值,并发送短信和邮件通知给用户。 缓存目前支持的监控告警规则有”内存使用率”、”已过期 Key 个数”等:

更多关于告警服务的内容可以参见 监控告警

配置

我们通过缓存配置组来管理缓存服务的配置。缓存服务和缓存配置组是解耦的,您可以创建多个独立的缓存配置组,并应用到不同缓存服务。 缓存服务在运行过程中,也可以随时变更缓存配置组。

1)创建新的缓存配置组

默认情况下,我们会为每个用户创建一个缺省配置组。用户也可以创建新的配置组,如图所示:

注解

缺省配置组不可以被删除。

  1. 修改配置项

点击该新建的缓存配置组,我们可以对每项配置项进行修改,如图所示:

修改完后,我们需要进行 “保存”,并点击 “应用” 让新的配置生效。

注解

当配置发生变化时,将会重启对应的缓存服务。

  1. 常用配置项
  • port: 缓存服务端口,默认为 11211。
  • udp_port: 缓存服务的 UDP 端口,默认为 11211,0 为禁用 UDP 服务端口。
  • cas_disabled: 禁用 CAS (Check and Set), 0 为 启用,1 为禁用,默认为 0。
  • error_on_memory_exhausted: 内存不足时的行为,0 为删除 key,1 为返回错误,默认为 0。

其他更多的配置项解释请参见 Memcached 官方文档。