皮皮网

【获取整个网站源码】【斗鱼源码是多少】【扣扣群置顶源码】jedisshardinfo 源码

2024-12-26 01:22:33 来源:android 源码查看网站

1.jedis 源码和 strpin-data-redis 哪一个好
2.java中如何调用enableSharding()

jedisshardinfo 源码

jedis 和 strpin-data-redis 哪一个好

       ä¹‹å‰ä¸€ç›´æ²¡ä»”细看过ShardedJedis的代码,最近遇到了shard后集群扩容后的数据迁移问题。

       ä»Šå¤©åœ¨çœ‹ShardedJedis源码的时候,发现ShardedJedis并没有使用节点的Ip和port做hash,而是用的instance的顺序或者name,太赞了。

       private void initialize(List<S> shards) {

        nodes = new TreeMap<Long, S>();

       for (int i = 0; i != shards.size(); ++i) {

        final S shardInfo = shards.get(i);

        if (shardInfo.getName() == null)

        for (int n = 0; n < * shardInfo.getWeight(); n++) {

        nodes.put(this.algo.hash("SHARD-" + i + "-NODE-" + n),

        shardInfo);

        }

        else

        for (int n = 0; n < * shardInfo.getWeight(); n++) {

        nodes.put(

        this.algo.hash(shardInfo.getName() + "*"

        + shardInfo.getWeight() + n), shardInfo);

        }

        resources.put(shardInfo, shardInfo.createResource());

        }

        }

       é…ç½®çš„时候也非常简单:

       <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">

        <property name="maxTotal" value=""/>

        <property name="maxIdle" value=""/>

        <property name="minIdle" value="1"/>

        <property name="maxWaitMillis" value=""/>

        <property name="testOnBorrow" value="true"/>

        <property name="testOnReturn" value="true"/>

        <property name="testWhileIdle" value="true"/>

        </bean>

        <bean id="shardedJedisPool" class="redis.clients.jedis.ShardedJedisPool" destroy-method="destroy">

        <constructor-arg ref="jedisPoolConfig"/>

        <constructor-arg>

        <list>

        <bean class="redis.clients.jedis.JedisShardInfo">

        <constructor-arg value=".0.0.1"/>

        <constructor-arg type="int" value=""/>

        <constructor-arg value="instance:"/>

        </bean>

        <bean class="redis.clients.jedis.JedisShardInfo">

        <constructor-arg value=".0.0.1"/>

        <constructor-arg type="int" value=""/>

        <constructor-arg value="instance:"/>

        </bean>

        <bean class="redis.clients.jedis.JedisShardInfo">

        <constructor-arg value=".0.0.1"/>

        <constructor-arg type="int" value=""/>

        <constructor-arg value="instance:"/>

        </bean>

        </list>

        </constructor-arg>

        </bean>

       ä¸€å¼€å§‹ä½ å¯ä»¥è®¾ç½®è¶³å¤Ÿå¤šçš„instance,数据扩容的时候,只需要将几个instance的数据copy到别的机器上。

       ç„¶åŽä¿®æ”¹é…ç½®æ–‡ä»¶çš„ip和端口即可。很方便吧?

       å¦å¤–,Jedis还提供了对jedis sentinel pool的封装,所以发生主从切换的时候,web server都不需要重新配置和deploy。高可用性的极佳体现啊。

       @Autowired private JedisSentinelPool pool;

       public void mymethod() {

        Jedis jedis = null;

        try {

        jedis = pool.getResource();

        jedis.hset(....

        } catch (JedisException je) {

        throw je;

        } finally {

        if (jedis != null) pool.returnResource(jedis);

        }

        }

       spring bean的配置:

       <bean id="redisSentinel" class="redis.clients.jedis.JedisSentinelPool">

        <constructor-arg index="0" value="mymaster" />

        <constructor-arg index="1">

        <set>

        <value>hostofsentinel:</value>

        </set>

        </constructor-arg>

        <constructor-arg index="2" ref="jedisPoolConfig" />

        </bean>

java中如何调用enableSharding()

       一.普通同步方式

        最简单和基础的调用方式

       @Test

       public void test1Normal() {

        Jedis jedis = new Jedis("localhost");

        long start = System.currentTimeMillis();

        for (int i = 0; i < ; i++) {

        String result = jedis.set("n" + i, "n" + i);

        }

        long end = System.currentTimeMillis();

        System.out.println("Simple SET: " + ((end - start)/.0) + " seconds");

        jedis.disconnect();

       }

        很简单吧,每次set之后都可以返回结果,源码标记是源码否成功。

       二.事务方式(Transactions)

        redis的源码事务很简单,他主要目的源码是保障,一个client发起的源码获取整个网站源码事务中的命令可以连续的执行,而中间不会插入其他client的源码命令。

        看下面例子:

       @Test

       public void test2Trans() {

        Jedis 源码jedis = new Jedis("localhost");

        long start = System.currentTimeMillis();

        Transaction tx = jedis.multi();

        for (int i = 0; i < ; i++) {

        tx.set("t" + i, "t" + i);

        }

        List<Object> results = tx.exec();

        long end = System.currentTimeMillis();

        System.out.println("Transaction SET: " + ((end - start)/.0) + " seconds");

        jedis.disconnect();

       }

        我们调用jedis.watch(…)方法来监控key,如果调用后key值发生变化,源码则整个事务会执行失败。源码另外,源码事务中某个操作失败,源码并不会回滚其他操作。源码斗鱼源码是多少这一点需要注意。源码还有,源码我们可以使用discard()方法来取消事务。

       三.管道(Pipelining)

        有时,我们需要采用异步方式,一次发送多个指令,扣扣群置顶源码不同步等待其返回结果。这样可以取得非常好的执行效率。这就是管道,调用方法如下:

       @Test

       public void test3Pipelined() {

        Jedis jedis = new Jedis("localhost");

        Pipeline pipeline = jedis.pipelined();

        long start = System.currentTimeMillis();

        for (int i = 0; i < ; i++) {

        pipeline.set("p" + i, "p" + i);

        }

        List<Object> results = pipeline.syncAndReturnAll();

        long end = System.currentTimeMillis();

        System.out.println("Pipelined SET: " + ((end - start)/.0) + " seconds");

        jedis.disconnect();

       }

       四.管道中调用事务

        就Jedis提供的方法而言,是可以做到在管道中使用事务,其代码如下:

       @Test

       public void test4combPipelineTrans() {

        jedis 龙子买点公式源码= new Jedis("localhost");

        long start = System.currentTimeMillis();

        Pipeline pipeline = jedis.pipelined();

        pipeline.multi();

        for (int i = 0; i < ; i++) {

        pipeline.set("" + i, "" + i);

        }

        pipeline.exec();

        List<Object> results = pipeline.syncAndReturnAll();

        long end = System.currentTimeMillis();

        System.out.println("Pipelined transaction: " + ((end - start)/.0) + " seconds");

        jedis.disconnect();

       }

        但是经测试(见本文后续部分),发现其效率和单独使用事务差不多,甚至还略微差点。

       五.分布式直连同步调用

       @Test

       public void test5shardNormal() {

        List<JedisShardInfo> shards = Arrays.asList(

        new JedisShardInfo("localhost",),

        new JedisShardInfo("localhost",));

        ShardedJedis sharding = new ShardedJedis(shards);

        long start = System.currentTimeMillis();

        for (int i = 0; i < ; i++) {

        String result = sharding.set("sn" + i, "n" + i);

        }

        long end = System.currentTimeMillis();

        System.out.println("Simple@Sharing SET: " + ((end - start)/.0) + " seconds");

        sharding.disconnect();

       }

        这个是分布式直接连接,并且是同步调用,每步执行都返回执行结果。类似地,手机整站源码下载还有异步管道调用。

       六.分布式直连异步调用

       @Test

       public void test6shardpipelined() {

        List<JedisShardInfo> shards = Arrays.asList(

        new JedisShardInfo("localhost",),

        new JedisShardInfo("localhost",));

        ShardedJedis sharding = new ShardedJedis(shards);

        ShardedJedisPipeline pipeline = sharding.pipelined();

        long start = System.currentTimeMillis();

        for (int i = 0; i < ; i++) {

        pipeline.set("sp" + i, "p" + i);

        }

        List<Object> results = pipeline.syncAndReturnAll();

        long end = System.currentTimeMillis();

        System.out.println("Pipelined@Sharing SET: " + ((end - start)/.0) + " seconds");

        sharding.disconnect();

       }

       七.分布式连接池同步调用

        如果,你的分布式调用代码是运行在线程中,那么上面两个直连调用方式就不合适了,因为直连方式是非线程安全的,这个时候,你就必须选择连接池调用。

       @Test

       public void test7shardSimplePool() {

        List<JedisShardInfo> shards = Arrays.asList(

        new JedisShardInfo("localhost",),

        new JedisShardInfo("localhost",));

        ShardedJedisPool pool = new ShardedJedisPool(new JedisPoolConfig(), shards);

        ShardedJedis one = pool.getResource();

        long start = System.currentTimeMillis();

        for (int i = 0; i < ; i++) {

        String result = one.set("spn" + i, "n" + i);

        }

        long end = System.currentTimeMillis();

        pool.returnResource(one);

        System.out.println("Simple@Pool SET: " + ((end - start)/.0) + " seconds");

        pool.destroy();

       }

        上面是同步方式,当然还有异步方式。

       八.分布式连接池异步调用

       @Test

       public void test8shardPipelinedPool() {

        List<JedisShardInfo> shards = Arrays.asList(

        new JedisShardInfo("localhost",),

        new JedisShardInfo("localhost",));

        ShardedJedisPool pool = new ShardedJedisPool(new JedisPoolConfig(), shards);

        ShardedJedis one = pool.getResource();

        ShardedJedisPipeline pipeline = one.pipelined();

        long start = System.currentTimeMillis();

        for (int i = 0; i < ; i++) {

        pipeline.set("sppn" + i, "n" + i);

        }

        List<Object> results = pipeline.syncAndReturnAll();

        long end = System.currentTimeMillis();

        pool.returnResource(one);

        System.out.println("Pipelined@Pool SET: " + ((end - start)/.0) + " seconds");

        pool.destroy();

       }

       九.需要注意的地方

        事务和管道都是异步模式。在事务和管道中不能同步查询结果。比如下面两个调用,都是不允许的:

       Transaction tx = jedis.multi();

       for (int i = 0; i < ; i++) {

        tx.set("t" + i, "t" + i);

       }

       System.out.println(tx.get("t").get()); //不允许

       List<Object> results = tx.exec();

       Pipeline pipeline = jedis.pipelined();

       long start = System.currentTimeMillis();

       for (int i = 0; i < ; i++) {

       pipeline.set("p" + i, "p" + i);

       }

       System.out.println(pipeline.get("p").get()); //不允许

       List<Object> results = pipeline.syncAndReturnAll();

        事务和管道都是异步的,个人感觉,在管道中再进行事务调用,没有必要,不如直接进行事务模式。

        分布式中,连接池的性能比直连的性能略好(见后续测试部分)。

        分布式调用中不支持事务。

        因为事务是在服务器端实现,而在分布式中,每批次的调用对象都可能访问不同的机器,所以,没法进行事务。