使用场景
1. 分布式缓存 :
原有项目使用ecache做缓存,后来由于需要搭建集群,为保持数据一致性,提高系统的性能使用redis当分布式缓存(其实个人感觉引入消息队列会好点,毕竟jvm缓存远比redis快).主要用于存储用户数据,防止在并发 注册时校验用户
注意:
如果存在bigkey且 频繁操作容易引起redis连接不够
2. 消息队列
相当于单机版的阻塞队列(BlockingQueue)
3. 分布式锁
用于 防止在集群环境下定时任务 重复执行
4. 计数
考虑到性能对部分业务的并发数做限制,维持系统稳定
数据类型(5种)
String
k/v 形式 : 可以用于计数 分布式锁(setnx)
list
队列
注意:
list 是链表结构,所有如果在头部和尾部插入数据,性能会非常高,不受链表长度的影响;但如果在链表中插入数据,性能就会越来越差。
set
去重
zset
hash
相当于java中的对象
批处理
作用: 较少网络链接和耗时
实现方案:
1. 管道(Pipeline)
Redis是一个响应式的服务,当客户端发送一个请求后,就处于阻塞状态等待Redis返回结果。这样一次命令消耗的时间就包括四个部分:请求从客户端到服务器的时间、命令排队的时间和命令真正执行时间、结果从服务器到客户端的时间,第一个和第四个消耗的时间总和称为RTT(Round Trip Time),当客户端与服务器存在网络延时时,RTT就可能会很大,这样就会导致性能问题。
管道(Pipeline)就是为了改善这个情况的,利用管道,客户端可以一次性发送多个请求而不用等待服务器的响应,待所有命令都发送完后再一次性读取服务的响应,这样可以极大的降低RTT时间从而提升性能。需要注意到是用pipeline方式打包命令发送,redis必须在处理完所有命令前先缓存起所有命令的处理结果。打包的命令越多,缓存消耗内存也越多。所以并不是打包的命令越多越好。
public void testPipelineSet() {
Jedis jedis = jedisPool.getResource();
Pipeline pipelined = jedis.pipelined();
String keyPrefix = "pipeline";
long begin = System.currentTimeMillis();
for (int i = 1; i < 10000; i++) {
String key = keyPrefix + "_" + i;
String value = String.valueOf(i);
pipelined.set(key, value);
}
pipelined.sync();
jedis.close();
long end = System.currentTimeMillis();
System.out.println("use pipeline batch set total time:" + (end - begin));
一次RTT时间,n次命令执行时间
注意:
1. 一次性不能捆绑太多
2. 极容易发生网络超时(在循环中使用大量reis连接,造成redis连接获取超时,可以增大 connectiontimeout 和sotimeout解决)
3. rediscluster中方案中可以使用
2. 原生api mset mget
一次命令,具有原子性
[性能优化](https://www.jianshu.com/p/75137d23ae4a)