概念:

  Jedis:是Redis的Java实现客户端,提供了比较全面的Redis命令的支持,

  Redisson:实现了分布式和可扩展的Java数据结构。

  Lettuce:高级Redis客户端,用于线程安全同步,异步和响应使用,支持集群,Sentinel,管道和编码器。

优点:

  Jedis:比较全面的提供了Redis的操作特性

  Redisson:促使使用者对Redis的关注分离,提供很多分布式相关操作服务,例如,分布式锁,分布式集合,可通过Redis支持延迟队列

  Lettuce:主要在一些分布式缓存框架上使用比较多

可伸缩:

Jedis:使用阻塞的I/O,且其方法调用都是同步的,程序流需要等到sockets处理完I/O才能执行,不支持异步。Jedis客户端实例不是线程安全的,所以需要通过连接池来使用Jedis。

Redisson:基于Netty框架的事件驱动的通信层,其方法调用是异步的。Redisson的API是线程安全的,所以可以操作单个Redisson连接来完成各种操作

Lettuce:基于Netty框架的事件驱动的通信层,其方法调用是异步的。Lettuce的API是线程安全的,所以可以操作单个Lettuce连接来完成各种操作

 

结论:

建议使用:Jedis + Redisson

 

 

补充: redis 管道+操作事务-by:2021-4-16

情景再现:一个业务需多次发送redis操作时,每条命令在网络传输中的往返时延,会远远大于执行时间,这也是为什么说影响redis性能的最大难题是网络时延,而管道(pipeline)可以一次性发送多条命令并在执行完后一次性将结果返回。

管道就是减少客户端与redis的通信次数来实现降低往返延时时间,底层实现是通过队列

注意项:用管道pipeline方式打包发送命令,redis须在处理完所有命令前先缓存起所有命令的处理结果。打包的命令越多,缓存消耗内存也越多。所以并是不是打包的命令越多越好。此外,pipeline期间将“独占”当前redis连接,此期间将不能进行非“管道”类型的其他操作,直到该pipeline关闭。

pipeline不是原子性的,中间可能会存在部分失败的情况,也就是说不能保证每条命令都能执行成功,如果中间有命令出现错误,redis不会中断执行,而是直接执行下一条命令,然后将所有命令的执行结果(执行成果或者执行失败)放到列表中统一返回,如果需要每条命令都执行成功,我们在批量执行过程中需要监控执行数量和返回的成功数量是否一致。

应用场景:
有多个command需要被及时提交,而且他们对相互结果没有依赖,对命令结果也无需立即获得,那么pipeline就可以充当这种批处理的工具

Pipeline pipeline = conn.pipelined();
        for (User user : users){
            String age= "age:" + user.getId();
            pipeline.incry(age);
        }

        List<Object> response = pipeline.syncAndReturnAll();

redis简单事务

  • 开始事务——multi
  • 命令入队——在此块中可以写事务中要执行的命令
  • 执行事务——exec

为什么说redis的事务是简单事务呢?
关系型数据库具有ACID特性,redis能保证A(原子性)和I(隔离性),D(持久性)看是否有配置RDB或者AOF持久化操作,但无法保证一致性,因为redis事务不支持回滚。

事务中出现错误的两种情况

如果在EXEC指令被提交之前,Redis-server即检测到提交的某个指令存在语法错误,那么此事务将会被提前标记为DISCARD,此后事务提交也将直接被驳回;
如果在EXEC提交后,在实施数据变更时(Redis将不会预检测数据类型,比如你对一个“非数字”类型的key执行INCR操作),某条命令执行导致了ERROR,那么redis仍然不会回滚此前已经执行成功的操作,而且也不会中断ERROR之后的其他操作继续执行,这点是跟pipeline是一样的。所以对于我们开发者而言,我们需要关注事务执行后返回的结果(结果将是一个集合,按照操作提交的顺序排列,对于执行失败的操作,结果将是一个ERROR)。

事务与pipeline的区别
事务与pipeline都是不支持回滚;中间命令出现错误,不会影响前面已经执行成功的命令,也不会中断后面的命令继续执行;
事务可以实现原子性和隔离性

Redis提供实现“事务”的方式
MULTI,EXEC,DISCARD,WATCH/UNWATCH指令用来操作事务。
1) MUTIL:开启事务,此后所有的操作将会添加到当前链接的事务“操作队列”中。
2) EXEC:提交事务
3) DISCARD:取消事务,记住,此指令不是严格意义上的“事务回滚”,只是表达了“事务操作被取消”的语义,将会导致事务的操作队列中的操作不会被执行,且事务关闭。
4) WATCH/UNWATCH:“观察”,在事务开启前,可以对某个KEY注册“WATCH”,如果在事务提交后,将会首先检测“WATCH”列表中的KEY集合是否被其他客户端修改,如果任意一个KEY 被修改,都将会导致事务直接被“DISCARD”;即使事务中没有操作某个WATCH KEY,如果此KEY被外部修改,仍然会导致事务取消。事务执行成功或者被DISCARD,都将会导致WATCH KEY被“UNWATCH”,因此事务之后,你需要重新WATCH。WATCH需要在事务开启之前执行。
WATCH的实现
通过CAS操作实现乐观锁。Redis使用WATCH命令实现事务的“检查再设置”(CAS)行为。作为WATCH命令的参数的键会受到Redis的监控,Redis能够检测到它们的变化。在执行EXEC命令之前,如果Redis检测到至少有一个键被修改了,那么整个事务便会中止运行,然后EXEC命令会返回一个Null值,提醒用户事务运行失败。

Exception in thread "main" redis.clients.jedis.exceptions.JedisDataException: Cannot use Jedis when in Multi. Please use JedisTransaction instead.
	at redis.clients.jedis.BinaryJedis.checkIsInMulti(BinaryJedis.java:1637)
	at redis.clients.jedis.Jedis.exists(Jedis.java:109)
	at redisExample.MainTest.main(MainTest.java:17)


JedisPool pool = new JedisPool("192.168.109.133");
		Jedis jedis = pool.getResource();
		Transaction multi = jedis.multi();
		multi.set("t1", "t1");
		multi.set("t2", "t2");
		log(multi.exists("t1"));
		log(jedis.exists("t1"));
		multi.exec();

说明:出现该异常是由于在multi还未exec中途去使用jedis去执行 会导致失败