1.jedis 源码å strpin-data-redis åªä¸ä¸ªå¥½
2.java中如何调用enableSharding()
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();
事务和管道都是异步的,个人感觉,在管道中再进行事务调用,没有必要,不如直接进行事务模式。
分布式中,连接池的性能比直连的性能略好(见后续测试部分)。
分布式调用中不支持事务。
因为事务是在服务器端实现,而在分布式中,每批次的调用对象都可能访问不同的机器,所以,没法进行事务。