最近开发毕设时,使用到了redis,由于服务器是学生机配置,所以没有做redis集群处理,只是使用单例jedis做各种redis处理,但是使用这种方法确实会遇到并发问题,通过客户端jedis连接redis服务器并发写入数据时报出“redis.clients.jedis.exceptions.JedisConnectionException: java.net.SocketException: Software caused connection abort: socket write error…Caused by: java.net.SocketException: Software caused connection abort: socket write error”等异常日志,详情如下所示:
redis.clients.jedis.exceptions.JedisConnectionException: java.net.SocketException: Software caused connection abort: socket write error
[xwood-pms-publish] [pool-2-thread-1] 2017-06-05 13:31:08,246 - com.xwood.publisher.master.PublishEntityDataHandler -61998 [pool-2-thread-1] INFO com.xwood.publisher.master.PublishEntityDataHandler - 【 extract - PublishEntityDataHandler:1】 s1-2@ entityNo:447@349779 ....
at redis.clients.jedis.Protocol.sendCommand(Protocol.java:94)
at redis.clients.jedis.Protocol.sendCommand(Protocol.java:74)
at redis.clients.jedis.Connection.sendCommand(Connection.java:80)
at redis.clients.jedis.BinaryClient.set(BinaryClient.java:92)
at redis.clients.jedis.Client.set(Client.java:24)
at redis.clients.jedis.Jedis.set(Jedis.java:62)
at com.xwood.publisher.util.JedisUtil.set(JedisUtil.java:35)
at com.xwood.publisher.master.PublishEntityDataHandler.pushRemoteRedis(PublishEntityDataHandler.java:43)
at com.xwood.publisher.master.PublishEntityDataHandler.run(PublishEntityDataHandler.java:36)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:439)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
at java.util.concurrent.FutureTask.run(FutureTask.java:138)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:98)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:206)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:895)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:918)
at java.lang.Thread.run(Thread.java:662)
[xwood-pms-publish] [pool-2-thread-1] 2017-06-05 13:31:08,247 - com.xwood.publisher.master.PublishEntityDataHandler -61999 [pool-2-thread-1] INFO com.xwood.publisher.master.PublishEntityDataHandler - 【extract - PublishEntityDataHandler:1】 s1-3@ entityNo:447@349779 ....
Caused by: java.net.SocketException: Software caused connection abort: socket write error
at java.net.SocketOutputStream.socketWrite0(Native Method)
at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:92)
at java.net.SocketOutputStream.write(SocketOutputStream.java:136)
at redis.clients.util.RedisOutputStream.flushBuffer(RedisOutputStream.java:31)
at redis.clients.util.RedisOutputStream.write(RedisOutputStream.java:38)
at redis.clients.jedis.Protocol.sendCommand(Protocol.java:80)
... 16 more
之前创建jedis实例如下:
static {
jedis = new Jedis("xxx.xxx.xxx.xxx",6379,300000);
jedis.auth("chen8999958...");
}
在不同的线程中使用相同的Jedis实例会发生奇怪的错误。但是创建太多的实现也不好因为这意味着会建立很多sokcet连接,也会导致奇怪的错误发生。单一Jedis实例不是线程安全的。为了避免这些问题,可以使用JedisPool, JedisPool是一个线程安全的网络连接池。可以用JedisPool创建一些可靠Jedis实例,可以从池中拿到Jedis的实例。这种方式可以解决那些问题并且会实现高效的性能. 具体实现看如下工具类代码:
package cn.alias.shop.common.util;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisCluster;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import javax.annotation.PostConstruct;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingDeque;
/**
* Redis单机版工具类
* @author Alias.Chen
* @Date 2018/11/7 15:33
* @Function
*/
@Slf4j
public class RedisUtil {
private static ObjectMapper mapper = new ObjectMapper();
private static String systemEnv = "alias:dev:";
private static JedisPool jedisPool;
private static JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
public static String get(String key) {
try(Jedis jedis = jedisPool.getResource()) {
return jedis.get(systemEnv + key);
}
}
public static String set(String key,String value,String nxxx,String expx,long time) {
try(Jedis jedis = jedisPool.getResource()) {
return jedis.set(systemEnv+key,value,nxxx,expx,time);
}
}
public static String set(String key,String value) {
try(Jedis jedis = jedisPool.getResource()) {
return jedis.set(systemEnv+key,value);
}
}
public static String setex(String key ,int second,String value) {
try(Jedis jedis = jedisPool.getResource()) {
return jedis.setex(systemEnv+key,second,value);
}
}
public static Long setnx(String key,String value) {
try(Jedis jedis = jedisPool.getResource()) {
return jedis.setnx(systemEnv+key,value);
}
}
public static Long del(String... keys) {
try(Jedis jedis = jedisPool.getResource()) {
String[] newKeys = new String[keys.length];
for(int i = 0 ; i < newKeys.length;i++) {
newKeys[i] = systemEnv + keys[i];
}
return jedis.del(newKeys);
}
}
public static boolean exists(String key) {
try(Jedis jedis = jedisPool.getResource()) {
return jedis.exists(systemEnv + key);
}
}
public static Long expire(String key,int seconds) {
try(Jedis jedis = jedisPool.getResource()) {
return jedis.expire(systemEnv + key,seconds);
}
}
public static Long ttl(String key) {
try(Jedis jedis = jedisPool.getResource()) {
return jedis.ttl(systemEnv + key);
}
}
public static Long lpush(String key,String... value) {
try(Jedis jedis = jedisPool.getResource()) {
return jedis.lpush(systemEnv + key,value);
}
}
public static String rpop(String key) {
try(Jedis jedis = jedisPool.getResource()) {
return jedis.rpop(systemEnv + key);
}
}
public static Long hset(String key,String field,String value){
try(Jedis jedis = jedisPool.getResource()) {
return jedis.hset(systemEnv + key,field,value);
}
}
public static Long hdel(String key,String... field) {
try(Jedis jedis = jedisPool.getResource()) {
return jedis.hdel(systemEnv + key,field);
}
}
public static String hget(String key,String field) {
try(Jedis jedis = jedisPool.getResource()) {
return jedis.hget(systemEnv + key,field);
}
}
public static Map<String,String> hgetAll(String key) {
try(Jedis jedis = jedisPool.getResource()) {
return jedis.hgetAll(systemEnv + key);
}
}
public static Long incr(String key) {
try(Jedis jedis = jedisPool.getResource()) {
return jedis.incr(systemEnv + key);
}
}
private static void shutDown() {
try(Jedis jedis = jedisPool.getResource()) {
try{
jedis.close();
}catch(Exception e) {
log.error("Redis关闭错误");
}
}
}
static {
// 设置配置
jedisPoolConfig.setMaxTotal(1024);
jedisPoolConfig.setMaxIdle(100);
jedisPoolConfig.setMaxWaitMillis(100);
jedisPoolConfig.setTestOnBorrow(false);//jedis 第一次启动时,会报错
jedisPoolConfig.setTestOnReturn(true);
// 初始化JedisPool
jedisPool = new JedisPool(jedisPoolConfig, "xxxx.xxx.xxxx.xxx", 6379, 300000);
}
}