十. redis java client

本文对比了三种Java Redis客户端:JDBC-Redis、JRedis 和 Jedis 的优缺点,包括性能、维护状态及使用建议。同时介绍了Spring提供的封装方案及JOhm等映射库。

    redis主页上列出的java 客户端JDBC-Redis JRedis Jedis三种,下面分别介绍三种客户端的优缺点及其他相关的工具.

 

支持redis版本性能维护推荐
JDBC-Redis not good  
JRedis1.2.n release
2.0.0 尚未release版本
fast  
Jedis2.0.0 releasefastactively developed推荐

 

JDBC-Redis

JDBC-Redis is just a JDBC wrapper for JRedis database.
If you plan on using your code with different back-ends then JDBC is a good way to go. NOTE: It is not a complete JDBC implementation and the NOSQL will bleed through.

If you are going to stay with Redis then I would suggest using the API, which will give you more flexibility. Use a DAO layer pattern to encapsulate your DB Access and down the road that is all you will need to change.

- Romain Hippeau

Redis syntax is completely different from standard SQL so using JDBC doesn't help encapsulating different back-ends as you suggest: I would have to write new queries anyway... – muriloq Jun 16 '10 at 14:00

@muriloq - but the mechanical acquiring and releasing resources is standard. – Romain Hippeau

 

 

spring wrapper

Spring provides a wrapper around both implementations(Jredis Jedis) and they're providing serialization/deserialization, amongst other things:

Person p = new Person("Joe", "Trader", 33);
template.convertAndSet("trader:1", p);
Person samePerson = template.getAndConvert("trader:1", Person.class);
Assert.assertEquals(p, samePerson);

spring nosql/cross-store

prototype implementation allowing entities to be stored in multiple types of data stores (i.e. JPA and Neo4j or JPA and Redis etc.)


JOhm

JOhm is a blazingly fast Object-Hash Mapping library for Java inspired by the awesome Ohm. The JOhm OHM is a modern-day avatar of the old ORM's like Hibernate with the difference being that we are not dealing with an RDBMS here but with a NoSQL rockstar.

homepage:https://github.com/xetorthio/johm

 

参考:
http://stackoverflow.com/questions/3047010/best-redis-library-for-java
https://github.com/xetorthio/johm

异常信息 class org.springframework.data.redis.RedisConnectionFailureException : Unexpected end of stream.; nested exception is redis.clients.jedis.exceptions.JedisConnectionException: Unexpected end of stream. 请求中的Parameter包括: Account=1001@1058 Password=c398d8bad6e96fb98e8e4c48fa5a15c6 VerifyCode= manyLogin=1 堆栈信息 org.springframework.data.redis.RedisConnectionFailureException: Unexpected end of stream.; nested exception is redis.clients.jedis.exceptions.JedisConnectionException: Unexpected end of stream. at org.springframework.data.redis.connection.jedis.JedisExceptionConverter.convert(JedisExceptionConverter.java:47) at org.springframework.data.redis.connection.jedis.JedisExceptionConverter.convert(JedisExceptionConverter.java:36) at org.springframework.data.redis.PassThroughExceptionTranslationStrategy.translate(PassThroughExceptionTranslationStrategy.java:37) at org.springframework.data.redis.FallbackExceptionTranslationStrategy.translate(FallbackExceptionTranslationStrategy.java:37) at org.springframework.data.redis.connection.jedis.JedisConnection.convertJedisAccessException(JedisConnection.java:210) at org.springframework.data.redis.connection.jedis.JedisConnection.get(JedisConnection.java:1122) at org.springframework.data.redis.core.DefaultValueOperations$1.inRedis(DefaultValueOperations.java:46) at org.springframework.data.redis.core.AbstractOperations$ValueDeserializingRedisCallback.doInRedis(AbstractOperations.java:52) at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:191) at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:153) at org.springframework.data.redis.core.AbstractOperations.execute(AbstractOperations.java:86) at org.springframework.data.redis.core.DefaultValueOperations.get(DefaultValueOperations.java:43) at com.callcenter.authentication.service.session.impl.CctShiroSessionServiceImpl.doReadSession(CctShiroSessionServiceImpl.java:68) at org.apache.shiro.session.mgt.eis.Abstr
10-21
<think>嗯,用户这次的问题很具体,是关于Spring Data Redis连接异常的排查,而且异常还和特定请求参数有关。从引用内容来看,用户显然已经做了一些功课,引用了两篇关于Redis连接异常的解决方案,但可能还没找到针对"Unexpected end of stream"这个具体问题的解决方法。 用户提到的两个异常——RedisConnectionFailureException和JedisConnectionException,本质上都是连接问题,但后者更底层。特别值得注意的是"Unexpected end of stream"这个细节,这通常意味着连接被意外中断了。结合用户给出的请求参数,我猜测可能是以下三种情况之一: 第一,请求参数中的特殊字符"@"可能触发了Redis的协议解析问题。Redis协议对特殊字符比较敏感,尤其是当这些字符出现在键名中时。比如用户参数里的"1001@1058",这个"@"符号在Redis的RESP协议中是有特殊含义的。虽然Spring Data Redis通常会自动处理转义,但如果配置不当还是可能出问题。 第二,密码字段看起来像是MD5哈希值,长度32位符合常见哈希特征。这里可能存在两个隐患:一是密码包含数字和字母可能被错误解析,二是如果redis-server配置了requirepass但客户端没配密码,或者密码错误,都会导致连接立即中断——这也解释了"end of stream"现象,因为服务端会直接关闭未认证的连接。 第三,验证码VerifyCode字段为空,而manyLogin=1表示允许多重登录。这里要特别注意redis.conf里关于maxclients的配置,是否因为大量空验证码请求导致连接数暴涨触发限制。 在解决方案上,需要分三层来排查:首先是网络层,用telnet快速验证端口可达性;然后是协议层,检查参数中的特殊字符是否需要转义;最后是应用层,确认Jedis连接池配置是否正确——特别是testOnBorrow和testOnCreate这些健康检查参数,很多"end of stream"错误都是因为连接池拿到了已经失效的连接。 用户似乎是个开发者,给出的请求参数这么详细,应该是正在调试某个认证接口。可能遇到了生产环境的问题,语气里透着着急。不过能精准提供异常名称和参数细节,说明技术水平不错,排查思路也很清晰。这类连接问题通常不难解决,但需要系统性地排除各种可能性。 对了,还要提醒用户注意Spring Boot的自动配置陷阱。如果同时存在lettuce和jedis的依赖,可能会默认使用lettuce连接池,而用户代码却用Jedis API,这种依赖冲突也会导致奇怪的连接错误... </think>以下是针对Spring Data Redis出现`RedisConnectionFailureException`和`JedisConnectionException (Unexpected end of stream)`异常的完整排查流程,特别针对含特定参数的请求场景: ### 一、核心问题定位(含请求参数场景) 1. **连接中断根源** `Unexpected end of stream`表明连接被意外终止,常见于: - 特殊字符引发协议冲突(如参数中的`@`和长哈希值) ```java // 示例请求参数触发点 String account = "1001@1058"; // "@"可能被误解析为Redis协议分隔符 String password = "c398d8bad6e96fb98e8e4c48fa5a15c6"; // 超长字符串易导致缓冲区异常 ``` - 网络层数据分包异常(MTU设置不当) - Redis服务端主动断开(客户端验证失败或命令超时) 2. **参数相关风险点** | 参数 | 风险类型 | 影响机制 | |--------------|-------------------------|------------------------------| | `Account` | 特殊字符`@` | Redis协议误解析 | | `Password` | 超长哈希值(32字符) | 缓冲区溢出/SSL分段错误 | | `VerifyCode` | 空值 | 空参数触发序列化异常 | ### 二、针对性解决方案 #### 1. 参数预处理(关键步骤) ```java // 对特殊参数进行编码处理 public String sanitizeParam(String input) { return Base64.getEncoder().encodeToString(input.getBytes()); } // 使用时: redisTemplate.opsForValue().set( sanitizeParam(account), sanitizeParam(password) ); ``` #### 2. 连接池加固配置 ```yaml spring: redis: jedis: pool: max-active: 100 # 避免高并发流断裂 test-on-borrow: true # 强制验证连接有效性 timeout: 2000 # 短超时防线程阻塞 ssl: false # 除非必要否则关闭SSL ``` #### 3. 网络层优化 ```bash # 调整系统MTU值(Linux示例) sudo ifconfig eth0 mtu 1400 # 验证Redis端口连通性 telnet your_redis_host 6379 ``` #### 4. Redis服务端检查 ```bash # 检查客户端拒绝记录 grep "CLIENT CLOSE" /var/log/redis/redis-server.log # 监控内存使用(防OOM断开连接) redis-cli info memory | grep used_memory_human ``` ### 三、特定场景处理建议 1. **空验证码问题** 在数据序列化层添加空值拦截: ```java redisTemplate.setDefaultSerializer(new RedisSerializer<String>() { @Override public byte[] serialize(String s) { if(s == null || s.isEmpty()) return "NULL".getBytes(); return s.getBytes(); } }); ``` 2. **长密码传输优化** 启用压缩传输(需双方配置): ```java @Bean public RedisConnectionFactory redisFactory() { JedisConnectionFactory factory = new JedisConnectionFactory(); factory.setUsePool(true); factory.setCompression(true); // 启用压缩 return factory; } ``` ### 四、应急恢复方案 当异常发生时立即执行: ```java try { // 业务代码 } catch (RedisConnectionFailureException ex) { // 1. 重置当前连接 redisTemplate.getConnectionFactory().getConnection().close(); // 2. 重建连接池 ((JedisConnectionFactory)redisTemplate.getConnectionFactory()).resetConnectionPool(); } ``` > **关键提示**:在含特殊参数的请求场景中,务必在预生产环境使用**Redis Monitor命令**实时观察命令解析过程: > ```bash > redis-cli monitor | grep -E "@|c398d8" > ``` --- ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值