四 redis连接数据库
1.下载依赖jedis
<dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>2.9.0</version> </dependency>
2.连接数据库, 和redis一样的操作命令, 关闭资源
// 连接Redis
Jedis jedis = new Jedis("192.168.43.30", 6379);
// 操作Redis, jedis的操作命令和redis完全一样
jedis.set("name","coco");
String name = jedis.get("name");
System.out.println(name);
// 释放资源
jedis.close();
3. 存对象.(对象要求k,v都必须是byte[],或者都不是String)
3.1 以byte[]形式存储对象,
(1).定义的对象必须实现Serializable
@Data @AllArgsConstructor public class User implements Serializable { private int id; private String name; private Date brithday; }
(2).将k,v都转成byte[]
添加依赖spring-context, 可以利用SerializationUtil将string和object与byte[]进行转换
<dependency>
<groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.2.12.RELEASE</version> </dependency>
String key = "user"; User value = new User(1,"tony",new Date()); // 2,将key value转成byte[] byte[] key_b = key.getBytes(); byte[] value_b = SerializationUtils.serialize(value); // 3.存储 String set = jedis.set(key_b, value_b); // System.out.println(set); // 4.获取 byte[] bytes = jedis.get(key_b); User user = (User)SerializationUtils.deserialize(bytes); System.out.println(user);
3.2 以String方式存储对象
1, 添加fastjson依赖,方便将Object与string的转换
<dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.73</version> </dependency>
2. 存取,
Jedis jedis = new Jedis("192.168.43.30", 6379); // 以string的方式存对象 String key = "user"; User user = new User(2, "jim", new Date()); // 将user序列化成Json对象 String value = JSON.toJSONString(user); // 存入 jedis.set(key,value); String s = jedis.get(key); User user1 = JSON.parseObject(s, User.class); System.out.println(user1); // 释放资源 jedis.close();
五, jedis连接池
同mysql一样, 频繁的数据库创建和关闭, 严重影响性能,
jedispool的应用
// 1.创建连接池对象 JedisPool jedisPool = new JedisPool("192.168.43.30", 6379); // 2.通过连接池对象获取连接对象 Jedis jedis = jedisPool.getResource(); // 3.操作 jedis.set("name","jim"); // 4.将连接放回连接池 jedis.close();
// 1.创建连接池对象 // 1.1 自定义连接池配置
maxIdle值与maxActive值应配置的接近。 因为,当连接数超过maxIdle值后,刚刚使用完的连接(刚刚空闲下来)会立即被销毁。
而不是我想要的空闲M秒后再销毁起一个缓冲作用。这一点DBCP做的可能与你想像的不一样。
若maxIdle与maxActive相差较大,在高负载的系统中会导致频繁的创建、销毁连接,连接数在maxIdle与maxActive间快速频繁波动,这不是我想要的。
高负载系统的maxIdle值可以设置为与maxActive相同或设置为-1(-1表示不限制),让连接数量在minIdle与maxIdle间缓冲慢速波动。
看到这个我明白了因为我们的配置是maxIdle配置的值是5,而maxActive配置的值为40,这样当并发较高的时候,当连接数接近maxActive值的情况下,空闲连接数很容易超过maxIdle,很快就被连接池给主动销毁了,这样就导致了连接频繁的创建,弱化了数据库连接池的作用。
这次的性能测试然让我深刻的感受到了数据库连接池对的价值,使用得当,它能够很好地复用已有的物理连接,在高并发的场景下,减少频繁的创建和销毁物理连接,降低系统的压力。用得不好,它的价值就发挥不出来
GenericObjectPoolConfig genericObjectPoolConfig = new GenericObjectPoolConfig(); genericObjectPoolConfig.setMaxIdle(8);//最大空闲数, 这个是如何确定的个数????我得弄明白 genericObjectPoolConfig.setMaxTotal(8);//最大活跃数 genericObjectPoolConfig.setMinIdle(0); // 1.2 创建连接池对象 JedisPool jedisPool = new JedisPool(genericObjectPoolConfig,"192.168.43.30", 6379); // 2.通过连接池对象获取连接对象 Jedis jedis = jedisPool.getResource(); // 3.操作 jedis.set("name","jim"); // 4.将连接放回连接池 jedis.close();
六. redis管道操作
Redis是一种基于客户端-服务端模型以及请求/响应协议的TCP服务。这意味着通常情况下一个请求会遵循以下步骤:
- 客户端向服务端发送一个查询请求,并监听Socket返回,通常是以阻塞模式,等待服务端响应。
- 服务端处理命令,并将结果返回给客户端。
Redis 管道技术可以在服务端未响应时,客户端可以继续向服务端发送请求,并最终一次性读取所有服务端的响应。
Redis 的管道实质就是命令打包批量执行,多次网络交互减少到单次。使用管道和不使用管道时的交互过程如下:
redis的pipeline就是一个上菜的餐车,点菜完了, 从厨房用餐车将所有菜品都推出来送过来, 而不是服务生一次一个的从厨房把的菜传上来.
管道的使用:
创建管道 :Jedis pool = jedisPool.getResource(); Pipeline pipelined = pool.pipelined();
执行(用管道代替jedis): pipelined.incr("age");
查看执行结果: List<Object> objects = pipelined.syncAndReturnAll();
管道效率对比: 5w次写;增加age
// 1.创建连接池
GenericObjectPoolConfig genericObjectPoolConfig = new GenericObjectPoolConfig();
JedisPool jedisPool = new JedisPool(genericObjectPoolConfig, "192.168.43.30", 6379);
// 不使用管道
long currentTimeMillis = System.currentTimeMillis();
Jedis jedis = jedisPool.getResource();
for (int i = 0; i < 50000; i++) {
jedis.incr("age");
}
long currentTimeMillis1 = System.currentTimeMillis();
System.out.println(currentTimeMillis1 - currentTimeMillis);//结果是210
jedis.close();
// 使用管道
//1.获取资源
Jedis pool = jedisPool.getResource();
long l = System.currentTimeMillis();
//2.创建管道
Pipeline pipelined = pool.pipelined();
// 3.执行命令
for (int j = 0; j < 50000; j++) {
pipelined.incr("age");
}
List<Object> objects = pipelined.syncAndReturnAll();
long l1 = System.currentTimeMillis();
System.out.println(l1 - l); //结果是4320
// 4释放资源
jedis.close();