├── .gitignore
├── pom.xml
└── src
├── main
├── java
│ └── com
│ │ └── zzy
│ │ └── util
│ │ ├── hash
│ │ ├── HashRedisConfig.java
│ │ ├── HashRedisExecutor.java
│ │ └── HashRedisUtil.java
│ │ └── sharded
│ │ ├── ShardedRedisExecutor.java
│ │ ├── ShardedRedisUtil.java
│ │ └── SharedRedisConfig.java
└── resources
│ ├── hashRedis.properties
│ ├── logback.xml
│ └── shardedRedis.properties
└── test
└── java
└── com
└── zzy
└── util
├── HashRedisUtilTest.java
└── ShardedRedisUtilTest.java
/.gitignore:
--------------------------------------------------------------------------------
1 | *.metadata
2 | */bin/*
3 | */bin/
4 | */tmp/**
5 | *.tmp
6 | *.bak
7 | *.swp
8 | *~.nib
9 | *.classpath
10 | *.project
11 | *.settings/*
12 | *.settings/
13 | */target/*
14 | */target/
15 | target
16 | *.class
17 | *.iml
18 | .idea
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
3 | 4.0.0
4 | zzy
5 | redisUtil
6 | 0.0.1-SNAPSHOT
7 |
8 |
9 | 1.7
10 | 2.8.0
11 | 1.7.12
12 | 4.12
13 | 1.1.3
14 | 2.6
15 | ${java.version}
16 | ${java.version}
17 |
18 |
19 |
20 |
21 | redis.clients
22 | jedis
23 | ${redis.version}
24 |
25 |
26 | commons-lang
27 | commons-lang
28 | ${commons-lang.version}
29 |
30 |
31 | junit
32 | junit
33 | ${junit.version}
34 | test
35 |
36 |
37 |
38 | ch.qos.logback
39 | logback-core
40 | ${logback.version}
41 |
42 |
43 | ch.qos.logback
44 | logback-classic
45 | ${logback.version}
46 |
47 |
48 | org.slf4j
49 | jcl-over-slf4j
50 | ${slf4j.version}
51 |
52 |
53 | org.slf4j
54 | log4j-over-slf4j
55 | ${slf4j.version}
56 |
57 |
58 |
59 | ${project.artifactId}
60 |
61 |
62 | org.apache.maven.plugins
63 | maven-compiler-plugin
64 |
65 | ${java.version}
66 | ${java.version}
67 | ${project.build.sourceEncoding}
68 |
69 |
70 |
71 |
72 |
--------------------------------------------------------------------------------
/src/main/java/com/zzy/util/hash/HashRedisConfig.java:
--------------------------------------------------------------------------------
1 | package com.zzy.util.hash;
2 |
3 | import java.util.ResourceBundle;
4 |
5 | /**
6 | * 读取redis配置
7 | *
8 | * @author zhengzhiyuan
9 | * @since May 20, 2016
10 | */
11 | public class HashRedisConfig {
12 | private static final String DEFAULT_REDIS_PROPERTIES = "hashRedis";
13 | private static ResourceBundle REDIS_CONFIG = ResourceBundle.getBundle(DEFAULT_REDIS_PROPERTIES);
14 |
15 | public static String getConfigProperty(String key) {
16 | return REDIS_CONFIG.getString(key);
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/main/java/com/zzy/util/hash/HashRedisExecutor.java:
--------------------------------------------------------------------------------
1 | package com.zzy.util.hash;
2 |
3 | import redis.clients.jedis.Jedis;
4 |
5 | // redis具体逻辑接口
6 | public interface HashRedisExecutor {
7 | T execute(Jedis jedis);
8 | }
9 |
--------------------------------------------------------------------------------
/src/main/java/com/zzy/util/hash/HashRedisUtil.java:
--------------------------------------------------------------------------------
1 | package com.zzy.util.hash;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 | import java.util.Map;
6 |
7 | import org.apache.commons.lang.math.NumberUtils;
8 | import org.slf4j.Logger;
9 | import org.slf4j.LoggerFactory;
10 |
11 | import redis.clients.jedis.Jedis;
12 | import redis.clients.jedis.JedisPool;
13 | import redis.clients.jedis.JedisPoolConfig;
14 |
15 | /**
16 | * 对redis pool 进行hash分片
17 | *
18 | * @author zhengzhiyuan
19 | * @since May 20, 2016
20 | */
21 | public class HashRedisUtil {
22 | private static final Logger LOGGER = LoggerFactory.getLogger(HashRedisUtil.class);
23 |
24 | private static final String DEFAULT_REDIS_SEPARATOR = ";";
25 |
26 | private static final String HOST_PORT_SEPARATOR = ":";
27 |
28 | private JedisPool[] jedisPools = new JedisPool[0];
29 |
30 | private static final HashRedisUtil INSTANCE = new HashRedisUtil();
31 |
32 | private HashRedisUtil() {
33 | initPool();
34 | }
35 |
36 | private void initPool() {
37 |
38 | // 操作超时时间,默认2秒
39 | int timeout = NumberUtils.toInt(HashRedisConfig.getConfigProperty("redis.timeout"), 2000);
40 | // jedis池最大连接数总数,默认8
41 | int maxTotal = NumberUtils.toInt(HashRedisConfig.getConfigProperty("redis.jedisPoolConfig.maxTotal"), 8);
42 | // jedis池最大空闲连接数,默认8
43 | int maxIdle = NumberUtils.toInt(HashRedisConfig.getConfigProperty("redis.jedisPoolConfig.maxIdle"), 8);
44 | // jedis池最少空闲连接数
45 | int minIdle = NumberUtils.toInt(HashRedisConfig.getConfigProperty("redis.jedisPoolConfig.minIdle"), 0);
46 | // jedis池没有对象返回时,最大等待时间单位为毫秒
47 | long maxWaitMillis = NumberUtils.toLong(HashRedisConfig.getConfigProperty("redis.jedisPoolConfig.maxWaitTime"), -1);
48 | // 在borrow一个jedis实例时,是否提前进行validate操作
49 | boolean testOnBorrow = Boolean.parseBoolean(HashRedisConfig.getConfigProperty("redis.jedisPoolConfig.testOnBorrow"));
50 |
51 | // 设置jedis连接池配置
52 | JedisPoolConfig poolConfig = new JedisPoolConfig();
53 | poolConfig.setMaxTotal(maxTotal);
54 | poolConfig.setMaxIdle(maxIdle);
55 | poolConfig.setMinIdle(minIdle);
56 | poolConfig.setMaxWaitMillis(maxWaitMillis);
57 | poolConfig.setTestOnBorrow(testOnBorrow);
58 |
59 | // 取得redis的url
60 | String redisUrls = HashRedisConfig.getConfigProperty("redis.jedisPoolConfig.urls");
61 | if (redisUrls == null || redisUrls.trim().isEmpty()) {
62 | throw new IllegalStateException("the urls of redis is not configured");
63 | }
64 | LOGGER.info("the urls of redis is {}", redisUrls);
65 |
66 | // 生成连接池
67 | List jedisPoolList = new ArrayList();
68 | for (String redisUrl : redisUrls.split(DEFAULT_REDIS_SEPARATOR)) {
69 | String[] redisUrlInfo = redisUrl.split(HOST_PORT_SEPARATOR);
70 | jedisPoolList.add(new JedisPool(poolConfig, redisUrlInfo[0], Integer.parseInt(redisUrlInfo[1]), timeout));
71 | }
72 |
73 | jedisPools = jedisPoolList.toArray(jedisPools);
74 | }
75 |
76 | public static HashRedisUtil getInstance() {
77 | return INSTANCE;
78 | }
79 |
80 | /**
81 | * 实现jedis连接的获取和释放,具体的redis业务逻辑由executor实现
82 | *
83 | * @param executor RedisExecutor接口的实现类
84 | * @return
85 | */
86 | public T execute(String key, HashRedisExecutor executor) {
87 | Jedis jedis = jedisPools[(0x7FFFFFFF & key.hashCode()) % jedisPools.length].getResource();
88 | T result = null;
89 | try {
90 | result = executor.execute(jedis);
91 | } finally {
92 | if (jedis != null) {
93 | jedis.close();
94 | }
95 | }
96 | return result;
97 | }
98 |
99 | public String set(final String key, final String value) {
100 | return execute(key, new HashRedisExecutor() {
101 | @Override
102 | public String execute(Jedis jedis) {
103 | return jedis.set(key, value);
104 | }
105 | });
106 | }
107 |
108 | public String set(final String key, final String value, final String nxxx, final String expx, final long time) {
109 | return execute(key, new HashRedisExecutor() {
110 | @Override
111 | public String execute(Jedis jedis) {
112 | return jedis.set(key, value, nxxx, expx, time);
113 | }
114 | });
115 | }
116 |
117 | public String get(final String key) {
118 | return execute(key, new HashRedisExecutor() {
119 | @Override
120 | public String execute(Jedis jedis) {
121 | return jedis.get(key);
122 | }
123 | });
124 | }
125 |
126 | public Boolean exists(final String key) {
127 | return execute(key, new HashRedisExecutor() {
128 | @Override
129 | public Boolean execute(Jedis jedis) {
130 | return jedis.exists(key);
131 | }
132 | });
133 | }
134 |
135 | public Long setnx(final String key, final String value) {
136 | return execute(key, new HashRedisExecutor() {
137 | @Override
138 | public Long execute(Jedis jedis) {
139 | return jedis.setnx(key, value);
140 | }
141 | });
142 | }
143 |
144 | public String setex(final String key, final int seconds, final String value) {
145 | return execute(key, new HashRedisExecutor() {
146 | @Override
147 | public String execute(Jedis jedis) {
148 | return jedis.setex(key, seconds, value);
149 | }
150 | });
151 | }
152 |
153 | public Long expire(final String key, final int seconds) {
154 | return execute(key, new HashRedisExecutor() {
155 | @Override
156 | public Long execute(Jedis jedis) {
157 | return jedis.expire(key, seconds);
158 | }
159 | });
160 | }
161 |
162 | public Long incr(final String key) {
163 | return execute(key, new HashRedisExecutor() {
164 | @Override
165 | public Long execute(Jedis jedis) {
166 | return jedis.incr(key);
167 | }
168 | });
169 | }
170 |
171 | public Long decr(final String key) {
172 | return execute(key, new HashRedisExecutor() {
173 | @Override
174 | public Long execute(Jedis jedis) {
175 | return jedis.decr(key);
176 | }
177 | });
178 | }
179 |
180 | public Long hset(final String key, final String field, final String value) {
181 | return execute(key, new HashRedisExecutor() {
182 | @Override
183 | public Long execute(Jedis jedis) {
184 | return jedis.hset(key, field, value);
185 | }
186 | });
187 | }
188 |
189 | public String hget(final String key, final String field) {
190 | return execute(key, new HashRedisExecutor() {
191 | @Override
192 | public String execute(Jedis jedis) {
193 | return jedis.hget(key, field);
194 | }
195 | });
196 | }
197 |
198 | public String hmset(final String key, final Map hash) {
199 | return execute(key, new HashRedisExecutor() {
200 | @Override
201 | public String execute(Jedis jedis) {
202 | return jedis.hmset(key, hash);
203 | }
204 | });
205 | }
206 |
207 | public List hmget(final String key, final String... fields) {
208 | return execute(key, new HashRedisExecutor>() {
209 | @Override
210 | public List execute(Jedis jedis) {
211 | return jedis.hmget(key, fields);
212 | }
213 | });
214 | }
215 |
216 | public Long del(final String key) {
217 | return execute(key, new HashRedisExecutor() {
218 | @Override
219 | public Long execute(Jedis jedis) {
220 | return jedis.del(key);
221 | }
222 | });
223 | }
224 |
225 | public Map hgetAll(final String key) {
226 | return execute(key, new HashRedisExecutor