Search in sources :

Example 96 with HostAndPort

use of redis.clients.jedis.HostAndPort in project cachecloud by sohutv.

the class ClusterNodeInformationParser method parse.

public ClusterNodeInformation parse(String nodeInfo, HostAndPort current) {
    String[] nodeInfoPartArray = nodeInfo.split(" ");
    HostAndPort node = getHostAndPortFromNodeLine(nodeInfoPartArray, current);
    ClusterNodeInformation info = new ClusterNodeInformation(node);
    if (nodeInfoPartArray.length >= SLOT_INFORMATIONS_START_INDEX) {
        String[] slotInfoPartArray = extractSlotParts(nodeInfoPartArray);
        fillSlotInformation(slotInfoPartArray, info);
    }
    return info;
}
Also used : HostAndPort(redis.clients.jedis.HostAndPort)

Example 97 with HostAndPort

use of redis.clients.jedis.HostAndPort in project cachecloud by sohutv.

the class RedisSentinelTest method testSentinel.

@Test
public void testSentinel() {
    JedisSentinelPool sentinelPool = ClientBuilder.redisSentinel(appId).setConnectionTimeout(2000).setSoTimeout(1000).build();
    HostAndPort currentHostMaster = sentinelPool.getCurrentHostMaster();
    logger.info("current master: {}", currentHostMaster.toString());
    Jedis jedis = sentinelPool.getResource();
    for (int i = 0; i < 10; i++) {
        jedis.lpush("mylist", "list-" + i);
    }
    jedis.close();
    sentinelPool.destroy();
}
Also used : HostAndPort(redis.clients.jedis.HostAndPort) Jedis(redis.clients.jedis.Jedis) JedisSentinelPool(redis.clients.jedis.JedisSentinelPool) BaseTest(com.sohu.tv.test.base.BaseTest) Test(org.junit.Test)

Example 98 with HostAndPort

use of redis.clients.jedis.HostAndPort in project cachecloud by sohutv.

the class RedisClusterBuilder method build.

public JedisCluster build() {
    if (jedisCluster == null) {
        while (true) {
            try {
                lock.tryLock(10, TimeUnit.SECONDS);
                if (jedisCluster != null) {
                    return jedisCluster;
                }
                String url = String.format(ConstUtils.REDIS_CLUSTER_URL, String.valueOf(appId));
                String response = HttpUtils.doGet(url);
                JSONObject jsonObject = null;
                try {
                    jsonObject = JSONObject.parseObject(response);
                } catch (Exception e) {
                    logger.error("remote build error, appId: {}", appId, e);
                }
                if (jsonObject == null) {
                    logger.error("get cluster info for appId: {} error. continue...", appId);
                    continue;
                }
                int status = jsonObject.getIntValue("status");
                String message = jsonObject.getString("message");
                /**
                 * 检查客户端版本 *
                 */
                if (status == ClientStatusEnum.ERROR.getStatus()) {
                    throw new IllegalStateException(message);
                } else if (status == ClientStatusEnum.WARN.getStatus()) {
                    logger.warn(message);
                } else {
                    logger.info(message);
                }
                Set<HostAndPort> nodeList = new HashSet<HostAndPort>();
                // 形如 ip1:port1,ip2:port2,ip3:port3
                String nodeInfo = jsonObject.getString("shardInfo");
                // 为了兼容,如果允许直接nodeInfo.split(" ")
                nodeInfo = nodeInfo.replace(" ", ",");
                String[] nodeArray = nodeInfo.split(",");
                for (String node : nodeArray) {
                    String[] ipAndPort = node.split(":");
                    if (ipAndPort.length < 2) {
                        continue;
                    }
                    String ip = ipAndPort[0];
                    int port = Integer.parseInt(ipAndPort[1]);
                    nodeList.add(new HostAndPort(ip, port));
                }
                // 收集上报数据
                if (clientStatIsOpen) {
                    ClientDataCollectReportExecutor.getInstance();
                }
                String password = jsonObject.getString("password");
                if (StringUtil.isBlank(password)) {
                    jedisCluster = new JedisCluster(nodeList, connectionTimeout, soTimeout, maxRedirections, jedisPoolConfig);
                } else {
                    jedisCluster = new JedisCluster(nodeList, connectionTimeout, soTimeout, maxRedirections, password, jedisPoolConfig);
                }
                return jedisCluster;
            } catch (Throwable e) {
                logger.error(e.getMessage(), e);
            } finally {
                lock.unlock();
            }
            try {
                // 活锁
                TimeUnit.MILLISECONDS.sleep(200 + new Random().nextInt(1000));
            } catch (InterruptedException e) {
                logger.error(e.getMessage(), e);
            }
        }
    } else {
        return jedisCluster;
    }
}
Also used : HostAndPort(redis.clients.jedis.HostAndPort) JSONObject(com.alibaba.fastjson.JSONObject) Random(java.util.Random) JedisCluster(redis.clients.jedis.JedisCluster) HashSet(java.util.HashSet)

Example 99 with HostAndPort

use of redis.clients.jedis.HostAndPort in project cachecloud by sohutv.

the class RedisDeployCenterImpl method addSlotsFailMaster.

@Override
public RedisOperateEnum addSlotsFailMaster(final long appId, int lossSlotsInstanceId, final String newMasterHost) throws Exception {
    // 1.参数、应用、实例信息确认
    Assert.isTrue(appId > 0);
    Assert.isTrue(lossSlotsInstanceId > 0);
    Assert.isTrue(StringUtils.isNotBlank(newMasterHost));
    AppDesc appDesc = appDao.getAppDescById(appId);
    Assert.isTrue(appDesc != null);
    int type = appDesc.getType();
    if (!TypeUtil.isRedisCluster(type)) {
        logger.error("{} is not redis cluster type", appDesc);
        return RedisOperateEnum.FAIL;
    }
    // 获取失联slots的实例信息
    InstanceInfo lossSlotsInstanceInfo = instanceDao.getInstanceInfoById(lossSlotsInstanceId);
    Assert.isTrue(lossSlotsInstanceInfo != null);
    // 2.获取集群中一个健康的master作为clusterInfo Nodes的数据源
    List<InstanceInfo> allInstanceInfo = redisCenter.getAllHealthyInstanceInfo(appId);
    // InstanceInfo sourceMasterInstance = redisCenter.getHealthyInstanceInfo(appId);
    if (allInstanceInfo == null || allInstanceInfo.size() == 0) {
        logger.warn("appId {} get all instance is zero", appId);
        return RedisOperateEnum.FAIL;
    }
    // 默认获取第一个master节点
    InstanceInfo sourceMasterInstance = allInstanceInfo.get(0);
    // 并未找到一个合适的实例可以
    if (sourceMasterInstance == null) {
        logger.warn("appId {} does not have right instance", appId);
        return RedisOperateEnum.FAIL;
    }
    // 3. 找到丢失的slots,如果没找到就说明集群正常,直接返回
    String healthyMasterHost = sourceMasterInstance.getIp();
    int healthyMasterPort = sourceMasterInstance.getPort();
    int healthyMasterMem = sourceMasterInstance.getMem();
    // 3.1 查看整个集群中是否有丢失的slots
    List<Integer> allLossSlots = redisCenter.getClusterLossSlots(appId, healthyMasterHost, healthyMasterPort);
    if (CollectionUtils.isEmpty(allLossSlots)) {
        logger.warn("appId {} all slots is regular and assigned", appId);
        return RedisOperateEnum.ALREADY_SUCCESS;
    }
    // 3.2 查看目标实例丢失slots
    final List<Integer> clusterLossSlots = redisCenter.getInstanceSlots(appId, healthyMasterHost, healthyMasterPort, lossSlotsInstanceInfo.getIp(), lossSlotsInstanceInfo.getPort());
    // 4.开启新的节点
    // 4.1 从newMasterHost找到可用的端口newMasterPort
    final Integer newMasterPort = machineCenter.getAvailablePort(newMasterHost, ConstUtils.CACHE_TYPE_REDIS_CLUSTER);
    if (newMasterPort == null) {
        logger.error("host={} getAvailablePort is null", newMasterHost);
        return RedisOperateEnum.FAIL;
    }
    // 4.2 按照sourceMasterInstance的内存启动
    boolean isRun = runInstance(appDesc, newMasterHost, newMasterPort, healthyMasterMem, true);
    if (!isRun) {
        logger.error("{}:{} is not run", newMasterHost, newMasterPort);
        return RedisOperateEnum.FAIL;
    }
    // 4.3 拷贝配置
    boolean isCopy = copyCommonConfig(appId, healthyMasterHost, healthyMasterPort, newMasterHost, newMasterPort);
    if (!isCopy) {
        logger.error("{}:{} copy config {}:{} is error", healthyMasterHost, healthyMasterPort, newMasterHost, newMasterPort);
        return RedisOperateEnum.FAIL;
    }
    // 5. meet
    boolean isClusterMeet = false;
    Jedis sourceMasterJedis = null;
    try {
        sourceMasterJedis = redisCenter.getJedis(appId, healthyMasterHost, healthyMasterPort);
        isClusterMeet = clusterMeet(sourceMasterJedis, appId, newMasterHost, newMasterPort);
        if (!isClusterMeet) {
            logger.error("{}:{} cluster is failed", newMasterHost, newMasterPort);
            return RedisOperateEnum.FAIL;
        }
    } catch (Exception e) {
        logger.error(e.getMessage(), e);
    } finally {
        if (sourceMasterJedis != null) {
            sourceMasterJedis.close();
        }
    }
    if (!isClusterMeet) {
        logger.warn("{}:{} meet {}:{} is fail", healthyMasterHost, healthyMasterPort, newMasterHost, newMasterPort);
        return RedisOperateEnum.FAIL;
    }
    // 6. 分配slots
    String nodeId = null;
    Jedis newMasterJedis = null;
    try {
        newMasterJedis = redisCenter.getJedis(appId, newMasterHost, newMasterPort, 5000, 5000);
        // 获取新的补救节点的nodeid
        nodeId = getClusterNodeId(newMasterJedis);
    } catch (Exception e) {
        logger.error(e.getMessage(), e);
    } finally {
        if (newMasterJedis != null) {
            newMasterJedis.close();
        }
    }
    final String newNodeId = nodeId;
    if (StringUtils.isBlank(nodeId)) {
        logger.warn("{}:{} nodeId is empty!");
        return RedisOperateEnum.FAIL;
    }
    // 需要做setslot的实例列表
    final List<HostAndPort> hostAndPorts = new ArrayList<>();
    hostAndPorts.add(new HostAndPort(newMasterHost, newMasterPort));
    for (InstanceInfo instance : allInstanceInfo) {
        hostAndPorts.add(new HostAndPort(instance.getIp(), instance.getPort()));
    }
    final Map<String, Jedis> jedisMap = new HashMap<String, Jedis>();
    for (final Integer slot : clusterLossSlots) {
        logger.warn("set slot {} start", slot);
        boolean setSlotStatus = new IdempotentConfirmer() {

            @Override
            public boolean execute() {
                String setSlotsResult = null;
                for (HostAndPort hostAndPort : hostAndPorts) {
                    Jedis masterJedis = null;
                    try {
                        String hostPort = hostAndPort.toString();
                        if (jedisMap.containsKey(hostAndPort)) {
                            masterJedis = jedisMap.get(hostAndPort);
                        } else {
                            masterJedis = redisCenter.getJedis(appId, hostAndPort.getHost(), hostAndPort.getPort(), 5000, 5000);
                            jedisMap.put(hostPort, masterJedis);
                        }
                        setSlotsResult = masterJedis.clusterSetSlotNode(slot, newNodeId);
                        logger.warn("\t {} set slot {}, result is {}", hostAndPort.toString(), slot, setSlotsResult);
                    } catch (JedisDataException exception) {
                        logger.warn(exception.getMessage());
                        // unkown jedis node
                        try {
                            TimeUnit.SECONDS.sleep(2);
                        } catch (InterruptedException e) {
                            logger.error(e.getMessage(), e);
                        }
                    }
                }
                boolean nodeSetStatus = setSlotsResult != null && setSlotsResult.equalsIgnoreCase("OK");
                return nodeSetStatus;
            }
        }.run();
        // set slots result
        if (setSlotStatus) {
            logger.warn("set slot {} success", slot);
        } else {
            logger.warn("set slot {} faily", slot);
            return RedisOperateEnum.FAIL;
        }
    }
    // 统一关闭
    for (Jedis jedis : jedisMap.values()) {
        if (jedis != null) {
            jedis.close();
        }
    }
    // 7.保存实例信息、并开启收集信息
    saveInstance(appId, newMasterHost, newMasterPort, healthyMasterMem, ConstUtils.CACHE_TYPE_REDIS_CLUSTER, "");
    redisCenter.deployRedisCollection(appId, newMasterHost, newMasterPort);
    // 休息一段时间,同步clusterNodes信息
    TimeUnit.SECONDS.sleep(2);
    // 8.最终打印出当前还没有补充的slots
    List<Integer> currentLossSlots = redisCenter.getClusterLossSlots(appId, newMasterHost, newMasterPort);
    logger.warn("appId {} failslots assigned unsuccessfully, lossslots is {}", appId, currentLossSlots);
    return RedisOperateEnum.OP_SUCCESS;
}
Also used : AppDesc(com.sohu.cache.entity.AppDesc) JedisDataException(redis.clients.jedis.exceptions.JedisDataException) InstanceInfo(com.sohu.cache.entity.InstanceInfo) JedisDataException(redis.clients.jedis.exceptions.JedisDataException) Jedis(redis.clients.jedis.Jedis) HostAndPort(redis.clients.jedis.HostAndPort) IdempotentConfirmer(com.sohu.cache.util.IdempotentConfirmer)

Example 100 with HostAndPort

use of redis.clients.jedis.HostAndPort in project cachecloud by sohutv.

the class JedisSentinelTestUtil method waitForNewPromotedMaster.

public static HostAndPort waitForNewPromotedMaster(final String masterName, final Jedis sentinelJedis, final Jedis commandJedis) throws InterruptedException {
    final AtomicReference<String> newmaster = new AtomicReference<String>("");
    sentinelJedis.psubscribe(new JedisPubSub() {

        @Override
        public void onPMessage(String pattern, String channel, String message) {
            if (channel.equals("+switch-master")) {
                newmaster.set(message);
                punsubscribe();
            } else if (channel.startsWith("-failover-abort")) {
                punsubscribe();
                throw new FailoverAbortedException("Unfortunately sentinel cannot failover... reason(channel) : " + channel + " / message : " + message);
            }
        }

        @Override
        public void onPSubscribe(String pattern, int subscribedChannels) {
            commandJedis.sentinelFailover(masterName);
        }
    }, "*");
    String[] chunks = newmaster.get().split(" ");
    HostAndPort newMaster = new HostAndPort(chunks[3], Integer.parseInt(chunks[4]));
    return newMaster;
}
Also used : HostAndPort(redis.clients.jedis.HostAndPort) AtomicReference(java.util.concurrent.atomic.AtomicReference) JedisPubSub(redis.clients.jedis.JedisPubSub)

Aggregations

HostAndPort (redis.clients.jedis.HostAndPort)102 Test (org.junit.Test)42 HashSet (java.util.HashSet)35 JedisCluster (redis.clients.jedis.JedisCluster)35 Jedis (redis.clients.jedis.Jedis)25 LinkedHashSet (java.util.LinkedHashSet)18 JedisPoolConfig (redis.clients.jedis.JedisPoolConfig)12 Before (org.junit.Before)9 JedisPool (redis.clients.jedis.JedisPool)9 ArrayList (java.util.ArrayList)8 ClusterNodeInformation (redis.clients.util.ClusterNodeInformation)6 AppDesc (com.sohu.cache.entity.AppDesc)5 InstanceInfo (com.sohu.cache.entity.InstanceInfo)5 JedisSentinelPool (redis.clients.jedis.JedisSentinelPool)5 IOException (java.io.IOException)4 AtomicReference (java.util.concurrent.atomic.AtomicReference)4 JedisPubSub (redis.clients.jedis.JedisPubSub)4 HashMap (java.util.HashMap)3 Map (java.util.Map)3 Properties (java.util.Properties)3