redis的 java 客户端

比较有名的是jedis( 连接池是基于apache-commons pool2实现的)和Lettuce(基于netty实现),Redisson(基于netty实现,有不少高级功能,比如分布式锁)

1.jedis

Jedis连接方式有三种Jedis/JedisPool 连接、ShardedJedis/ShardedJedisPool 连接、JedisCluster 连接。

Jedis直连相当于一个TCP连接,数据传输完成后关闭连接

JedisPool 是一个链接池,存储了一批jedis对象,多次使用时,不需要反复创建Jedis。

 

ShardedJedis 要根据key返回映射到的jedis,再调用jedis对象。

  public String set(String key, String value) {
    Jedis j = getShard(key);
    return j.set(key, value);
  }

ShardedJedisPool 构造了一组ShardedJedis对象,每个ShardedJedis对象包含一个redis分片对应的jedis对象。

从ShardedJedisPool选取一个ShardedJedis,实际包含了到每个redis分片的链接。这里是否可以考虑基于jedisPool数组来实现?用一个map记录shard信息,和shard对应的redis的分片的jedispool, 通过key取到对应的jedispool,再从jedispool里取出一个jedis链接。

public class ShardedJedisPool extends Pool<ShardedJedis>

    @Override
    public PooledObject<ShardedJedis> makeObject() hrows Exception {
      ShardedJedis jedis = new ShardedJedis(shards, algo, keyTagPattern);
      return new DefaultPooledObject<ShardedJedis>(jedis);
    }

ShardedJedisPool 在验证到red is 服务器的链接的有效性时,只要到一个分片的链接失效,这个ShardedJedis就认为失效,哪怕到其他redis分片链接是好的。

    @Override
    public boolean validateObject(PooledObject<ShardedJedis> pooledShardedJedis) {
      try {
        ShardedJedis jedis = pooledShardedJedis.getObject();
        for (Jedis shard : jedis.getAllShards()) {
          if (!shard.ping().equals("PONG")) {
            return false;
          }
        }
        return true;
      } catch (Exception ex) {
        return false;
      }
    }

JedisSentinelPool 要用 sentinel中读取redis主节点的Ip端口,还需要一个监听器(线程和redis订阅发布机制)来监听 master的变化。

      try {
        jedis = new Jedis(hap.getHost(), hap.getPort());

        List<String> masterAddr = jedis.sentinelGetMasterAddrByName(masterName);

        // connected to sentinel...
        sentinelAvailable = true;

        if (masterAddr == null || masterAddr.size() != 2) {
          log.warning("Can not get master addr, master name: " + masterName + ". Sentinel: " + hap
              + ".");
          continue;
        }

        master = toHostAndPort(masterAddr);
        log.fine("Found Redis master at " + master);
        break;
      } catch (JedisException e) {

 

protected class MasterListener extends Thread {

...

   public void run() {

      running.set(true);

      while (running.get()) {

        j = new Jedis(host, port);

        try {
          // double check that it is not being shutdown
          if (!running.get()) {
            break;
          }

          j.subscribe(new JedisPubSub() {
            @Override
            public void onMessage(String channel, String message) {
              log.fine("Sentinel " + host + ":" + port + " published: " + message + ".");

              String[] switchMasterMsg = message.split(" ");

              if (switchMasterMsg.length > 3) {

                if (masterName.equals(switchMasterMsg[0])) {
                  initPool(toHostAndPort(Arrays.asList(switchMasterMsg[3], switchMasterMsg[4])));
                } else {
                  log.fine("Ignoring message on +switch-master for master name "
                      + switchMasterMsg[0] + ", our master name is " + masterName);
                }

jedis2.8不支持ShardedJedisSentinelPool,以及读写分离的ShardedJedisSentinelPool,需要自己参考JedisSentinelPool和ShardedJedisPool来实现

ShardedJedisSentinelPool可以参考ShardedJedisPool实现方式,本质还是通过setinel拿到一组master节点的ip端口等信息后,建一个Pool<ShardedJedis>,当然,还需要启动监听器线程,监听master的变化,master变化后要重新初始化链接。

利用apache commons pool 创建池时,需要传入一个对象创建工厂,实际传入的事ShardedJedisFactory,里面实现了makeObject函数用来创建ShardedJedis对象,放入DefaultPooledObject中。

this.internalPool = new GenericObjectPool<T>(factory, poolConfig);

 

   @Override
    public PooledObject<ShardedJedis> makeObject() throws Exception {
      ShardedJedis jedis = new ShardedJedis(shards, algo, keyTagPattern);
      return new DefaultPooledObject<ShardedJedis>(jedis);
    }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值