获得直连地址后,您可以绕过代理,用直连模式访问云数据库Redis集群实例,缩短Redis服务的响应时间。本章节以使用Jedis和PhpRedis客户端为例,介绍了直连访问的注意事项和方法。

前提条件

  • 开通直连访问
  • 将客户端地址加入Redis白名单
  • 使用JedisPhpRedis等支持Redis Cluster的客户端。
    说明
    • 使用不支持Redis Cluster的客户端,可能因客户端无法重定向请求到正确的分片而获取不到需要的数据。
    • Jedis对于Redis Cluster的支持是基于JedisCluster这个类,详细说明请参见Jedis文档
    • 您可以在Redis官网的客户端列表里查找更多支持Redis Cluster的客户端。
  • Redis客户端所在的ECS与目标Redis实例在同一VPC网络。

背景信息

开启直连模式时,云Redis系统会为云Redis集群中所有数据分片的master节点分配一个虚拟IP(VIP)地址。客户端在首次向直连地址发送请求前会通过DNS服务器解析直连地址,解析结果会是集群中一个随机数据分片的VIP。获取到VIP后,客户端即可通过Redis Cluster协议操作云Redis集群中的数据。下图展示了直连模式下Redis集群版的服务架构。
图 1. Redis集群版直连模式服务架构
Redis集群版直连模式服务架构

注意事项

  • 直连地址仅支持通过阿里云内网访问。
  • 直连模式支持使用SELECT命令切换DB,但部分Redis Cluster客户端(例如stackExchange.redis)不支持SELECT命令,如果使用该类客户端则只能使用DB0。
  • 如需使用多key命令、事务、Lua脚本等修改多个key,需确保这些key分布于同一个hash slot。
    说明 多key命令包括DEL、SORT、MGET、MSET、BITOP、EXISTS、MSETNX、RENAME、 RENAMENX、BLPOP、BRPOP、RPOPLPUSH、BRPOPLPUSH、SMOVE、SUNION、SINTER、SDIFF、SUNIONSTORE、SINTERSTORE、SDIFFSTORE、ZUNIONSTORE、ZINTERSTORE、 PFMERGE、PFCOUNT等。
  • 直连模式支持VPC免密账号密码认证

Jedis连接代码示例

说明 Jedis使用说明请参见官方文档
  • 使用默认连接池的示例代码
    import redis.clients.jedis.HostAndPort;
    import redis.clients.jedis.JedisCluster;
    import redis.clients.jedis.JedisPoolConfig;
    
    import java.util.HashSet;
    import java.util.Set;
    
    public class DirectTest  {
        private static final int DEFAULT_TIMEOUT = 2000;
        private static final int DEFAULT_REDIRECTIONS = 5;
        private static final JedisPoolConfig DEFAULT_CONFIG = new JedisPoolConfig();
    
        public static void main(String args[]){
    
            // 开通直连访问时申请到的直连地址
            String host = "r-bp1xxxxxxxxxxxx.redis.rds.aliyuncs.com";
            int port = 6379;
            String password = "xxxx";
    
            Set<HostAndPort> jedisClusterNode = new HashSet<HostAndPort>();
            jedisClusterNode.add(new HostAndPort(host, port));
    
            JedisCluster jc = new JedisCluster(jedisClusterNode, DEFAULT_TIMEOUT, DEFAULT_TIMEOUT,
                    DEFAULT_REDIRECTIONS,password, "clientName", DEFAULT_CONFIG);
    
            jc.set("key","value");
            jc.get("key");
    
            jc.close();
        }
    }
  • 使用自定义连接池的示例代码
    import redis.clients.jedis.*;
    
    import java.util.HashSet;
    import java.util.Set;
    public class main {
        private static final int DEFAULT_TIMEOUT = 2000;
        private static final int DEFAULT_REDIRECTIONS = 5;
        private static final JedisPoolConfig DEFAULT_CONFIG = new JedisPoolConfig();
    
        public static void main(String args[]){
            JedisPoolConfig config = new JedisPoolConfig();
            // 最大空闲连接数, 根据业务需要设置,不能超过实例规格规定的最大的连接数
            config.setMaxIdle(200);
            // 最大连接数, 根据业务需要设置,不能超过实例规格规定的最大的连接数
            config.setMaxTotal(300);
            config.setTestOnBorrow(false);
            config.setTestOnReturn(false);
    
            // 开通直连访问时申请到的直连地址
            String host = "r-bp1xxxxxxxxxxxx.redis.rds.aliyuncs.com"; 
            int port = 6379;
            // 实例的密码
            String password = "xxxxx";
    
            Set<HostAndPort> jedisClusterNode = new HashSet<HostAndPort>();
            jedisClusterNode.add(new HostAndPort(host, port));
            JedisCluster jc = new JedisCluster(jedisClusterNode, DEFAULT_TIMEOUT, DEFAULT_TIMEOUT,
                    DEFAULT_REDIRECTIONS,password, "clientName", config);
    
            try {
                jc.set("foo", "bar");
                String foobar = jc.get("foo");
                jc.zadd("sose", 0, "car");
                jc.zadd("sose", 0, "bike");
                Set<String> sose = jc.zrange("sose", 0, -1);
            } finally {
                if (jc != null) {
                    jc.close();
                }
            }
        }
    }

PhpRedis连接代码示例

说明 PhpRedis使用说明请参见官方文档
<?php
// 直连地址和连接端口
$array = ['r-bp1xxxxxxxxxxxx.redis.rds.aliyuncs.com:6379'];
// 连接密码
$pwd = "xxxx";

// 使用密码连接集群
$obj_cluster = new RedisCluster(NULL, $array, 1.5, 1.5, true, $pwd);

// 输出连接结果
var_dump($obj_cluster);

if ($obj_cluster->set("foo", "bar") == false) {
    die($obj_cluster->getLastError());
}
$value = $obj_cluster->get("foo");
echo $value;
?>