redis学习及实践3---Jedis、JedisPool、Jedis分布式实例介绍

一、相关jar包

    主要用到的是jedis的核心包,笔者用到的是2.1.0版;另根据“池”的应用等还需要用到相关jar包。下图是笔者建立的简单的jedis测试project图:

wKioL1MdK_fybGUhAACpWhNr9Ik847.jpg

    jar包的文档可参考:

http://www.boyunjian.com/javadoc/org.apache.servicemix.bundles/org.apache.servicemix.bundles.jedis/2.1.0_1/_/redis/clients/jedis/JedisShardInfo.html

二、简单的Jedis实例

    在引入相关jar包后,只要new一个Jedis对象,就能做redis相关操作了。以下是一个简单的jedis实例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
package com.pptv.redis;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import redis.clients.jedis.Jedis;
public class JedisDemo {
public void test(){
Jedis  redis = new Jedis ("172.0.0.1",6379);//连接redis
redis.auth("redis");//验证密码,如果需要验证的话
// STRING 操作
//SET key value将字符串值value关联到key。
redis.set("name""wangjun1");
redis.set("id""123456");
redis.set("address""guangzhou");
//SETEX key seconds value将值value关联到key,并将key的生存时间设为seconds(以秒为单位)。
redis.setex("foo"5"haha");
//MSET key value [key value ...]同时设置一个或多个key-value对。
redis.mset("haha","111","xixi","222");
//redis.flushAll();清空所有的key
System.out.println(redis.dbSize());//dbSize是多少个key的个数
//APPEND key value如果key已经存在并且是一个字符串,APPEND命令将value追加到key原来的值之后。
redis.append("foo""00");//如果key已经存在并且是一个字符串,APPEND命令将value追加到key原来的值之后。
//GET key 返回key所关联的字符串值
redis.get("foo");
//MGET key [key ...] 返回所有(一个或多个)给定key的值
List list = redis.mget("haha","xixi");
for(int i=0;i<list.size();i++){
System.out.println(list.get(i));
}
}
public static void main(String[] args) {
JedisDemo t1 = new JedisDemo();
t1.test();
}
}

三、JedisPool应用

Jedis使用commons-pool完成池化实现。

    先做个配置文件(properties文件):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#最大分配的对象数
redis.pool.maxActive=1024
#最大能够保持idel状态的对象数
redis.pool.maxIdle=200
#当池内没有返回对象时,最大等待时间
redis.pool.maxWait=1000
#当调用borrow Object方法时,是否进行有效性检查
redis.pool.testOnBorrow=true
#当调用return Object方法时,是否进行有效性检查
redis.pool.testOnReturn=true
#IP
redis.ip=172.0.0.1
#Port
redis.port=6379

    jedisPool的相关详细配置可参考:http://www.2cto.com/database/201311/254449.html    

    在静态代码段中完成初始化:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
private static JedisPool pool;
static {
ResourceBundle bundle = ResourceBundle.getBundle("redis");
if (bundle == null) {
throw new IllegalArgumentException(
"[redis.properties] is not found!");
}
JedisPoolConfig config = new JedisPoolConfig();
config.setMaxActive(Integer.valueOf(bundle
.getString("redis.pool.maxActive")));
config.setMaxIdle(Integer.valueOf(bundle
.getString("redis.pool.maxIdle")));
config.setMaxWait(Long.valueOf(bundle.getString("redis.pool.maxWait")));
config.setTestOnBorrow(Boolean.valueOf(bundle
.getString("redis.pool.testOnBorrow")));
config.setTestOnReturn(Boolean.valueOf(bundle
.getString("redis.pool.testOnReturn")));
pool = new JedisPool(config, bundle.getString("redis.ip"),
Integer.valueOf(bundle.getString("redis.port")));
}

    然后修改#2的简单实例,修改为Jedis从pool中获得:

1
2
3
4
5
6
7
8
9
10
11
12
// 从池中获取一个Jedis对象
Jedis jedis = pool.getResource();
String keys = "name";
// 删数据
jedis.del(keys);
// 存数据
jedis.set(keys, "snowolf");
// 取数据
String value = jedis.get(keys);
System.out.println(value);
// 释放对象池
pool.returnResource(jedis);

四、Jedis分布式(Sharding/shared一致性哈希)

    Memcached完全基于分布式集群,而RedisMaster-Slave,如果想把Reids,做成集群模式,无外乎多做几套Master-Slave,每套Master-Slave完成各自的容灾处理,通过Client工具,完成一致性哈希。(PS:Memcached是在Server端完成ShardingRedis只能依靠各个ClientSharding。可能会在Redis 3.0系列支持ServerSharding。)

    shared一致性哈希采用以下方案:

  1. Redis服务器节点划分:将每台服务器节点采用hash算法划分为160个虚拟节点(可以配置划分权重)

  2. 将划分虚拟节点采用TreeMap存储

  3. 对每个Redis服务器的物理连接采用LinkedHashMap存储

  4. 对Key or KeyTag 采用同样的hash算法,然后从TreeMap获取大于等于键hash值得节点,取最邻近节点存储;当key的hash值大于虚拟节点hash值得最大值时,存入第一个虚拟节点

sharded采用的hash算法:MD5 和 MurmurHash两种;默认采用64位的MurmurHash算法;有兴趣的可以研究下,MurmurHash是一种高效,低碰撞的hash算法;参考地址:  

    保留前面的JedisPoolConfig,新增两个Redis的IP(redis1.ip,redis2.ip),完成两个JedisShardInfo实例,并将其丢进List中:

1
2
3
4
5
6
7
JedisShardInfo jedisShardInfo1 = new JedisShardInfo(
bundle.getString("redis1.ip"), Integer.valueOf(bundle                       .getString("redis.port")));
JedisShardInfo jedisShardInfo2 = new JedisShardInfo(
bundle.getString("redis2.ip"), Integer.valueOf(bundle                       .getString("redis.port")));
List<JedisShardInfo> list = new LinkedList<JedisShardInfo>();
list.add(jedisShardInfo1);
list.add(jedisShardInfo2);

    初始化ShardedJedisPool代替JedisPool:

1
ShardedJedisPool pool = new ShardedJedisPool(config, list);

     改由ShardedJedis,获取Jedis对象:

1
2
3
4
5
6
7
8
9
10
11
12
13
// 从池中获取一个Jedis对象
ShardedJedis jedis = pool.getResource();
String keys = "name";
String value = "snowolf";
// 删数据
jedis.del(keys);
// 存数据
jedis.set(keys, value);
// 取数据
String v = jedis.get(keys);
System.out.println(v);
// 释放对象池
pool.returnResource(jedis);

    通过以上方式,向redis进行set操作的key-value,会通过hash而均匀的分配到pool里的redis机器中。

五、综合实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
package com.pptv.redis;
import java.util.ArrayList;
import java.util.List;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.JedisShardInfo;
import redis.clients.jedis.ShardedJedis;
import redis.clients.jedis.ShardedJedisPool;
/**
* redis的Java客户端Jedis测试验证
*
* @author
*/
public class Test {
/**
* 非切片客户端链接
*/
private Jedis jedis;
/**
* 非切片链接池
*/
private JedisPool jedisPool;
/**
* 切片客户端链接
*/
private ShardedJedis shardedJedis;
/**
* 切片链接池
*/
private ShardedJedisPool shardedJedisPool;
private String ip = "172.16.205.186";
/**
* 构造函数
*/
public Test() {
initialPool();
initialShardedPool();
shardedJedis = shardedJedisPool.getResource();
jedis = jedisPool.getResource();
}
private void initialPool() {
// 池基本配置
JedisPoolConfig config = new JedisPoolConfig();
config.setMaxActive(20);
config.setMaxIdle(5);
config.setMaxWait(1000l);
config.setTestOnBorrow(false);
jedisPool = new JedisPool(config, ip, 6379);
}
/**
* 初始化切片池
*/
private void initialShardedPool() {
// 池基本配置
JedisPoolConfig config = new JedisPoolConfig();
config.setMaxActive(20);
config.setMaxIdle(5);
config.setMaxWait(1000l);
config.setTestOnBorrow(false);
// slave链接
List<JedisShardInfo> shards = new ArrayList<JedisShardInfo>();
shards.add(new JedisShardInfo(ip, 6379"master"));
// 构造池
shardedJedisPool = new ShardedJedisPool(config, shards);
}
public void show() {
// key检测
testKey();
// string检测
testString();
// list检测
testList();
// set检测
testSet();
// sortedSet检测
testSortedSet();
// hash检测
testHash();
shardedJedisPool.returnResource(shardedJedis);
}
private void testKey() {
System.out.println("=============key==========================");
// 清空数据
System.out.println(jedis.flushDB());
System.out.println(jedis.echo("foo"));
// 判断key否存在
System.out.println(shardedJedis.exists("foo"));
shardedJedis.set("key""values");
System.out.println(shardedJedis.exists("key"));
}
private void testString() {
System.out.println("=============String==========================");
// 清空数据
System.out.println(jedis.flushDB());
// 存储数据
shardedJedis.set("foo""bar");
System.out.println(shardedJedis.get("foo"));
// 若key不存在,则存储
shardedJedis.setnx("foo""foo not exits");
System.out.println(shardedJedis.get("foo"));
// 覆盖数据
shardedJedis.set("foo""foo update");
System.out.println(shardedJedis.get("foo"));
// 追加数据
shardedJedis.append("foo"" hello, world");
System.out.println(shardedJedis.get("foo"));
// 设置key的有效期,并存储数据
shardedJedis.setex("foo"2"foo not exits");
System.out.println(shardedJedis.get("foo"));
try {
Thread.sleep(3000);
catch (InterruptedException e) {
}
System.out.println(shardedJedis.get("foo"));
// 获取并更改数据
shardedJedis.set("foo""foo update");
System.out.println(shardedJedis.getSet("foo""foo modify"));
// 截取value的值
System.out.println(shardedJedis.getrange("foo"13));
System.out.println(jedis.mset("mset1""mvalue1""mset2""mvalue2",
"mset3""mvalue3""mset4""mvalue4"));
System.out.println(jedis.mget("mset1""mset2""mset3""mset4"));
System.out.println(jedis.del(new String[] { "foo""foo1""foo3" }));
}
private void testList() {
System.out.println("=============list==========================");
// 清空数据
System.out.println(jedis.flushDB());
// 添加数据
shardedJedis.lpush("lists""vector");
shardedJedis.lpush("lists""ArrayList");
shardedJedis.lpush("lists""LinkedList");
// 数组长度
System.out.println(shardedJedis.llen("lists"));
// 排序
//      System.out.println(shardedJedis.sort("lists"));
// 字串
System.out.println(shardedJedis.lrange("lists"03));
// 修改列表中单个值
shardedJedis.lset("lists"0"hello list!");
// 获取列表指定下标的值
System.out.println(shardedJedis.lindex("lists"1));
// 删除列表指定下标的值
System.out.println(shardedJedis.lrem("lists"1"vector"));
// 删除区间以外的数据
System.out.println(shardedJedis.ltrim("lists"01));
// 列表出栈
System.out.println(shardedJedis.lpop("lists"));
// 整个列表值
System.out.println(shardedJedis.lrange("lists"0, -1));
}
private void testSet() {
System.out.println("=============set==========================");
// 清空数据
System.out.println(jedis.flushDB());
// 添加数据
shardedJedis.sadd("sets""HashSet");
shardedJedis.sadd("sets""SortedSet");
shardedJedis.sadd("sets""TreeSet");
// 判断value是否在列表中
System.out.println(shardedJedis.sismember("sets""TreeSet"));
;
// 整个列表值
System.out.println(shardedJedis.smembers("sets"));
// 删除指定元素
System.out.println(shardedJedis.srem("sets""SortedSet"));
// 出栈
System.out.println(shardedJedis.spop("sets"));
System.out.println(shardedJedis.smembers("sets"));
//
shardedJedis.sadd("sets1""HashSet1");
shardedJedis.sadd("sets1""SortedSet1");
shardedJedis.sadd("sets1""TreeSet");
shardedJedis.sadd("sets2""HashSet2");
shardedJedis.sadd("sets2""SortedSet1");
shardedJedis.sadd("sets2""TreeSet1");
// 交集
System.out.println(jedis.sinter("sets1""sets2"));
// 并集
System.out.println(jedis.sunion("sets1""sets2"));
// 差集
System.out.println(jedis.sdiff("sets1""sets2"));
}
private void testSortedSet() {
System.out.println("=============zset==========================");
// 清空数据
System.out.println(jedis.flushDB());
// 添加数据
shardedJedis.zadd("zset"10.1"hello");
shardedJedis.zadd("zset"10.0":");
shardedJedis.zadd("zset"9.0"zset");
shardedJedis.zadd("zset"11.0"zset!");
// 元素个数
System.out.println(shardedJedis.zcard("zset"));
// 元素下标
System.out.println(shardedJedis.zscore("zset""zset"));
// 集合子集
System.out.println(shardedJedis.zrange("zset"0, -1));
// 删除元素
System.out.println(shardedJedis.zrem("zset""zset!"));
System.out.println(shardedJedis.zcount("zset"9.510.5));
// 整个集合值
System.out.println(shardedJedis.zrange("zset"0, -1));
}
private void testHash() {
System.out.println("=============hash==========================");
// 清空数据
System.out.println(jedis.flushDB());
// 添加数据
shardedJedis.hset("hashs""entryKey""entryValue");
shardedJedis.hset("hashs""entryKey1""entryValue1");
shardedJedis.hset("hashs""entryKey2""entryValue2");
// 判断某个值是否存在
System.out.println(shardedJedis.hexists("hashs""entryKey"));
// 获取指定的值
System.out.println(shardedJedis.hget("hashs""entryKey"));
// 批量获取指定的值
System.out
.println(shardedJedis.hmget("hashs""entryKey""entryKey1"));
// 删除指定的值
System.out.println(shardedJedis.hdel("hashs""entryKey"));
// 为key中的域 field 的值加上增量 increment
System.out.println(shardedJedis.hincrBy("hashs""entryKey", 123l));
// 获取所有的keys
System.out.println(shardedJedis.hkeys("hashs"));
// 获取所有的values
System.out.println(shardedJedis.hvals("hashs"));
}
/**
* @param args
*/
public static void main(String[] args) {
new Test().show();
}
}
原文地址:https://www.cnblogs.com/yuhoukongshan/p/6344286.html