Jedis,lettuce,RedisTemplate,Redission区别
1.Jedis:
Redis官方推荐使用Jedis操作Redis,Jedis的方法和Redis的指令一一对应。
Jedis和lettuce都是可以操作redis的平台
使用时:
导包
-
<dependency>
-
<groupId>redis.clients</groupId>
-
<artifactId>jedis</artifactId>
-
</dependency>
创建工具类
-
public class JedisUtil {
-
-
private static final JedisPool jedisPool;
-
-
static {
-
//设置基本属性
-
GenericObjectPoolConfig<Jedis> poolConfig = new JedisPoolConfig();
-
//最大连接数
-
poolConfig.setMaxTotal(50);
-
//最大空闲数
-
poolConfig.setMaxIdle(10);
-
-
jedisPool = new JedisPool(poolConfig, "XXX", 6379, 2000, "XXX");
-
}
-
-
public static Jedis getJedis(){
-
return jedisPool.getResource();
-
}
-
-
}
测试使用:
-
/**
-
* 测试 使用封装的工具类来使用redis
-
*/
-
-
void test03(){
-
Jedis jedis = JedisUtil.getJedis();
-
jedis.lpush("lol","abc");
-
jedis.lpush("lol","def");
-
jedis.lpush("lol","ghj");
-
//弹出
-
System.out.println(jedis.lrange("lol", 0, -1));
-
}
因为Jedis采用的直连,多个线程操作是不安全的,如果想要避免,得使用jedis pool连接池 ,并且不支持异步
2.lettuce
Lettuce基于Netty的连接实例(StatefulRedisConnection),可以在多个线程间并发访问,且线程安全,满足多线程环境下的并发访问,同时它是可伸缩的设计,一个连接实例不够的情况也可以按需增加连接实例
依赖:
-
-
<dependency>
-
<groupId>io.lettuce</groupId>
-
<artifactId>lettuce-core</artifactId>
-
</dependency>
具体没咋用过
3.RedisTemplate
redistemplate是spring框架对jedis和lettuce的封装。让spring框架体系能够更加方便的接入redis的功能。
依赖:
-
<dependency>
-
<groupId>org.springframework.boot</groupId>
-
<artifactId>spring-boot-starter-data-redis</artifactId>
-
</dependency>
这个依赖包中就包括了jedis 和 lettuce的依赖
基础使用:
先配置自定义RedisTemplate 因为底层默认JDK二进制序列化 不能跨平台使用
-
-
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
-
RedisTemplate<String, Object> template = new RedisTemplate();
-
template.setConnectionFactory(redisConnectionFactory);
-
template.setKeySerializer(RedisSerializer.string());
-
template.setValueSerializer(RedisSerializer.json());
-
template.setHashKeySerializer(RedisSerializer.string());
-
template.setHashValueSerializer(RedisSerializer.json());
-
return template;
-
}
String Hash List Set Zset 基础使用:
-
/**
-
* String -- API
-
*/
-
-
void test07(){
-
//通用指令
-
//exists
-
System.out.println(redisTemplate.hasKey("a"));
-
System.out.println(redisTemplate.hasKey("b"));
-
//ttl
-
System.out.println(redisTemplate.getExpire("a", TimeUnit.SECONDS));
-
System.out.println(redisTemplate.getExpire("b", TimeUnit.SECONDS));
-
//expire
-
System.out.println(redisTemplate.expire("a", 100,TimeUnit.SECONDS));
-
System.out.println(redisTemplate.getExpire("a", TimeUnit.SECONDS));
-
redisTemplate.persist("a");
-
System.out.println(redisTemplate.getExpire("a", TimeUnit.SECONDS));
-
}
-
-
/**
-
* String -- API2
-
*/
-
-
void test08(){
-
//keys
-
ValueOperations valueOperations = redisTemplate.opsForValue();
-
valueOperations.set("abc","456");
-
-
System.out.println(redisTemplate.keys("*"));
-
//dbsize
-
System.out.println(redisTemplate.countExistingKeys(redisTemplate.keys("*")));
-
redisTemplate.delete("aaa");
-
System.out.println(redisTemplate.keys("*"));
-
System.out.println(redisTemplate.countExistingKeys(redisTemplate.keys("*")));
-
}
-
-
/**
-
* Hash --API
-
*/
-
-
void test09(){
-
HashOperations<String, Object, Object> hashOperations = redisTemplate.opsForHash();
-
//hset
-
hashOperations.put("number","NO1","金钱");
-
hashOperations.put("number","NO2","亲情");
-
hashOperations.put("number","NO3","爱情");
-
-
//hmset
-
HashMap<Object, Object> hashMap = new HashMap<>();
-
hashMap.put("number","123");
-
hashMap.put("age","25");
-
hashOperations.putAll("hmset",hashMap);
-
-
//hget
-
Object o = hashOperations.get("number", "NO1");
-
System.out.println("获取number集合中 no1-key的值:"+o);
-
-
//hkeys
-
Set<Object> number = hashOperations.keys("number");
-
System.out.println("获取number集合中的所有keys:"+number);
-
-
//hvals
-
List<Object> number1 = hashOperations.values("number");
-
System.out.println("获取number集合中的所有values:"+number1);
-
-
//hdel
-
hashOperations.delete("hmset","age");
-
//获取键值对
-
System.out.println("获取hmset的键值对"+hashOperations.entries("hmset"));
-
hashOperations.put("hmset","age",20);
-
System.out.println("获取hmset的age-value值"+hashOperations.get("hmset","age"));
-
-
//hincrby 使变量中的键以double值的大小进行自增长。
-
hashOperations.increment("hmset1","number",1);
-
System.out.println(hashOperations.get("hmset1","number"));
-
}
-
-
/**
-
* LIST --API
-
*/
-
-
void test(){
-
ListOperations<String, Object> opsForList= redisTemplate.opsForList();
-
//lpush rpush
-
opsForList.rightPushAll("rpush","a","b","c","d");
-
-
//lrange
-
System.out.println("取rpush集合中的所有值:"+opsForList.range("rpush", 0, -1));
-
-
//lpop rpop
-
/*Long size = opsForList.size("rpush");
-
for (int i = 0; i < size; i++) {
-
System.out.println("从rpush集合中弹出:"+opsForList.leftPop("rpush"));
-
}*/
-
-
Object object = null;
-
while (opsForList.leftPop("rpush") != null){
-
System.out.println("从rpush集合中弹出:"+opsForList.leftPop("rpush"));
-
}
-
-
}
-
/**
-
* Set --Api
-
*/
-
-
void test105(){
-
SetOperations<String, Object> opsForSet = redisTemplate.opsForSet();
-
//sadd
-
opsForSet.add("set1", "a","b","c","d","c","a");
-
//smembers
-
System.out.println(opsForSet.members("set1"));
-
//scard
-
System.out.println(opsForSet.size("set1"));
-
//sismember
-
System.out.println(opsForSet.isMember("set1","a"));
-
System.out.println(opsForSet.isMember("set1","x"));
-
//随机选取
-
//srandrem
-
System.out.println(opsForSet.randomMembers("set1", 3));
-
System.out.println(opsForSet.randomMembers("set1", 3));
-
System.out.println(opsForSet.randomMembers("set1", 3));
-
System.out.println(opsForSet.members("set1"));
-
System.out.println(opsForSet.pop("set1", 1));
-
System.out.println(opsForSet.pop("set1", 1));
-
System.out.println(opsForSet.members("set1"));
-
}
-
-
/**
-
* Zset --API
-
*/
-
-
void test11(){
-
ZSetOperations<String, Object> opsForZset = redisTemplate.opsForZSet();
-
//zadd
-
opsForZset.add("zset","数学",80);
-
opsForZset.add("zset","物理",70);
-
opsForZset.add("zset","英语",140);
-
System.out.println("zset中的全部key:"+opsForZset.range("zset",0,-1));
-
-
Set<ZSetOperations.TypedTuple<Object>> zset = opsForZset.rangeWithScores("zset", 0, -1);
-
for (ZSetOperations.TypedTuple<Object> o :zset) {
-
System.out.println(o.getValue());
-
System.out.println(o.getScore());
-
}
-
-
}
-
-
/**
-
* Zset --API 方式二:
-
* Arrays.asList()将数组转换为集合后,底层其实还是数组,它返回的是Arrays的一个内部类,体现了适配器模式。
-
* 传递的数组必须是对象数组,而不是基本类型。
-
*/
-
-
void test12(){
-
ZSetOperations<String, Object> opsForZSet = redisTemplate.opsForZSet();
-
Set<ZSetOperations.TypedTuple<Object>> zset2 = new HashSet<>();
-
DefaultTypedTuple<Object> t1 = new DefaultTypedTuple<>("历史", 80.0);
-
DefaultTypedTuple<Object> t2 = new DefaultTypedTuple<>("政治", 68.0);
-
DefaultTypedTuple<Object> t3 = new DefaultTypedTuple<>("地理", 90.0);
-
opsForZSet.add("zset2",new HashSet<>(Arrays.asList(t1,t2,t3)));
-
-
}
4.Redission
Redisson是一个在Redis的基础上实现的Java驻内存数据网格(In-Memory Data Grid)。它不仅提供了一系列的分布式的Java常用对象,还提供了许多分布式服务。其中包括Bitset, Set, MultiMap, SortedSet, Map, List, Queue, BlockingQueue, Deque, BlockingDeque, Semaphore, Lock, AtomicLong, CountDownLatch, Publish/Subscribe, Bloom filter, Remote service, Spring cache, Executor service, Live Object service, Scheduler service。Redisson提供了使用Redis的最简单和最便捷的方法。Redisson的宗旨是促进使用者对Redis的关注分离(Separation of Concern),从而让使用者能够将精力更集中地放在处理业务逻辑上。(官话)
暂时我用的Redission还不多 只在使用分布式锁时用了下
在一些场合中 比如在集群,多条指令,就需要分布式锁来进行控制Redis安全性
Redission依赖:
-
<dependency>
-
<groupId>org.springframework.session</groupId>
-
<artifactId>spring-session-data-redis</artifactId>
-
</dependency>
配置类:
-
/**
-
* Redisson 分布式锁
-
*/
-
-
-
public class RedissonConfiguration {
-
-
public RedissonClient redissonClient(){
-
Config config=new Config();
-
config.useSingleServer().setAddress("redis://xxx");
-
config.useSingleServer().setPassword("xxx");
-
return Redisson.create(config);
-
}
-
}
实际使用:
但是这样会使效率变低(比如秒杀)
-
/**
-
* 使用分布式锁
-
*/
-
-
public void incr2(){
-
RLock mylock = redissonClient.getLock("mylock");
-
mylock.lock();
-
//过期解锁 无需调用unlock
-
//mylock.lock(10, TimeUnit.SECONDS);
-
//尝试加锁 最多等待2秒 8s过期自动解锁
-
//boolean b = mylock.tryLock(2, 8, TimeUnit.SECONDS);
-
ValueOperations<String, Object> opsForValue = redisTemplate.opsForValue();
-
Object num = opsForValue.get("num");
-
if(num == null){
-
opsForValue.set("num","1");
-
}else{
-
int count=Integer.parseInt(num.toString());
-
count++;
-
opsForValue.set("num", count+"");
-
}
-
mylock.unlock();
-
}
在使用分布式锁时需要注意:
1.设置过期时间:当前应用加锁,如果宕机,可以正常解锁
2.解锁只能解自己的锁,不能解别人的锁:线程id
3.执行结束删除锁:判断+删除,两个指令中间可能会被打断执行,可能删除别人的锁。解决:Lua脚本:可以将多个Redis指令写成一组,一次发送,同时执行,保证原子性