Java使用Jedis操作Redis并发时遇到的坑记录

时间:17-04-12 栏目:Java开发 作者:kyle 评论:0 点击: 4,455 次

 

Java在使用jedis操作redis数据时,遇到坑,各种查资料解决了将近1天才实现结果。

 

坑1:

直接在Idea里面,建TestNG的Test类时,

里面的多线程代码,一直会提示报错,没有任何提示,直接就test任务结束。

解决方案:使用main建入口的方式进行测试,千万不要使用testng的@Test注解这种方式进行测试。

 

原因,估计是多线程引起的。怎么弄还不明白,只能换成main方法里面去执行多线程。

 

坑2:

多线程并发会造成冲突,会报各种错。

 

解决方法:使用JRedisPool建立线程池。

 

而且在操作时,使用synchronized把操作方法进行封装。否则依然会报错。

 

坑3:

超出线程池容量。1000个线程,会报大量的错。

 

解决方法:

JedisPoolConfig里面设置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
setMaxTotal为1000,即可以连接的最大数量。


然后并发1000个线程都可以操作Redis了。完美。

大概的代码:

public class JedisUtils {

    protected static Logger logger = LoggerFactory.getLogger(JedisUtils.class);

    //Redis服务器IP
    private static String ADDR_ARRAY = "127.0.0.1";

    //Redis的端口号
    private static int PORT = 6379;

    //访问密码
    private static String AUTH = "";

    //可用连接实例的最大数目,默认值为8;
    //如果赋值为-1,则表示不限制;如果pool已经分配了maxActive个jedis实例,则此时pool的状态为exhausted(耗尽)。
    private static int MAX_ACTIVE = 500;

    //控制一个pool最多有多少个状态为idle(空闲的)的jedis实例,默认值也是8。
    private static int MAX_IDLE = 100;

    //等待可用连接的最大时间,单位毫秒,默认值为-1,表示永不超时。如果超过等待时间,则直接抛出JedisConnectionException;
    private static int MAX_WAIT = 10 * 1000;

    private static int TIMEOUT = 10 * 1000;//超时时间

    //在borrow一个jedis实例时,是否提前进行validate操作;如果为true,则得到的jedis实例均是可用的;
    private static boolean TEST_ON_BORROW = true;

    private static JedisPool jedisPool = null;

    /**
     * 初始化Redis连接池
     */
    private static void initialPool() {
        try {
            JedisPoolConfig config = new JedisPoolConfig();
            config.setMaxTotal(MAX_ACTIVE);
            config.setMaxIdle(MAX_IDLE);
            config.setMaxWaitMillis(MAX_WAIT);

            config.setTestOnBorrow(TEST_ON_BORROW);//使用时进行扫描,确保都可用

            config.setTestWhileIdle(true);//Idle时进行连接扫描

            config.setTestOnReturn(true);//还回线程池时进行扫描
//
////表示idle object evitor两次扫描之间要sleep的毫秒数
//            config.setTimeBetweenEvictionRunsMillis(30000);
//
////表示idle object evitor每次扫描的最多的对象数
//            config.setNumTestsPerEvictionRun(10);
//
////表示一个对象至少停留在idle状态的最短时间,然后才能被idle object evitor扫描并驱逐;这一项只有在timeBetweenEvictionRunsMillis大于0时才有意义
//            config.setMinEvictableIdleTimeMillis(60000);

            if (StringUtils.isNotBlank(AUTH)) {
                jedisPool = new JedisPool(config, ADDR_ARRAY.split(",")[0], PORT, TIMEOUT, AUTH);
            } else {
                jedisPool = new JedisPool(config, ADDR_ARRAY.split(",")[0], PORT, TIMEOUT);
            }

        } catch (Exception e) {
            logger.error("First create JedisPool error : " + e);
            try {
                //如果第一个IP异常,则访问第二个IP
                JedisPoolConfig config = new JedisPoolConfig();
                config.setMaxTotal(MAX_ACTIVE);
                config.setMaxIdle(MAX_IDLE);
                config.setMaxWaitMillis(MAX_WAIT);
                config.setTestOnBorrow(TEST_ON_BORROW);
                jedisPool = new JedisPool(config, ADDR_ARRAY.split(",")[1], PORT, TIMEOUT, AUTH);
            } catch (Exception e2) {
                logger.error("Second create JedisPool error : " + e2);
            }
        }
    }

    /**
     * 在多线程环境同步初始化
     */
    private static synchronized void poolInit() {
        if (jedisPool == null) {
            initialPool();
        }
    }


    /**
     * 同步获取Jedis实例
     *
     * @return Jedis
     */
    public synchronized static Jedis getJedis() {
        if (jedisPool == null) {
            poolInit();
        }

        Jedis jedis = null;
        try {
            if (jedisPool != null) {
                jedis = jedisPool.getResource();
            }
        } catch (Exception e) {
            logger.error("Get jedis Error : " + e.getMessage(), e);
        } finally {
            returnResource(jedis);//归还到Redis池里面
        }
        return jedis;
    }

    /**
     * 释放jedis资源
     *
     * @param jedis
     */
    public static void returnResource(final Jedis jedis) {
        if (jedis != null && jedisPool != null) {
            jedisPool.returnResource(jedis);
        }
    }

    /**
     * 关闭连接池
     */
    public static void closePool() {
        if (jedisPool != null) {
            jedisPool.close();
        }
    }

    /**
     * 设置 String
     *
     * @param key
     * @param value
     */
    public synchronized static void setString(String key, String value) {
        try {
            value = StringUtils.isEmpty(value) ? "" : value;
            getJedis().set(key, value);
        } catch (Exception e) {
            logger.error("Set key error : " + e);
        }
    }

    /**
     * 设置 过期时间
     *
     * @param key
     * @param seconds 以秒为单位
     * @param value
     */
    public synchronized static void setString(String key, int seconds, String value) {
        try {
            value = StringUtils.isEmpty(value) ? "" : value;
            getJedis().setex(key, seconds, value);
        } catch (Exception e) {
            logger.error("Set keyex error : " + e);
        }
    }

    /**
     * 获取String值
     *
     * @param key
     * @return value
     */
    public synchronized static String getString(String key) {
        if (getJedis() == null || !getJedis().exists(key)) {
            return null;
        }
        return getJedis().get(key);
    }

}

 

 

 

成都SEO小五嚎2句: 本文是(成都SEO小五)辛苦弄出来的,转载成都SEO小五原创的请保留链接: Java使用Jedis操作Redis并发时遇到的坑记录,3Q

Java使用Jedis操作Redis并发时遇到的坑记录:等您坐沙发呢!

来给哥评论评论


------====== 小五公告 ======------
成都SEO小五,专注成都搜索引擎优化。
小五善长站内外优化,C#、PHP开发,中英文SEO,Google中英文和百度优化技术。欢迎群内交流。伸手党请绕路,求资源的请绕开,求问题解答的请进群内交流。开放了一个QQ交流群:160750032。加入验证时请标注任何SEO相交字眼。友情链接直接Q我,收录正常,内容大部份原创、SEO或者程序开发、网络营销、线上推广等相关行业即可。

常用工具

赞助广告

来看过哥的人