背景:

一个中小型H5游戏

核心错误信息:

  (1): java.lang.ClassCastException: [B cannot be cast to java.lang.Long

  at redis.clients.jedis.Connection.getIntegerReply(Connection.java:201)
  at redis.clients.jedis.Jedis.del(Jedis.java:129) 

 

  (2):redis.clients.jedis.exceptions.JedisConnectionException: java.net.SocketException: Socket closed

  at redis.clients.jedis.Protocol.process(Protocol.java:131)
  at redis.clients.jedis.Protocol.read(Protocol.java:187)
  at redis.clients.jedis.Connection.getIntegerReply(Connection.java:201)
  at redis.clients.jedis.Jedis.del(Jedis.java:129)

贴上核心问题代码(Jedis工具类):

/**
* 获取连接池.
*
* @return 连接池实例
*/
private static JedisPool getPool() {
String key = ip + ":" + port;
JedisPool pool = null;
//这里为了提供大多数情况下线程池Map里面已经有对应ip的线程池直接返回,提高效率
if (maps.containsKey(key)) {
pool = maps.get(key);
return pool;
}
//这里的同步代码块防止多个线程同时产生多个相同的ip线程池
synchronized (JedisUtil.class) {
if (!maps.containsKey(key)) {
JedisPoolConfig config = new JedisPoolConfig();
config.setMaxTotal(maxTotal);
config.setMaxIdle(maxIdle);
config.setTestOnBorrow(true);
config.setTestOnReturn(true);
config.setMaxWaitMillis(maxWaitMillis);
config.setBlockWhenExhausted(blockWhenExhausted);
try {
if (password != null && !"".equals(password)) {
pool = new JedisPool(config, ip, port, timeout, password);
} else {
pool = new JedisPool(config, ip, port, timeout);
}
maps.put(key, pool);
} catch (Exception e) {
e.printStackTrace();
}
} else {
pool = maps.get(key);
}
}
return pool;
} /**
* 获取Redis实例.
*
* @return Redis工具类实例
*/
public Jedis getJedis() {
Jedis jedis = null;
int count = 0;
while (jedis == null && count < retryNum) {
try {
JedisPool pool = getPool();
jedis = pool.getResource();
} catch (Exception e) {
logger.error("get redis master failed!", e);
} finally {
closeJedis(jedis);
}
count++;
}
return jedis;
} /**
* 释放redis实例到连接池.
*
* @param jedis redis实例
*/
public void closeJedis(Jedis jedis) {
if (jedis != null) {
getPool().returnResource(jedis);
}
}

  

问题剖析:

  查阅了线上资料,发现是由于多线程使用了同一个Jedis实例导致的并发问题.

结果:

  一开始,我发现我调用了getJedis()获取了jedis实例并使用后没有关闭.

  于是我把关闭Jedis的操作加上去了

  结果是错误的量少了

  但还是有报错,说明这是其中一个问题.

  最后还是没能使用Jedis连接池搞定这个问题

解决办法:

  抛弃使用连接池

  每次使用Jedis都生成一个独立的实例

  每次用完以后就close()

  这样也就不存在并发的问题了

  这样做有一个潜在的问题是如果并发量达到很大值,Redis连接数被塞满的话还是会出现问题.

  一般情况下不是非常大的并发,用完就close的话,没那么容易到这个瓶颈

相关代码:

    /**
* 获取一个独立的Jedis实例
* @return jedis
*/
public Jedis getSingleJedis() {
Jedis jedis = new Jedis(ip, port, timeout);
jedis.connect();
if (StringUtils.isNotBlank(password)) {
jedis.auth(password);
}
return jedis;
}   // 关闭Jedis直接调用 jedis.close() 即可

  

Java中多线程服务中遇到的Redis并发问题?的更多相关文章

  1. WIN7中组件服务中的DCOM配置找不到Microsoft Excel应用程序的解决办法

    转自:http://blog.csdn.net/lploveme/article/details/8215265 在运行栏中输入命令:dcomcnfg,打开组件服务管理窗口,但是却发现找不到Micro ...

  2. GDAL库中WFS服务中含有中文不能获取数据的问题

    GDAL库中目前提供了对WFS服务发布的数据进行获取,目前发现对于中文的服务名称或者图层名为中文,GDAL不能正确识别.通过调试发现,其原因有下面两点: 1.输入的URL路径没有使用UTF8编码而从网 ...

  3. geoserver中WMS服务详细说明

    官方geoserver中WMS服务中几种操作的API的详细说明地址: http://docs.geoserver.org/stable/en/user/services/wms/reference.h ...

  4. Java中多线程并发体系知识点汇总

    一.多线程 1.操作系统有两个容易混淆的概念,进程和线程. 进程:一个计算机程序的运行实例,包含了需要执行的指令:有自己的独立地址空间,包含程序内容和数据:不同进程的地址空间是互相隔离的:进程拥有各种 ...

  5. 2.1多线程(java学习笔记) java中多线程的实现(附静态代理模式)

    一.多线程 首先我们要清楚程序.进程.线程的关系. 首先进程从属于程序,线程从属于进程. 程序指计算机执行操作或任务的指令集合,是一个静态的概念. 但我们实际运行程序时,并发程序因为相互制约,具有“执 ...

  6. Java 在spring cloud中使用Redis,spring boot同样适用

    1.本地安装redis服务,官网下载. 2.在开发中要使用redis,首先要启动本地redis服务,启动后页面如下: 3.在spring boot项目pom.xml文件中添加Redis需要的依赖包,可 ...

  7. 庐山真面目之十三微服务架构中如何在Docker上使用Redis缓存

    一.介绍     1.开始说明 在微服务器架构中,有一个组件是不能少的,那就是缓存组件.其实来说,缓存组件,这个叫法不是完全正确,因为除了缓存功能,它还能完成其他很多功能.我就不隐瞒了,今天我们要探讨 ...

  8. 利用Java Service Wrapper将java项目添加到windows服务中

    1.web项目,即tomcat/resin添加至window系统服务,步骤如下:第一步:找到tomcat的bin目录,如:D:\apache-tomcat-8.0.26\bin第二步:打开cmd,cd ...

  9. Java程序员面试中的多线程问题

    很多核心Java面试题来源于多线程(Multi-Threading)和集合框架(Collections Framework),理解核心线程概念时,娴熟的实际经验是必需的.这篇文章收集了Java线程方面 ...

随机推荐

  1. [转帖]十二 个经典 Linux 进程管理命令介绍

    https://www.cnblogs.com/swordxia/p/4550825.html 接了 http referer 头 没法显示图片 可以去原始blog 里面去查看.   随笔- 109  ...

  2. Django初印象之视图(view)

    一.view的初印象 一个视图函数(类),简称视图.我们发起web请求时,返回的web响应.[大家约定成俗将视图放置在项目(project)或应用程序(app)目录中的名为views.py的文件中.] ...

  3. 【数学建模】数模day13-灰色系统理论I-灰色关联与GM(1,1)预测

    接下来学习灰色系统理论. 0. 什么是灰色系统? 部分信息已知而部分信息未知的系统,我们称之为灰色系统.相应的,知道全部信息的叫白色系统,完全未知的叫黑色系统. 为什么采用灰色系统理论? 在给定信息不 ...

  4. luogu P2071 座位安排

    这个题可以被分为两部分 1.匈牙利算法(板子) 2.邻接表存图(好像这不能称为第二部分) 每一排能坐两个人,那就把一排拆成两个点, 用匈牙利算法求最大匹配 每个人都只想坐两排,说明每个人只会连四条边 ...

  5. P1962 斐波那契数列

    题面是这样的,其实斐波那契我们之前也有接触过,并不是什么太陌生的玩意,第一个想到的方法其实是用递归来做,这样的话其实是非常轻松的,but同志们你们有没有关注过这样一个鬼东西 你以为蓝题是让你切着玩的吗 ...

  6. shell 基础(二)变量

    1. shell变量的定义 1)Shell 支持以下三种定义变量的方式: variable=value variable='value' variable="value" 特点 1 ...

  7. Flink部署-standalone模式

    Flink部署-standalone模式 2018年11月30日 00:07:41 Xlucas 阅读数:74   版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.cs ...

  8. CF209C Trails and Glades

    题目链接 题意 有一个\(n\)个点\(m\)条边的无向图(可能有重边和自环)(不一定联通).问最少添加多少条边,使得可以从\(1\)号点出发,沿着每条边走一遍之后回到\(1\)号点. 思路 其实就是 ...

  9. HTML编辑器KindEditor

    KindEditor 是一套开源的在线HTML编辑器,主要用于让用户在网站上获得所见即所得编辑效果,开发人员可以用 KindEditor 把传统的多行文本输入框(textarea)替换为可视化的富文本 ...

  10. centos7项目部署

    1. 安装nginx   添加CentOS 7 Nginx yum资源库 sudo rpm -Uvh http://nginx.org/packages/centos/7/noarch/RPMS/ng ...