18.java连接redis

 

java连接redis

1. Jedis所需要的jar包依赖

1
2
3
4
5
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>3.3.0</version>
</dependency>

2. Jedis常用操作

2.1 测试连通性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package com.redis.demo;

import redis.clients.jedis.Jedis;

public class RedisConnection {

public static void main(String[] args) {

// create redis connection
Jedis jedis = new Jedis("192.168.168.130", 6379);
// ping
String pingResult = jedis.ping();
System.out.println(pingResult);
// close the redis connection
jedis.close();

}
}

2.2 基本操作

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
package com.redis.demo;

import redis.clients.jedis.Jedis;

import java.util.*;

public class RedisJavaCommon {
public static void main(String[] args) {

// redis connection
Jedis jedis = new Jedis("192.168.168.130", 6379);

// key
System.out.println("----------key----------");
Set<String> keys = jedis.keys("*");
Iterator<String> keysIterator = keys.iterator();
while (keysIterator.hasNext()) {
String key = keysIterator.next();
System.out.println(key);
}

// String
System.out.println("----------String----------");
jedis.set("level", "middle");
jedis.append("level", "-class");
System.out.println(jedis.get("level"));
jedis.set("k1", "v1");
jedis.mset("k2", "v2", "k3", "v3");
System.out.println(jedis.mget("k1", "k2", "k3"));

// list
System.out.println("----------list----------");
// clear the list
while (jedis.lpop("myRedisList") != null) {

}
jedis.lpush("myRedisList", "e1", "e2", "e3", "e4", "e5", "e6");
List<String> redisList = jedis.lrange("myRedisList", 0, -1);
for (String element: redisList) {
System.out.println(element);
}

// set
System.out.println("----------set----------");
jedis.sadd("series number", "111");
jedis.sadd("series number", "222");
jedis.sadd("series number", "333");
Set<String> myRedisSet = jedis.smembers("series number");
Iterator<String> setIterator = myRedisSet.iterator();
while (setIterator.hasNext()) {
String element = setIterator.next();
System.out.println(element);
}
jedis.srem("series number", "333");
int size = jedis.smembers("series number").size();
System.out.println("size = " + size);

// hash
System.out.println("----------hash----------");
jedis.hset("student1", "name", "Kim");
jedis.hset("student1", "age", "12");
Map<String, String> map1 = new HashMap<>();
map1.put("telephone", "13512221555");
map1.put("email", "Kim@qq.com");
jedis.hset("student1", map1);
String student1Email = jedis.hget("student1", "email");
System.out.println("student1Email = " + student1Email);

System.out.println();
jedis.hset("student2","name", "Peter");
Map<String, String> map2 = new HashMap<>();
map2.put( "age", "15");
map2.put("telephone", "13316161818");
map2.put("address", "city");
map2.put("email", "Peter@qq.com");
jedis.hmset("student2", map2);
List<String> infoStudent2 = jedis.hmget("student2", "name", "age", "telephone", "address", "email");
for (String item: infoStudent2) {
System.out.println(item);
}

// zset
System.out.println("----------zset----------");
jedis.zadd("class", 10, "a");
jedis.zadd("class", 30, "c");
jedis.zadd("class", 40, "d");
jedis.zadd("class", 20, "b");
Set<String> redisZset = jedis.zrange("class", 0 ,-1);
Iterator<String> zsetIterator = redisZset.iterator();
while (zsetIterator.hasNext()) {
System.out.println(zsetIterator.next());
}

// 关闭redis连接
jedis.close();

}
}

output:

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
----------key----------
myRedisList
series number
level
k1
student2
k2
student1
name
k3
weight
class
age
----------String----------
middle-class
[v1, v2, v3]
----------list----------
e6
e5
e4
e3
e2
e1
----------set----------
111
222
333
size = 2
----------hash----------
student1Email = Kim@qq.com

Peter
15
13316161818
city
Peter@qq.com
----------zset----------
a
b
c
d

2.3 事务提交

exec:

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
package com.redis.demo;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.Response;
import redis.clients.jedis.Transaction;

public class RedisTransaction {

public static void main(String[] args) {

Jedis jedis = new Jedis("192.168.88.128", 9001);
jedis.auth("123456");

Transaction transaction = jedis.multi();
transaction.rpush("myList", "a");
transaction.rpush("myList", "b");
transaction.rpush("myList", "c");
transaction.exec();

System.out.println(jedis.lrange("myList", 0,-1));
// [a, b, c]

jedis.close();
}
}

discard:

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
package com.redis.demo;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.Response;
import redis.clients.jedis.Transaction;

public class RedisTransaction {

public static void main(String[] args) {

Jedis jedis = new Jedis("192.168.88.128", 9001);
jedis.auth("123456");

Transaction transaction = jedis.multi();
transaction.rpush("myList", "elem1");
transaction.rpush("myList", "elem2");
transaction.rpush("myList", "elem3");
transaction.discard();

System.out.println(jedis.lrange("myList", 0,-1));
// [a, b, c]

jedis.close();

}
}

watch:

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
package com.redis.demo;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.Response;
import redis.clients.jedis.Transaction;

public class RedisTransaction {

public static void main(String[] args) {

Jedis jedis = new Jedis("192.168.88.128", 9001);
jedis.auth("123456");

jedis.watch("myList");
jedis.rpush("myList", "num1");

Transaction transaction = jedis.multi();
transaction.rpush("myList", "num2");
transaction.rpush("myList", "num3");
transaction.exec();

System.out.println(jedis.lrange("myList", 0,-1));
// [a, b, c, num1]

jedis.close();

}
}

unwatch:

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
package com.redis.demo;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.Response;
import redis.clients.jedis.Transaction;

public class RedisTransaction {

public static void main(String[] args) {

Jedis jedis = new Jedis("192.168.88.128", 9001);
jedis.auth("123456");

jedis.watch("myList");
jedis.rpush("myList", "num2");
jedis.unwatch();

Transaction transaction = jedis.multi();
transaction.rpush("myList", "num3");
transaction.exec();

System.out.println(jedis.lrange("myList", 0,-1));
// [a, b, c, num1, num2, num3]

jedis.close();

}
}

2.4 主从复制

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package com.redis.demo;

import redis.clients.jedis.Jedis;

public class RedisDuplication {

public static void main(String[] args) throws InterruptedException {
Jedis jedisMaster = new Jedis("192.168.88.128", 6379);
Jedis jedisSlave = new Jedis("192.168.88.128", 7000);

jedisSlave.slaveof("192.168.88.128", 6379);
jedisMaster.set("number", "100");
Thread.sleep(2*1000);
System.out.println(jedisSlave.get("number"));
// 100

jedisMaster.close();
jedisSlave.close();
}
}
1
jedisSlave.set("number", "200");

会抛出以下异常:

1
2
3
4
5
6
7
8
Exception in thread "main" redis.clients.jedis.exceptions.JedisDataException: READONLY You can't write against a read only replica.
at redis.clients.jedis.Protocol.processError(Protocol.java:132)
at redis.clients.jedis.Protocol.process(Protocol.java:166)
at redis.clients.jedis.Protocol.read(Protocol.java:220)
at redis.clients.jedis.Connection.readProtocolWithCheckingBroken(Connection.java:278)
at redis.clients.jedis.Connection.getStatusCodeReply(Connection.java:196)
at redis.clients.jedis.Jedis.set(Jedis.java:154)
at com.redis.demo.RedisDuplication.main(RedisDuplication.java:24)

2.6 集群连接

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
[root@localhost redis_cluster]# ps -ef | grep redis
root 1703 1 0 20:57 ? 00:00:06 ./redis-server 192.168.168.130:7001 [cluster]
root 1709 1 0 20:57 ? 00:00:06 ./redis-server 192.168.168.130:7002 [cluster]
root 1715 1 0 20:58 ? 00:00:05 ./redis-server 192.168.168.130:7003 [cluster]
root 1721 1 0 20:58 ? 00:00:05 ./redis-server 192.168.168.130:7004 [cluster]
root 1730 1 0 20:58 ? 00:00:06 ./redis-server 192.168.168.130:7005 [cluster]
root 1740 1 0 20:58 ? 00:00:06 ./redis-server 192.168.168.130:7006 [cluster]
root 1872 1676 0 21:28 pts/0 00:00:00 grep --color=auto redis
[root@localhost redis_cluster]#
[root@localhost redis_cluster]# ./redis-cli -c -h 192.168.168.130 -p 7001
192.168.168.130:7001> cluster info
cluster_state:ok
cluster_slots_assigned:16384
cluster_slots_ok:16384
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:6
cluster_size:3
cluster_current_epoch:6
cluster_my_epoch:1
cluster_stats_messages_ping_sent:3201
cluster_stats_messages_pong_sent:3230
cluster_stats_messages_fail_sent:2
cluster_stats_messages_sent:6433
cluster_stats_messages_ping_received:3230
cluster_stats_messages_pong_received:3196
cluster_stats_messages_fail_received:7
cluster_stats_messages_received:6433
192.168.168.130:7001>
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
package com.redis.demo;

import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.JedisCluster;

import java.util.HashSet;
import java.util.Set;

public class RedisCluster {

public static final String HOST = "192.168.168.130";

public static void main(String[] args) {
Set<HostAndPort> nodes = new HashSet<>();

HostAndPort node1 = new HostAndPort(HOST, 7001);
HostAndPort node2 = new HostAndPort(HOST, 7002);
HostAndPort node3 = new HostAndPort(HOST, 7003);
HostAndPort node4 = new HostAndPort(HOST, 7004);
HostAndPort node5 = new HostAndPort(HOST, 7005);
HostAndPort node6 = new HostAndPort(HOST, 7006);

nodes.add(node1);
nodes.add(node2);
nodes.add(node3);
nodes.add(node4);
nodes.add(node5);
nodes.add(node6);

JedisCluster jedisCluster = new JedisCluster(nodes);
jedisCluster.set("number", "500");
String number = jedisCluster.get("number");
System.out.println(number);

// close redis connection
jedisCluster.close();

}
}

3. JedisPool

3.1 为什么要使用JedisPool

  • 1.获取Jedis实例需要从JedisPool中获取
  • 2.用完Jedis实例需要返还给JedisPool
  • 3.如果Jedis在使用过程中出错,则也需要还给JedisPool

3.2 案例及代码

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
package com.redis.demo;

import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

public class JedisPoolUtil {
// 被volatile修饰的变量不会被本地线程缓存,对该变量的读写都是直接操作共享内存。
private static volatile JedisPool jedisPool = null;

private JedisPoolUtil() {

}

public static JedisPool getJedisPoolInstance() {
if (jedisPool == null) {
synchronized (JedisPoolUtil.class) {
if (jedisPool == null) {
JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
jedisPoolConfig.setMaxTotal(100);
jedisPoolConfig.setMaxIdle(32);
jedisPoolConfig.setMinIdle(10);
jedisPoolConfig.setMaxWaitMillis(30 * 1000);
jedisPoolConfig.setTestOnBorrow(true);

jedisPool = new JedisPool(jedisPoolConfig, "192.168.168.130", 6379);

}
}
}
return jedisPool;
}

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package com.redis.demo;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

public class JedisPoolTest {
public static void main(String[] args) {

try {
JedisPool jedisPool = JedisPoolUtil.getJedisPoolInstance();
Jedis jedis = jedisPool.getResource();
jedis.set("number", "1000");
String number = jedis.get("number");
System.out.println(number);
jedis.close();
}
catch (Exception e) {
e.printStackTrace();
}

}
}

3.3 配置总结all

JedisPool的配置参数大部分是由JedisPoolConfig的对应项来赋值的。

  • maxTotal/maxActive: 控制一个pool可分配多少个jedis实例,通过pool.getResource()来获取;如果赋值为-1,则表示不限制;如果pool已经分配了maxActive个jedis实例,则此时pool的状态为exhausted。

  • maxIdle:控制一个pool最多有多少个状态为idle(空闲)的jedis实例

  • whenExhaustedAction: 表示当pool中的jedis实例都被allocated完时,pool要采取的操作;默认有三种。

WHEN_EXHAUSTED_FAIL –> 表示无jedis实例时,直接抛出NoSuchElementException;

WHEN_EXHAUSTED_BLOCK –> 则表示阻塞住,或者达到maxWait时抛出JedisConnectionException;

WHEN_EXHAUSTED_GROW –> 则表示新建一个jedis实例,也就说设置的maxActive无用;

  • setMaxWaitMillis/maxWait: 表示当borrow一个jedis实例时,最大的等待时间,如果超过等待时间,则直接抛JedisConnectionException;

  • testOnBorrow: 获得一个jedis实例的时候是否检查连接可用性(ping());如果为true,则得到的jedis实例均是可用的

  • testOnReturn: return 一个jedis实例给pool时,是否检查连接可用性(ping());

  • testWhileIdle: 如果为true,表示有一个idle object evitor线程对idle object进行扫描,如果validate失败,此object会被从pool中drop掉;这一项只有在timeBetweenEvictionRunsMillis大于0时才有意义;

  • timeBetweenEvictionRunsMillis: 表示idle object evitor两次扫描之间要sleep的毫秒数;

  • numTestsPerEvictionRun: 表示idle object evitor每次扫描的最多的对象数;

  • minEvictableIdleTimeMillis: 表示一个对象至少停留在idle状态的最短时间,然后才能被idle object evitor扫描并驱逐;这一项只有在timeBetweenEvictionRunsMillis大于0时才有意义;

  • softMinEvictableIdleTimeMillis: 在minEvictableIdleTimeMillis基础上,加入了至少minIdle个对象已经在pool里面了。如果为-1,evicted不会根据idle time驱逐任何对象。如果minEvictableIdleTimeMillis>0,则此项设置无意义,且只有在timeBetweenEvictionRunsMillis大于0时才有意义;

  • lifo: borrowObject返回对象时,是采用DEFAULT_LIFO(last in first out,即类似cache的最频繁使用队列),如果为False,则表示FIFO队列;

其中JedisPoolConfig对一些参数的默认设置如下:

  • testWhileIdle=true

  • minEvictableIdleTimeMills=60000

  • timeBetweenEvictionRunsMillis=30000

  • numTestsPerEvictionRun=-1

    4. Redis存储Object

可以将Java Object转换为json字符串,然后存入Redis,需要使用对象时,从Redis中取得json字符串,然后转换为Java Object

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
package com.redis.demo;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

public class JedisPoolTest {
public static void main(String[] args) {

try {
JedisPool jedisPool = JedisPoolUtil.getJedisPoolInstance();
Jedis jedis = jedisPool.getResource();

User user = new User();
user.setId(10);
user.setName("Peter");
user.setAge(15);
user.setEmail("Peter@qq.com");

String userJSONStr = JSON.toJSONString(user);
jedis.set("user", userJSONStr);

String userRedisStr = jedis.get("user");
User userRedisObject = JSONObject.parseObject(userRedisStr, User.class);
System.out.println(userRedisObject.getName() + " " + userRedisObject.getEmail());

jedis.close();

}
catch (Exception e) {
e.printStackTrace();
}

}
}