├── .gitignore ├── .project ├── .reviewboardrc ├── codeformat.xml ├── pom.xml ├── releasenotes.txt └── src ├── main └── java │ └── com │ └── yeahmobi │ └── yedis │ ├── async │ ├── AsyncOperation.java │ ├── JedisPoolExecutor.java │ ├── OperationResult.java │ └── ThreadLocalHolder.java │ ├── atomic │ ├── AtomConfig.java │ └── Yedis.java │ ├── common │ ├── ServerInfo.java │ ├── YedisException.java │ ├── YedisNetworkException.java │ └── YedisTimeoutException.java │ ├── group │ ├── ConfigChangeListener.java │ ├── DefaultConfigManager.java │ ├── GroupConfig.java │ ├── GroupYedis.java │ ├── MasterSlaveConfigManager.java │ ├── ReadMode.java │ └── ZookeeperConfigManager.java │ ├── loadbalance │ ├── LoadBalancer.java │ ├── RandomLoadBalancer.java │ └── RoundRobinLoadBalancer.java │ ├── pipeline │ ├── PipelineJedisPool.java │ ├── ShardedYedisPipeline.java │ └── YedisPipeline.java │ ├── shard │ ├── AbstractShardingStrategy.java │ ├── DummyShardingStrategy.java │ ├── HashCodeComputingStrategy.java │ ├── ShardedYedis.java │ ├── ShardingAlgorithm.java │ ├── ShardingStrategy.java │ ├── ShardingStrategyFactory.java │ └── SimpleHashingShardingStrategy.java │ └── util │ ├── RetribleExecutor.java │ └── SleepStrategy.java └── test ├── java └── com │ └── yeahmobi │ └── yedis │ ├── base │ ├── DoubleServerYedisTestBase.java │ ├── YedisBaseTest.java │ └── YedisTestBase.java │ ├── example │ ├── GroupUseCase.java │ ├── GroupUseCaseWithZK.java │ ├── PerformanceTest.java │ ├── ShardedYedisPipelineCase.java │ └── YedisCase.java │ ├── group │ ├── GroupYedisHashTest.java │ ├── GroupYedisKeyTest.java │ ├── GroupYedisListTest.java │ ├── GroupYedisSetTest.java │ ├── GroupYedisStringTest.java │ └── GroupYedisTest.java │ ├── loadbalance │ ├── RandomLoadBalancerTest.java │ └── RoundRobinLoadBalancerTest.java │ ├── shard │ ├── AbstractShardedYedisTest.java │ ├── DefaultHashCodeCoputingStrategy.java │ ├── ShardedYedisHashTest.java │ ├── ShardedYedisKeyTest.java │ ├── ShardedYedisListTest.java │ ├── ShardedYedisSetTest.java │ ├── ShardedYedisStringTest.java │ └── ShardedYedisTest.java │ └── util │ └── RetribleExecutorTest.java └── resources └── logback.xml /.gitignore: -------------------------------------------------------------------------------- 1 | # temp folder # 2 | ###################### 3 | target/ 4 | bin/ 5 | .settings/ 6 | .metadata/ 7 | lib/ 8 | classes/ 9 | genimage/ 10 | .svn/ 11 | # Compiled source # 12 | ################### 13 | .classpath 14 | *.com 15 | *.class 16 | *.dll 17 | *.exe 18 | *.o 19 | *.so 20 | 21 | # Packages # 22 | ############ 23 | # it's better to unpack these files and commit the raw source 24 | # git has its own built in compression methods 25 | *.7z 26 | *.dmg 27 | *.gz 28 | *.iso 29 | *.jar 30 | *.rar 31 | *.tar 32 | *.zip 33 | 34 | # Logs and databases # 35 | ###################### 36 | *.log 37 | 38 | # OS generated files # 39 | ###################### 40 | .DS_Store 41 | .DS_Store? 42 | ._* 43 | .Spotlight-V100 44 | .Trashes 45 | Icon? 46 | ehthumbs.db 47 | Thumbs.db 48 | 49 | # eclipse generated files # 50 | ###################### 51 | #.project 52 | #.classpath 53 | 54 | # jupiter generated files # 55 | ###################### 56 | .jupiter 57 | *.review 58 | */review/ 59 | 60 | # temp file # 61 | ###################### 62 | *~ 63 | !/lib 64 | -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | yedis 4 | NO_M2ECLIPSE_SUPPORT: Project files created with the maven-eclipse-plugin are not supported in M2Eclipse. 5 | 6 | 7 | 8 | org.eclipse.jdt.core.javabuilder 9 | 10 | 11 | 12 | org.eclipse.jdt.core.javanature 13 | 14 | -------------------------------------------------------------------------------- /.reviewboardrc: -------------------------------------------------------------------------------- 1 | REVIEWBOARD_URL = "http://rb.dy/" 2 | REPOSITORY = "platform" 3 | -------------------------------------------------------------------------------- /codeformat.xml: -------------------------------------------------------------------------------- 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 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 3 | com.yeahmobi.yedis 4 | yedis 5 | 0.4.0-beta 6 | 4.0.0 7 | yedis v${project.version} 8 | 9 | 10 | clojars.org 11 | http://clojars.org/repo 12 | 13 | 14 | 15 | 16 | yeahmobi-releases 17 | http://172.20.0.77:8081/nexus/content/repositories/releases/ 18 | 19 | 20 | 21 | 22 | ch.qos.logback 23 | logback-classic 24 | test 25 | 26 | 27 | org.slf4j 28 | slf4j-api 29 | 30 | 31 | redis.clients 32 | jedis 33 | 34 | 35 | org.apache.curator 36 | curator-framework 37 | 38 | 39 | com.alibaba 40 | fastjson 41 | 42 | 43 | com.google.guava 44 | guava 45 | 46 | 47 | redis.embedded 48 | embedded-redis 49 | test 50 | 51 | 52 | junit 53 | junit 54 | test 55 | 56 | 57 | org.easymock 58 | easymock 59 | test 60 | 61 | 62 | 63 | 64 | 65 | ch.qos.logback 66 | logback-classic 67 | 1.0.12 68 | 69 | 70 | redis.embedded 71 | embedded-redis 72 | 0.3 73 | 74 | 75 | com.google.guava 76 | guava 77 | 18.0 78 | 79 | 80 | org.easymock 81 | easymock 82 | 2.4 83 | 84 | 85 | org.easymock 86 | easymockclassextension 87 | 2.4 88 | 89 | 90 | junit 91 | junit 92 | 4.8.1 93 | 94 | 95 | org.slf4j 96 | slf4j-api 97 | 1.6.1 98 | 99 | 100 | org.slf4j 101 | slf4j-log4j12 102 | 1.6.1 103 | 104 | 105 | redis.clients 106 | jedis 107 | 2.5.2 108 | 109 | 110 | org.apache.curator 111 | curator-framework 112 | 2.6.0 113 | 114 | 115 | com.alibaba 116 | fastjson 117 | 1.1.41 118 | 119 | 120 | 121 | 122 | 123 | 124 | org.apache.maven.plugins 125 | maven-compiler-plugin 126 | 3.1 127 | 128 | 1.6 129 | 1.6 130 | UTF-8 131 | 132 | 133 | 134 | org.apache.maven.plugins 135 | maven-source-plugin 136 | 2.3 137 | 138 | 139 | 140 | jar 141 | 142 | 143 | 144 | 145 | 146 | org.apache.maven.plugins 147 | maven-resources-plugin 148 | 2.6 149 | 150 | UTF-8 151 | 152 | 153 | 154 | org.apache.maven.plugins 155 | maven-eclipse-plugin 156 | 2.9 157 | 158 | true 159 | true 160 | true 161 | 162 | 163 | 164 | org.apache.maven.plugins 165 | maven-surefire-report-plugin 166 | 2.17 167 | 168 | 169 | org.codehaus.mojo 170 | cobertura-maven-plugin 171 | 2.6 172 | 173 | 174 | org.jacoco 175 | jacoco-maven-plugin 176 | 0.6.3.201306030806 177 | 178 | 179 | 180 | prepare-agent 181 | 182 | 183 | 184 | report 185 | prepare-package 186 | 187 | report 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | org.codehaus.mojo 198 | cobertura-maven-plugin 199 | 2.6 200 | 201 | 202 | 203 | 204 | -------------------------------------------------------------------------------- /releasenotes.txt: -------------------------------------------------------------------------------- 1 | Version 0.1 (2014.09.13) 2 | 3 | 1.配置动态化 4 | 可以从 zookeeper 获取服务器列表;列表发生变化时,能自动重建新的连接,自动切换。 5 | 2.读写分离 6 | 4种读写分离策略 (默认是 SlavePreferred ) 7 | Master:写操作和读操作都访问 master。 8 | MasterPreferred:写操作访问 master;读操作访问 master,但当 master 不可用时,则访问 slave。 9 | Slave:写操作访问 master;读操作访问 slave,slave 不可用时读调用会报错。 10 | SlavePreferred:写操作访问 master;读操作访问 slave,但当 slave 都不可用时,则访问 master。 11 | 3.读库负载均衡 12 | 策略 (默认是 RoundRobin,暂不支持权重 ) 13 | RoundRobin 14 | Random 15 | 16 | Version 0.3 (2014.11.05) 17 | 1. 支持Sharding 18 | 现在只支持简单hash算法 19 | 20 | Version 0.4 (2015.03.02) 21 | 1. 支持 pipeline 22 | -------------------------------------------------------------------------------- /src/main/java/com/yeahmobi/yedis/async/AsyncOperation.java: -------------------------------------------------------------------------------- 1 | package com.yeahmobi.yedis.async; 2 | 3 | import java.util.concurrent.Callable; 4 | 5 | import redis.clients.jedis.Jedis; 6 | 7 | public abstract class AsyncOperation implements Callable> { 8 | 9 | public abstract OperationResult execute(Jedis jedis); 10 | 11 | @Override 12 | public OperationResult call() throws Exception { 13 | Jedis jedis = ThreadLocalHolder.jedisHolder.get(); 14 | return execute(jedis); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/com/yeahmobi/yedis/async/JedisPoolExecutor.java: -------------------------------------------------------------------------------- 1 | package com.yeahmobi.yedis.async; 2 | 3 | import java.util.concurrent.ExecutionException; 4 | import java.util.concurrent.Future; 5 | import java.util.concurrent.FutureTask; 6 | import java.util.concurrent.LinkedBlockingQueue; 7 | import java.util.concurrent.atomic.AtomicBoolean; 8 | import java.util.concurrent.atomic.AtomicInteger; 9 | 10 | import org.slf4j.Logger; 11 | import org.slf4j.LoggerFactory; 12 | 13 | import redis.clients.jedis.Jedis; 14 | import redis.clients.jedis.exceptions.JedisConnectionException; 15 | 16 | import com.yeahmobi.yedis.atomic.AtomConfig; 17 | import com.yeahmobi.yedis.util.SleepStrategy; 18 | 19 | public class JedisPoolExecutor { 20 | 21 | private static final Logger logger = LoggerFactory.getLogger(JedisPoolExecutor.class); 22 | 23 | private static final String nameFormat = "YedisPool(%s)-Client%d"; 24 | 25 | private final AtomicInteger count = new AtomicInteger(1); 26 | 27 | private final AtomicBoolean shutdown = new AtomicBoolean(false); 28 | 29 | private final Worker[] workers; 30 | 31 | private final AtomicInteger workerIndex = new AtomicInteger(0); 32 | 33 | private AtomConfig config; 34 | 35 | public JedisPoolExecutor(AtomConfig config) { 36 | if (config == null) { 37 | throw new IllegalArgumentException("Argument cannot be null."); 38 | } 39 | 40 | this.config = config; 41 | 42 | this.workers = new Worker[config.getThreadPoolSize()]; 43 | } 44 | 45 | public void start() { 46 | for (int i = 0; i < this.workers.length; i++) { 47 | this.workers[i] = new Worker(); 48 | this.workers[i].start(); 49 | } 50 | } 51 | 52 | public void shutdown() { 53 | if (shutdown.compareAndSet(false, true)) { 54 | for (Worker worker : workers) { 55 | worker.close(); 56 | } 57 | } 58 | } 59 | 60 | public boolean isShutdown() { 61 | return shutdown.get(); 62 | } 63 | 64 | private void checkClose() { 65 | if (shutdown.get()) { 66 | throw new IllegalStateException("It is already closed."); 67 | } 68 | } 69 | 70 | public Future> submit(AsyncOperation opr) { 71 | checkClose(); 72 | if (opr == null) throw new NullPointerException(); 73 | FutureTask> ftask = new FutureTask>(opr); 74 | 75 | // 选择一个work, task入队 76 | workers[nextIndex()].addTask(ftask); 77 | 78 | return ftask; 79 | } 80 | 81 | private int nextIndex() { 82 | return Math.abs(workerIndex.getAndIncrement() % workers.length); 83 | } 84 | 85 | @SuppressWarnings("rawtypes") 86 | private class Worker extends Thread { 87 | 88 | private LinkedBlockingQueue queue = new LinkedBlockingQueue(); 89 | 90 | private Jedis jedis; 91 | 92 | private SleepStrategy sleepStrategy = new SleepStrategy(); 93 | 94 | public Worker() { 95 | super(String.format(nameFormat, config.getHost() + ":" + config.getPort(), count.getAndIncrement())); 96 | this.setDaemon(true); 97 | } 98 | 99 | public void close() { 100 | FutureTask task; 101 | // 将queue中的 task拿出来,cancle掉 102 | while ((task = queue.poll()) != null) { 103 | task.cancel(true); 104 | } 105 | this.interrupt(); 106 | if (jedis != null) { 107 | jedis.close(); 108 | } 109 | logger.info("Closed from " + config.getHost() + ":" + config.getPort()); 110 | } 111 | 112 | public void addTask(FutureTask task) { 113 | queue.add(task); 114 | } 115 | 116 | @Override 117 | public void run() { 118 | while (!shutdown.get()) { 119 | try { 120 | checkJedis(); 121 | 122 | FutureTask task = queue.take(); 123 | if (!task.isCancelled()) { 124 | ThreadLocalHolder.jedisHolder.set(jedis); 125 | task.run(); 126 | task.get();// 尝试获取结果,以便获取task是否有异常,如果有异常,需要关闭jedis 127 | } 128 | } catch (InterruptedException e) { 129 | // 如果被中断,按逻辑会继续检查shutdown (Yedis超时cancle时也会走到此中断的逻辑) 130 | } catch (ExecutionException e) { 131 | // 此处仅仅是为了判断task是否有jedis的网络异常 132 | Throwable cause = e.getCause(); 133 | if (cause instanceof JedisConnectionException) { 134 | // 网络问题,关闭 135 | if (jedis != null) { 136 | jedis.close(); 137 | } 138 | } 139 | } catch (JedisConnectionException e) { 140 | // 创建jedis时遇到网络问题 141 | logger.error("Error when connecting to " + config.getHost() + ":" + config.getPort() 142 | + " in YedisExecutor: " + e.getMessage()); 143 | // 网络问题,关闭 144 | if (jedis != null) { 145 | jedis.close(); 146 | sleepStrategy.sleep(); 147 | } 148 | } catch (RuntimeException e) { 149 | // 遇到task运行时异常,则记log (实际上FutureTask的run方法不会抛出任何异常) 150 | logger.error("Error when task running in YedisExecutor", e); 151 | } catch (Error e) { 152 | // 遇到task运行时异常,则记log(实际上FutureTask的run方法不会抛出任何异常) 153 | logger.error("Error when task running in YedisExecutor", e); 154 | } catch (Throwable e) { 155 | // 遇到task运行时异常,则记log(实际上FutureTask的run方法不会抛出任何异常) 156 | logger.error("Error when task running in YedisExecutor", e); 157 | } finally { 158 | ThreadLocalHolder.jedisHolder.remove(); 159 | } 160 | } 161 | } 162 | 163 | private void checkJedis() { 164 | if (jedis == null || !jedis.isConnected()) { 165 | createJedis(); 166 | } 167 | } 168 | 169 | private void createJedis() { 170 | jedis = new Jedis(config.getHost(), config.getPort(), config.getSocketTimeout()); 171 | jedis.select(config.getDatabase()); 172 | logger.info("Connected to " + config.getHost() + ":" + config.getPort()); 173 | sleepStrategy.reset(); 174 | } 175 | } 176 | 177 | } 178 | -------------------------------------------------------------------------------- /src/main/java/com/yeahmobi/yedis/async/OperationResult.java: -------------------------------------------------------------------------------- 1 | package com.yeahmobi.yedis.async; 2 | 3 | public class OperationResult { 4 | 5 | private T v; 6 | 7 | public OperationResult(T v) { 8 | this.v = v; 9 | } 10 | 11 | public T getValue() { 12 | return v; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/com/yeahmobi/yedis/async/ThreadLocalHolder.java: -------------------------------------------------------------------------------- 1 | package com.yeahmobi.yedis.async; 2 | 3 | import redis.clients.jedis.Jedis; 4 | 5 | 6 | public class ThreadLocalHolder { 7 | 8 | public static final ThreadLocal jedisHolder = new ThreadLocal(); 9 | 10 | 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/com/yeahmobi/yedis/atomic/AtomConfig.java: -------------------------------------------------------------------------------- 1 | package com.yeahmobi.yedis.atomic; 2 | 3 | import redis.clients.jedis.JedisPoolConfig; 4 | 5 | import com.yeahmobi.yedis.common.ServerInfo; 6 | 7 | public class AtomConfig implements Cloneable { 8 | 9 | private static final int DEFAULT_PORT = 6379; 10 | 11 | private static final int DEFAULT_MAX_POOL_SIZE = 20; 12 | 13 | private static final int DEFAULT_MIN_IDLE = 0; 14 | 15 | private static final int DEFAULT_MAX_IDLE = -1;//unlimited 16 | 17 | private static final long DEFAULT_MAX_WAIT_MILLIS = 1000; 18 | 19 | // host和port 20 | private ServerInfo serverInfo; 21 | 22 | // 数据库 23 | private int database = 0; 24 | 25 | // redis的密码 26 | private String password; 27 | 28 | // Jedis底层connection的timeout 29 | private int socketTimeout = 100; 30 | 31 | // 控制所有Yedis操作的超时 32 | private long timeout = 100; 33 | 34 | private int threadPoolSize = 5; 35 | 36 | private String clientName; 37 | 38 | private JedisPoolConfig pipelinePoolConfig = new JedisPoolConfig(); 39 | { 40 | pipelinePoolConfig.setMaxTotal(DEFAULT_MAX_POOL_SIZE); 41 | pipelinePoolConfig.setMaxIdle(DEFAULT_MAX_IDLE); 42 | pipelinePoolConfig.setMinIdle(DEFAULT_MIN_IDLE); 43 | pipelinePoolConfig.setMaxWaitMillis(DEFAULT_MAX_WAIT_MILLIS); 44 | } 45 | 46 | public AtomConfig() { 47 | 48 | } 49 | 50 | public AtomConfig(String host) { 51 | serverInfo = new ServerInfo(); 52 | serverInfo.setHost(host); 53 | serverInfo.setPort(DEFAULT_PORT); 54 | } 55 | 56 | public AtomConfig(String host, int port) { 57 | serverInfo = new ServerInfo(); 58 | serverInfo.setHost(host); 59 | serverInfo.setPort(port); 60 | } 61 | 62 | public ServerInfo getServerInfo() { 63 | return serverInfo; 64 | } 65 | 66 | public void setServerInfo(ServerInfo serverInfo) { 67 | this.serverInfo = serverInfo; 68 | } 69 | 70 | public String getHost() { 71 | return serverInfo.getHost(); 72 | } 73 | 74 | public void setHost(String host) { 75 | serverInfo.setHost(host); 76 | } 77 | 78 | public int getPort() { 79 | return serverInfo.getPort(); 80 | } 81 | 82 | public void setPort(int port) { 83 | serverInfo.setPort(port); 84 | } 85 | 86 | public int getDatabase() { 87 | return database; 88 | } 89 | 90 | public void setDatabase(int database) { 91 | this.database = database; 92 | } 93 | 94 | public String getPassword() { 95 | return password; 96 | } 97 | 98 | public void setPassword(String password) { 99 | this.password = password; 100 | } 101 | 102 | public long getTimeout() { 103 | return timeout; 104 | } 105 | 106 | public void setTimeout(long timeout) { 107 | this.timeout = timeout; 108 | } 109 | 110 | public int getSocketTimeout() { 111 | return socketTimeout; 112 | } 113 | 114 | public void setSocketTimeout(int socketTimeout) { 115 | this.socketTimeout = socketTimeout; 116 | } 117 | 118 | public int getThreadPoolSize() { 119 | return threadPoolSize; 120 | } 121 | 122 | public void setThreadPoolSize(int threadPoolSize) { 123 | this.threadPoolSize = threadPoolSize; 124 | } 125 | 126 | public String getClientName() { 127 | return clientName; 128 | } 129 | 130 | public void setClientName(String clientName) { 131 | this.clientName = clientName; 132 | } 133 | 134 | public JedisPoolConfig getPipelinePoolConfig() { 135 | return pipelinePoolConfig; 136 | } 137 | 138 | public void setPipelinePoolConfig(JedisPoolConfig pipelinePoolConfig) { 139 | this.pipelinePoolConfig = pipelinePoolConfig; 140 | } 141 | 142 | @Override 143 | public String toString() { 144 | return "AtomConfig [serverInfo=" + serverInfo + ", database=" + database + ", password=" + password 145 | + ", socketTimeout=" + socketTimeout + ", timeout=" + timeout + ", threadPoolSize=" + threadPoolSize 146 | + ", clientName=" + clientName + ", pipelinePoolConfig=" + pipelinePoolConfig + "]"; 147 | } 148 | 149 | } 150 | -------------------------------------------------------------------------------- /src/main/java/com/yeahmobi/yedis/common/ServerInfo.java: -------------------------------------------------------------------------------- 1 | package com.yeahmobi.yedis.common; 2 | 3 | public class ServerInfo { 4 | 5 | private String host; 6 | private int port; 7 | 8 | public ServerInfo() { 9 | } 10 | 11 | public ServerInfo(String host, int port) { 12 | super(); 13 | this.host = host; 14 | this.port = port; 15 | } 16 | 17 | public String getHost() { 18 | return host; 19 | } 20 | 21 | public void setHost(String host) { 22 | this.host = host; 23 | } 24 | 25 | public int getPort() { 26 | return port; 27 | } 28 | 29 | public void setPort(int port) { 30 | this.port = port; 31 | } 32 | 33 | public String generateKey() { 34 | return host + "_" + port; 35 | } 36 | 37 | @Override 38 | public boolean equals(Object obj) { 39 | if (obj == null) { 40 | return false; 41 | } 42 | if (getClass() != obj.getClass()) { 43 | return false; 44 | } 45 | final ServerInfo other = (ServerInfo) obj; 46 | if ((this.host == null) ? (other.host != null) : !this.host.equals(other.host)) { 47 | return false; 48 | } 49 | if (this.port != other.port) { 50 | return false; 51 | } 52 | return true; 53 | } 54 | 55 | @Override 56 | public int hashCode() { 57 | int hash = 3; 58 | hash = 41 * hash + host.hashCode(); 59 | hash = 41 * hash + this.port; 60 | return hash; 61 | } 62 | 63 | @Override 64 | public String toString() { 65 | return String.format("ServerInfo [host=%s, port=%s]", host, port); 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /src/main/java/com/yeahmobi/yedis/common/YedisException.java: -------------------------------------------------------------------------------- 1 | package com.yeahmobi.yedis.common; 2 | 3 | public class YedisException extends RuntimeException { 4 | 5 | private static final long serialVersionUID = -6731964051519025372L; 6 | 7 | public YedisException() { 8 | } 9 | 10 | public YedisException(String message) { 11 | super(message); 12 | } 13 | 14 | public YedisException(String message, Throwable cause) { 15 | super(message, cause); 16 | } 17 | 18 | public YedisException(Throwable cause) { 19 | super(cause); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/yeahmobi/yedis/common/YedisNetworkException.java: -------------------------------------------------------------------------------- 1 | package com.yeahmobi.yedis.common; 2 | 3 | public class YedisNetworkException extends YedisException { 4 | 5 | private static final long serialVersionUID = 1936628372356991877L; 6 | 7 | public YedisNetworkException() { 8 | } 9 | 10 | public YedisNetworkException(String message) { 11 | super(message); 12 | } 13 | 14 | public YedisNetworkException(String message, Throwable cause) { 15 | super(message, cause); 16 | } 17 | 18 | public YedisNetworkException(Throwable cause) { 19 | super(cause); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/yeahmobi/yedis/common/YedisTimeoutException.java: -------------------------------------------------------------------------------- 1 | package com.yeahmobi.yedis.common; 2 | 3 | public class YedisTimeoutException extends YedisException { 4 | 5 | private static final long serialVersionUID = -7454647511869528468L; 6 | 7 | public YedisTimeoutException() { 8 | } 9 | 10 | public YedisTimeoutException(String message) { 11 | super(message); 12 | } 13 | 14 | public YedisTimeoutException(String message, Throwable cause) { 15 | super(message, cause); 16 | } 17 | 18 | public YedisTimeoutException(Throwable cause) { 19 | super(cause); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/yeahmobi/yedis/group/ConfigChangeListener.java: -------------------------------------------------------------------------------- 1 | package com.yeahmobi.yedis.group; 2 | 3 | public interface ConfigChangeListener { 4 | 5 | void onChanged(MasterSlaveConfigManager configManager); 6 | 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/com/yeahmobi/yedis/group/DefaultConfigManager.java: -------------------------------------------------------------------------------- 1 | package com.yeahmobi.yedis.group; 2 | 3 | import java.util.List; 4 | 5 | import com.yeahmobi.yedis.common.ServerInfo; 6 | 7 | /** 8 | * @author atell 9 | */ 10 | public class DefaultConfigManager implements MasterSlaveConfigManager { 11 | 12 | private ServerInfo writeSeverInfo; 13 | 14 | private List readSeverInfoList; 15 | 16 | public DefaultConfigManager(ServerInfo writeSeverInfo, List readSeverInfoList) { 17 | this.writeSeverInfo = writeSeverInfo; 18 | this.readSeverInfoList = readSeverInfoList; 19 | } 20 | 21 | @Override 22 | public ServerInfo getMasterServerInfo() { 23 | return this.writeSeverInfo; 24 | } 25 | 26 | @Override 27 | public List getSlaveServerInfos() { 28 | return this.readSeverInfoList; 29 | } 30 | 31 | @Override 32 | public void addListener(ConfigChangeListener listener) { 33 | } 34 | 35 | @Override 36 | public void close() { 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/com/yeahmobi/yedis/group/GroupConfig.java: -------------------------------------------------------------------------------- 1 | package com.yeahmobi.yedis.group; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import org.apache.curator.RetryPolicy; 7 | 8 | import redis.clients.jedis.JedisPoolConfig; 9 | 10 | import com.yeahmobi.yedis.atomic.AtomConfig; 11 | import com.yeahmobi.yedis.common.ServerInfo; 12 | import com.yeahmobi.yedis.common.YedisException; 13 | import com.yeahmobi.yedis.loadbalance.LoadBalancer; 14 | import com.yeahmobi.yedis.loadbalance.LoadBalancer.Type; 15 | 16 | public class GroupConfig { 17 | 18 | private static final int DEFAULT_MAX_POOL_SIZE = 20; 19 | 20 | private static final int DEFAULT_MIN_IDLE = 0; 21 | 22 | private static final int DEFAULT_MAX_IDLE = -1;//unlimited 23 | 24 | private static final long DEFAULT_MAX_WAIT_MILLIS = 1000; 25 | 26 | // 读库负载均衡 27 | private LoadBalancer.Type loadBalancerType = Type.ROUND_ROBIN; 28 | 29 | private MasterSlaveConfigManager masterSlaveConfigManager; 30 | 31 | // 数据库 32 | private int database = 0; 33 | 34 | // redis的密码 35 | private String password; 36 | 37 | // Jedis底层connection的timeout 38 | private int socketTimeout = 100; 39 | 40 | // 控制所有Yedis操作的超时 41 | private long timeout = 100; 42 | 43 | private int threadPoolSize = 5; 44 | 45 | private String clientName; 46 | 47 | private ReadMode readMode = ReadMode.SLAVEPREFERRED; 48 | 49 | private JedisPoolConfig pipelinePoolConfig = new JedisPoolConfig(); 50 | { 51 | pipelinePoolConfig.setMaxTotal(DEFAULT_MAX_POOL_SIZE); 52 | pipelinePoolConfig.setMaxIdle(DEFAULT_MAX_IDLE); 53 | pipelinePoolConfig.setMinIdle(DEFAULT_MIN_IDLE); 54 | pipelinePoolConfig.setMaxWaitMillis(DEFAULT_MAX_WAIT_MILLIS); 55 | } 56 | 57 | public GroupConfig(ServerInfo writeSeverInfo, List readSeverInfoList) { 58 | this.masterSlaveConfigManager = new DefaultConfigManager(writeSeverInfo, readSeverInfoList); 59 | } 60 | 61 | /** 62 | * 通过zookeeper获取 Master/Slave的动态配置 63 | * 64 | * @param clusterName 集群名称,对应的zookeeper的路径是 /yedis/failover/[clusterName] 65 | * @param zkUrl zookeeper的连接字符串 66 | */ 67 | public GroupConfig(String clusterName, String zkUrl) { 68 | try { 69 | this.masterSlaveConfigManager = new ZookeeperConfigManager(clusterName, zkUrl); 70 | } catch (Exception e) { 71 | throw new YedisException(e.getMessage(), e); 72 | } 73 | } 74 | 75 | /** 76 | * 通过zookeeper获取 Master/Slave的动态配置 77 | * 78 | * @param rootpath zookeeper的根路径 79 | * @param clusterName 集群名称,对应的zookeeper的路径是 [rootpath]/[clusterName] 80 | * @param zkUrl zookeeper的连接字符串 81 | */ 82 | public GroupConfig(String rootPath, String clusterName, String zkUrl) { 83 | try { 84 | this.masterSlaveConfigManager = new ZookeeperConfigManager(rootPath, clusterName, zkUrl); 85 | } catch (Exception e) { 86 | throw new YedisException(e.getMessage(), e); 87 | } 88 | } 89 | 90 | /** 91 | * 通过zookeeper获取 Master/Slave的动态配置 92 | * 93 | * @param rootpath zookeeper的根路径 94 | * @param clusterName 集群名称,对应的zookeeper的路径是 [rootpath]/[clusterName] 95 | * @param zkUrl zookeeper的连接字符串 96 | * @param sessionTimeoutMs zookeeper的会话超时 97 | * @param connectionTimeoutMs zookeeper的连接超时 98 | * @param retryPolicy zookeeper的重试策略 99 | */ 100 | public GroupConfig(String rootPath, String clusterName, String zkUrl, int sessionTimeoutMs, 101 | int connectionTimeoutMs, RetryPolicy retryPolicy) { 102 | try { 103 | this.masterSlaveConfigManager = new ZookeeperConfigManager(rootPath, clusterName, zkUrl, sessionTimeoutMs, 104 | connectionTimeoutMs, retryPolicy); 105 | } catch (Exception e) { 106 | throw new YedisException(e.getMessage(), e); 107 | } 108 | } 109 | 110 | public ServerInfo getMasterServerInfo() { 111 | return masterSlaveConfigManager.getMasterServerInfo(); 112 | } 113 | 114 | public List getSlaveServerInfoList() { 115 | return masterSlaveConfigManager.getSlaveServerInfos(); 116 | } 117 | 118 | public void addListener(ConfigChangeListener listener) { 119 | masterSlaveConfigManager.addListener(listener); 120 | } 121 | 122 | public LoadBalancer.Type getLoadBalancerType() { 123 | return loadBalancerType; 124 | } 125 | 126 | public void setLoadBalancerType(LoadBalancer.Type loadBalancerType) { 127 | this.loadBalancerType = loadBalancerType; 128 | } 129 | 130 | public int getDatabase() { 131 | return database; 132 | } 133 | 134 | public void setDatabase(int database) { 135 | this.database = database; 136 | } 137 | 138 | public MasterSlaveConfigManager getMasterSlaveConfigManager() { 139 | return masterSlaveConfigManager; 140 | } 141 | 142 | public void setMasterSlaveConfigManager(MasterSlaveConfigManager masterSlaveConfigManager) { 143 | this.masterSlaveConfigManager = masterSlaveConfigManager; 144 | } 145 | 146 | public String getPassword() { 147 | return password; 148 | } 149 | 150 | public void setPassword(String password) { 151 | this.password = password; 152 | } 153 | 154 | public int getSocketTimeout() { 155 | return socketTimeout; 156 | } 157 | 158 | public void setSocketTimeout(int socketTimeout) { 159 | this.socketTimeout = socketTimeout; 160 | } 161 | 162 | public long getTimeout() { 163 | return timeout; 164 | } 165 | 166 | public void setTimeout(long timeout) { 167 | this.timeout = timeout; 168 | } 169 | 170 | public int getThreadPoolSize() { 171 | return threadPoolSize; 172 | } 173 | 174 | public void setThreadPoolSize(int threadPoolSize) { 175 | this.threadPoolSize = threadPoolSize; 176 | } 177 | 178 | public String getClientName() { 179 | return clientName; 180 | } 181 | 182 | public void setClientName(String clientName) { 183 | this.clientName = clientName; 184 | } 185 | 186 | public ReadMode getReadMode() { 187 | return readMode; 188 | } 189 | 190 | public void setReadMode(ReadMode readMode) { 191 | this.readMode = readMode; 192 | } 193 | 194 | public List getSlaveAtomConfigs() { 195 | List serverInfos = this.getSlaveServerInfoList(); 196 | if (serverInfos != null) { 197 | List atomConfigs = new ArrayList(serverInfos.size()); 198 | for (ServerInfo serverInfo : serverInfos) { 199 | AtomConfig atomConfig = new AtomConfig(); 200 | atomConfig.setClientName(clientName); 201 | atomConfig.setDatabase(database); 202 | atomConfig.setPassword(password); 203 | atomConfig.setServerInfo(serverInfo); 204 | atomConfig.setSocketTimeout(socketTimeout); 205 | atomConfig.setThreadPoolSize(threadPoolSize); 206 | atomConfig.setTimeout(timeout); 207 | atomConfig.setPipelinePoolConfig(pipelinePoolConfig); 208 | atomConfigs.add(atomConfig); 209 | } 210 | return atomConfigs; 211 | } 212 | return null; 213 | 214 | } 215 | 216 | public AtomConfig getMasterAtomConfig() { 217 | ServerInfo serverInfo = this.getMasterServerInfo(); 218 | if (serverInfo != null) { 219 | AtomConfig atomConfig = new AtomConfig(); 220 | atomConfig.setClientName(clientName); 221 | atomConfig.setDatabase(database); 222 | atomConfig.setPassword(password); 223 | atomConfig.setServerInfo(serverInfo); 224 | atomConfig.setSocketTimeout(socketTimeout); 225 | atomConfig.setThreadPoolSize(threadPoolSize); 226 | atomConfig.setTimeout(timeout); 227 | atomConfig.setPipelinePoolConfig(pipelinePoolConfig); 228 | return atomConfig; 229 | } 230 | return null; 231 | } 232 | 233 | public JedisPoolConfig getPipelinePoolConfig() { 234 | return pipelinePoolConfig; 235 | } 236 | 237 | @Override 238 | public String toString() { 239 | return "GroupConfig [loadBalancerType=" + loadBalancerType + ", masterSlaveConfigManager=" 240 | + masterSlaveConfigManager + ", database=" + database + ", password=" + password + ", socketTimeout=" 241 | + socketTimeout + ", timeout=" + timeout + ", threadPoolSize=" + threadPoolSize + ", clientName=" 242 | + clientName + ", readMode=" + readMode + ", pipelinePoolConfig=" + pipelinePoolConfig + "]"; 243 | } 244 | 245 | } 246 | -------------------------------------------------------------------------------- /src/main/java/com/yeahmobi/yedis/group/MasterSlaveConfigManager.java: -------------------------------------------------------------------------------- 1 | package com.yeahmobi.yedis.group; 2 | 3 | import java.util.List; 4 | 5 | import com.yeahmobi.yedis.common.ServerInfo; 6 | 7 | public interface MasterSlaveConfigManager { 8 | 9 | ServerInfo getMasterServerInfo(); 10 | 11 | List getSlaveServerInfos(); 12 | 13 | void addListener(ConfigChangeListener listener); 14 | 15 | void close(); 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/yeahmobi/yedis/group/ReadMode.java: -------------------------------------------------------------------------------- 1 | package com.yeahmobi.yedis.group; 2 | 3 | public enum ReadMode { 4 | /** 5 | * Master:写操作和读操作都访问 master。 6 | */ 7 | MASTER, 8 | /** 9 | * MasterPreferred:写操作访问 master;读操作访问 master,但当 master 不可用时,则访问 slave。 10 | */ 11 | MASTERPREFERRED, 12 | /** 13 | * Slave:写操作访问 master;读操作访问 slave,slave 不可用时读调用会报错。 14 | */ 15 | SLAVE, 16 | /** 17 | * SlavePreferred:写操作访问 master;读操作访问 slave,但当 slave 都不可用时,则访问 master 18 | */ 19 | SLAVEPREFERRED; 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/com/yeahmobi/yedis/group/ZookeeperConfigManager.java: -------------------------------------------------------------------------------- 1 | package com.yeahmobi.yedis.group; 2 | 3 | import java.io.UnsupportedEncodingException; 4 | import java.util.ArrayList; 5 | import java.util.Collections; 6 | import java.util.Comparator; 7 | import java.util.Iterator; 8 | import java.util.List; 9 | 10 | import org.apache.curator.RetryPolicy; 11 | import org.apache.curator.framework.CuratorFramework; 12 | import org.apache.curator.framework.CuratorFrameworkFactory; 13 | import org.apache.curator.framework.api.CuratorWatcher; 14 | import org.apache.curator.retry.BoundedExponentialBackoffRetry; 15 | import org.apache.zookeeper.WatchedEvent; 16 | import org.slf4j.Logger; 17 | import org.slf4j.LoggerFactory; 18 | 19 | import com.alibaba.fastjson.JSON; 20 | import com.google.common.base.Splitter; 21 | import com.google.common.base.Strings; 22 | import com.google.common.base.Verify; 23 | import com.yeahmobi.yedis.common.ServerInfo; 24 | 25 | /** 26 | * @author atell 27 | */ 28 | public class ZookeeperConfigManager implements MasterSlaveConfigManager, CuratorWatcher { 29 | 30 | private final static Logger logger = LoggerFactory.getLogger(ZookeeperConfigManager.class); 31 | 32 | private static final int DEFAULT_MAX_SLEEP_TIME = 30000; 33 | private static final int DEFAULT_BASE_SLEEP_TIME = 500; 34 | 35 | private static final int DEFAULT_SESSION_TIMEOUT_MS = 60 * 1000; 36 | private static final int DEFAULT_CONNECTION_TIMEOUT_MS = 15 * 1000; 37 | 38 | private static final String NAMESPACE = "yedis/failover"; 39 | 40 | private final CuratorFramework client; 41 | 42 | private final String clusterName; 43 | 44 | private List listeners = new ArrayList(); 45 | 46 | private ServerInfo masterSeverInfo; 47 | 48 | private List slaveSeverInfos; 49 | 50 | public ZookeeperConfigManager(String rootPath, String clusterName, String zkUrl, int sessionTimeoutMs, 51 | int connectionTimeoutMs, RetryPolicy retryPolicy) throws Exception { 52 | this.clusterName = clusterName; 53 | 54 | // 构造并启动zk client 55 | if (rootPath == null) { 56 | rootPath = NAMESPACE; 57 | } 58 | this.client = CuratorFrameworkFactory.builder().connectString(zkUrl).sessionTimeoutMs(sessionTimeoutMs).connectionTimeoutMs(connectionTimeoutMs).namespace(rootPath).retryPolicy(retryPolicy).build(); 59 | client.start(); 60 | 61 | // 获取并解析failoverStr,内容如:{"master":"172.20.0.53:6379","slaves":["172.20.0.55:6379","172.20.0.56:6379"],"unavailable":[]} 62 | byte[] data = client.getData().forPath(clusterName); 63 | Failover failover = parseFailoverStr(data); 64 | this.masterSeverInfo = parseServerInfo(failover.getMaster()); 65 | this.slaveSeverInfos = parseSlaves(failover.getSlaves()); 66 | 67 | // 设置zk监听 68 | client.getData().usingWatcher(this).inBackground().forPath(clusterName); 69 | 70 | } 71 | 72 | private Failover parseFailoverStr(byte[] data) throws Exception, UnsupportedEncodingException { 73 | String failoverStr = new String(data, "UTF-8"); 74 | Failover failover = JSON.parseObject(failoverStr, Failover.class); 75 | logger.info("cluster config is:" + failoverStr); 76 | return failover; 77 | } 78 | 79 | public ZookeeperConfigManager(String clusterName, String zkUrl, int sessionTimeoutMs, int connectionTimeoutMs) 80 | throws Exception { 81 | this(null, clusterName, zkUrl, sessionTimeoutMs, connectionTimeoutMs, 82 | new BoundedExponentialBackoffRetry(DEFAULT_BASE_SLEEP_TIME, DEFAULT_MAX_SLEEP_TIME, Integer.MAX_VALUE)); 83 | } 84 | 85 | public ZookeeperConfigManager(String rootPath, String clusterName, String zkUrl, int sessionTimeoutMs, 86 | int connectionTimeoutMs) throws Exception { 87 | this(rootPath, clusterName, zkUrl, sessionTimeoutMs, connectionTimeoutMs, 88 | new BoundedExponentialBackoffRetry(DEFAULT_BASE_SLEEP_TIME, DEFAULT_MAX_SLEEP_TIME, Integer.MAX_VALUE)); 89 | } 90 | 91 | public ZookeeperConfigManager(String clusterName, String zkUrl, RetryPolicy retryPolicy) throws Exception { 92 | this(null, clusterName, zkUrl, DEFAULT_SESSION_TIMEOUT_MS, DEFAULT_CONNECTION_TIMEOUT_MS, retryPolicy); 93 | } 94 | 95 | public ZookeeperConfigManager(String rootPath, String clusterName, String zkUrl, RetryPolicy retryPolicy) 96 | throws Exception { 97 | this(rootPath, clusterName, zkUrl, DEFAULT_SESSION_TIMEOUT_MS, DEFAULT_CONNECTION_TIMEOUT_MS, retryPolicy); 98 | } 99 | 100 | public ZookeeperConfigManager(String clusterName, String zkUrl) throws Exception { 101 | this(null, clusterName, zkUrl, DEFAULT_SESSION_TIMEOUT_MS, DEFAULT_CONNECTION_TIMEOUT_MS, 102 | new BoundedExponentialBackoffRetry(DEFAULT_BASE_SLEEP_TIME, DEFAULT_MAX_SLEEP_TIME, Integer.MAX_VALUE)); 103 | } 104 | 105 | public ZookeeperConfigManager(String rootPath, String clusterName, String zkUrl) throws Exception { 106 | this(rootPath, clusterName, zkUrl, DEFAULT_SESSION_TIMEOUT_MS, DEFAULT_CONNECTION_TIMEOUT_MS, 107 | new BoundedExponentialBackoffRetry(DEFAULT_BASE_SLEEP_TIME, DEFAULT_MAX_SLEEP_TIME, Integer.MAX_VALUE)); 108 | } 109 | 110 | private List parseSlaves(List slaves) { 111 | Verify.verify(slaves != null); 112 | 113 | List list = new ArrayList(); 114 | if (slaves != null) { 115 | for (String str : slaves) { 116 | ServerInfo serverInfo = parseServerInfo(str); 117 | list.add(serverInfo); 118 | } 119 | } 120 | return list; 121 | } 122 | 123 | private ServerInfo parseServerInfo(String nodeStr) { 124 | try { 125 | Verify.verify(!Strings.isNullOrEmpty(nodeStr)); 126 | 127 | Iterable split = Splitter.on(':').split(nodeStr); 128 | Iterator iterator = split.iterator(); 129 | 130 | boolean hasNext = iterator.hasNext(); 131 | Verify.verify(hasNext); 132 | 133 | String host = iterator.next(); 134 | hasNext = iterator.hasNext(); 135 | Verify.verify(hasNext); 136 | 137 | int port = Integer.parseInt(iterator.next()); 138 | 139 | return new ServerInfo(host, port); 140 | 141 | } catch (Exception e) { 142 | throw new IllegalArgumentException("Error node string:" + nodeStr); 143 | } 144 | } 145 | 146 | @Override 147 | public ServerInfo getMasterServerInfo() { 148 | return this.masterSeverInfo; 149 | } 150 | 151 | @Override 152 | public List getSlaveServerInfos() { 153 | return this.slaveSeverInfos; 154 | } 155 | 156 | @Override 157 | public void addListener(ConfigChangeListener listener) { 158 | this.listeners.add(listener); 159 | } 160 | 161 | @Override 162 | public void close() { 163 | client.close(); 164 | } 165 | 166 | public static class Failover { 167 | 168 | private String master; 169 | private List slaves; 170 | 171 | public String getMaster() { 172 | return master; 173 | } 174 | 175 | public void setMaster(String master) { 176 | this.master = master; 177 | } 178 | 179 | public List getSlaves() { 180 | return slaves; 181 | } 182 | 183 | public void setSlaves(List slaves) { 184 | this.slaves = slaves; 185 | } 186 | 187 | } 188 | 189 | @Override 190 | public void process(WatchedEvent event) throws Exception { 191 | logger.info("Config changed."); 192 | 193 | try { 194 | // 获取最新配置 195 | ServerInfo masterSeverInfo = null; 196 | List slaveSeverInfos = null; 197 | byte[] data = client.getData().forPath(clusterName); 198 | Failover failover = parseFailoverStr(data); 199 | masterSeverInfo = parseServerInfo(failover.getMaster()); 200 | slaveSeverInfos = parseSlaves(failover.getSlaves()); 201 | 202 | // 计算是否配置发生变更 203 | boolean changed = false; 204 | if (!this.masterSeverInfo.equals(masterSeverInfo)) { 205 | this.masterSeverInfo = masterSeverInfo; 206 | changed = true; 207 | } 208 | if (!equals(this.slaveSeverInfos, slaveSeverInfos)) { 209 | this.slaveSeverInfos = slaveSeverInfos; 210 | changed = true; 211 | } 212 | 213 | // 通知listener 214 | if (changed && listeners != null && listeners.size() > 0) { 215 | for (ConfigChangeListener listener : listeners) { 216 | try { 217 | listener.onChanged(this); 218 | } catch (Exception e) { 219 | logger.error("Config changed, but error occurred when invoke this listener.", e); 220 | } 221 | } 222 | } 223 | } catch (Exception e) { 224 | logger.error("Received watch event from zookeeper, but error occurred, so nothing changed.", e); 225 | } finally { 226 | // 再次监听 227 | client.getData().usingWatcher(this).inBackground().forPath(clusterName); 228 | } 229 | 230 | } 231 | 232 | private boolean equals(List list1, List list2) { 233 | if (list1 == null && list2 == null) { 234 | return true; 235 | } else if (list1 == null || list2 == null) { 236 | return false; 237 | } else if (list1.size() != list2.size()) { 238 | return false; 239 | } 240 | 241 | Comparator comparator = new Comparator() { 242 | 243 | @Override 244 | public int compare(ServerInfo o1, ServerInfo o2) { 245 | String c1 = o1.getHost() + o1.getPort(); 246 | String c2 = o2.getHost() + o2.getPort(); 247 | return c1.compareTo(c2); 248 | } 249 | 250 | }; 251 | Collections.sort(list1, comparator); 252 | Collections.sort(list2, comparator); 253 | 254 | return list1.equals(list2); 255 | } 256 | 257 | public String getClusterName() { 258 | return clusterName; 259 | } 260 | 261 | } 262 | -------------------------------------------------------------------------------- /src/main/java/com/yeahmobi/yedis/loadbalance/LoadBalancer.java: -------------------------------------------------------------------------------- 1 | package com.yeahmobi.yedis.loadbalance; 2 | 3 | import com.yeahmobi.yedis.atomic.Yedis; 4 | 5 | /** 6 | * @author atell 7 | */ 8 | public interface LoadBalancer { 9 | 10 | Yedis route(); 11 | 12 | Type getType(); 13 | 14 | public enum Type { 15 | RANDOM, ROUND_ROBIN 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/com/yeahmobi/yedis/loadbalance/RandomLoadBalancer.java: -------------------------------------------------------------------------------- 1 | package com.yeahmobi.yedis.loadbalance; 2 | 3 | import java.util.List; 4 | import java.util.Random; 5 | 6 | import com.yeahmobi.yedis.atomic.Yedis; 7 | 8 | public class RandomLoadBalancer implements LoadBalancer { 9 | 10 | private Type type = LoadBalancer.Type.RANDOM; 11 | private List yedisList; 12 | private int listSize; 13 | 14 | private final Random random = new Random(); 15 | 16 | public RandomLoadBalancer(List yedisList) { 17 | if (yedisList == null || yedisList.size() <= 0) { 18 | throw new IllegalArgumentException("yedisList cannot be null or empty."); 19 | } 20 | this.yedisList = yedisList; 21 | this.listSize = yedisList.size(); 22 | } 23 | 24 | @Override 25 | public Yedis route() { 26 | return yedisList.get(random.nextInt(listSize)); 27 | } 28 | 29 | @Override 30 | public Type getType() { 31 | return type; 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/com/yeahmobi/yedis/loadbalance/RoundRobinLoadBalancer.java: -------------------------------------------------------------------------------- 1 | package com.yeahmobi.yedis.loadbalance; 2 | 3 | import java.util.List; 4 | import java.util.concurrent.atomic.AtomicInteger; 5 | 6 | import com.yeahmobi.yedis.atomic.Yedis; 7 | 8 | public class RoundRobinLoadBalancer implements LoadBalancer { 9 | 10 | private final Type type = LoadBalancer.Type.ROUND_ROBIN; 11 | private final List yedisList; 12 | private final int listSize; 13 | 14 | private final AtomicInteger index = new AtomicInteger(-1); 15 | 16 | public RoundRobinLoadBalancer(List yedisList) { 17 | if (yedisList == null || yedisList.size() <= 0) { 18 | throw new IllegalArgumentException("yedisList cannot be null or empty."); 19 | } 20 | this.yedisList = yedisList; 21 | this.listSize = yedisList.size(); 22 | } 23 | 24 | @Override 25 | public Yedis route() { 26 | return yedisList.get(getIndex()); 27 | } 28 | 29 | private int getIndex() { 30 | return Math.abs(index.incrementAndGet() % listSize); 31 | } 32 | 33 | @Override 34 | public Type getType() { 35 | return type; 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/com/yeahmobi/yedis/pipeline/PipelineJedisPool.java: -------------------------------------------------------------------------------- 1 | package com.yeahmobi.yedis.pipeline; 2 | 3 | import redis.clients.jedis.Jedis; 4 | import redis.clients.jedis.JedisPool; 5 | 6 | import com.yeahmobi.yedis.atomic.AtomConfig; 7 | 8 | public class PipelineJedisPool { 9 | 10 | private final JedisPool jedisPool; 11 | 12 | private final AtomConfig config; 13 | 14 | public PipelineJedisPool(AtomConfig config) { 15 | if (config == null) { 16 | throw new IllegalArgumentException("Argument cannot be null."); 17 | } 18 | 19 | this.config = config; 20 | this.jedisPool = new JedisPool(config.getPipelinePoolConfig(), config.getHost(), config.getPort(), 21 | config.getSocketTimeout(), config.getPassword(), config.getDatabase()); 22 | } 23 | 24 | public AtomConfig getConfig() { 25 | return config; 26 | } 27 | 28 | public Jedis getJedis() { 29 | return this.jedisPool.getResource(); 30 | } 31 | 32 | public void returnBrokenJedis(Jedis resource) { 33 | jedisPool.returnBrokenResource(resource); 34 | } 35 | 36 | public void returnJedis(Jedis resource) { 37 | jedisPool.returnResource(resource); 38 | } 39 | 40 | public void destroy() { 41 | jedisPool.destroy(); 42 | } 43 | 44 | 45 | 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/com/yeahmobi/yedis/pipeline/ShardedYedisPipeline.java: -------------------------------------------------------------------------------- 1 | package com.yeahmobi.yedis.pipeline; 2 | 3 | import java.util.ArrayList; 4 | import java.util.HashMap; 5 | import java.util.List; 6 | import java.util.Map; 7 | import java.util.Set; 8 | 9 | import redis.clients.jedis.BinaryClient.LIST_POSITION; 10 | import redis.clients.jedis.BitPosParams; 11 | import redis.clients.jedis.Response; 12 | import redis.clients.jedis.SortingParams; 13 | import redis.clients.jedis.Tuple; 14 | 15 | import com.yeahmobi.yedis.group.GroupYedis; 16 | import com.yeahmobi.yedis.shard.ShardingStrategy; 17 | 18 | public class ShardedYedisPipeline { 19 | 20 | private HashMap pipelineInfos = new HashMap(); 21 | 22 | private ShardingStrategy shardingStrategy; 23 | 24 | private List responseInfos = new ArrayList(); 25 | 26 | static class PipelineInfo { 27 | 28 | YedisPipeline yedisPipeline; 29 | int indexCount = 0; 30 | } 31 | 32 | static class ResponseInfo { 33 | 34 | // indexCount指向当前pipeline的response的位置 35 | YedisPipeline yedisPipeline; 36 | // indexCount指向当前pipeline的response的位置 37 | int index; 38 | 39 | public ResponseInfo(YedisPipeline yedisPipeline, int index) { 40 | super(); 41 | this.yedisPipeline = yedisPipeline; 42 | this.index = index; 43 | } 44 | } 45 | 46 | public ShardedYedisPipeline(ShardingStrategy shardingStrategy) { 47 | super(); 48 | this.shardingStrategy = shardingStrategy; 49 | } 50 | 51 | private YedisPipeline route(byte[] key) { 52 | GroupYedis groupYedis = shardingStrategy.route(key); 53 | return getAndPut(groupYedis); 54 | } 55 | 56 | private YedisPipeline route(String key) { 57 | GroupYedis groupYedis = shardingStrategy.route(key); 58 | return getAndPut(groupYedis); 59 | } 60 | 61 | private YedisPipeline getAndPut(GroupYedis groupYedis) { 62 | PipelineInfo pipelineInfo = pipelineInfos.get(groupYedis); 63 | if (pipelineInfo == null) { 64 | pipelineInfo = new PipelineInfo(); 65 | pipelineInfo.yedisPipeline = groupYedis.pipelined(); 66 | pipelineInfos.put(groupYedis, pipelineInfo); 67 | } 68 | 69 | ResponseInfo responseInfo = new ResponseInfo(pipelineInfo.yedisPipeline, pipelineInfo.indexCount); 70 | responseInfos.add(responseInfo); 71 | 72 | pipelineInfo.indexCount++; 73 | 74 | return pipelineInfo.yedisPipeline; 75 | } 76 | 77 | public void sync() { 78 | List errorMsg = new ArrayList(); 79 | for (PipelineInfo pipelineInfo : pipelineInfos.values()) { 80 | YedisPipeline pipeline = pipelineInfo.yedisPipeline; 81 | try { 82 | pipeline.sync(); 83 | } catch (Exception e) { 84 | // 如果某个YedisPipeline 有异常,记录起来 85 | errorMsg.add(String.format("Pipeline(%s:%s) error message is " + e.getMessage(), 86 | pipeline.getConfig().getHost(), pipeline.getConfig().getPort())); 87 | } 88 | } 89 | if (errorMsg.size() > 0) { 90 | throw new RuntimeException("Some pipelines error, detail is: " + errorMsg.toString()); 91 | } 92 | } 93 | 94 | @SuppressWarnings("unchecked") 95 | public List syncAndReturnAll() { 96 | HashMap pipeline2ResponseList = new HashMap(); 97 | for (PipelineInfo pipelineInfo : pipelineInfos.values()) { 98 | YedisPipeline pipeline = pipelineInfo.yedisPipeline; 99 | try { 100 | List responseList = pipeline.syncAndReturnAll(); 101 | pipeline2ResponseList.put(pipeline, responseList); 102 | } catch (Exception e) { 103 | // 如果某个YedisPipeline 有异常,该pipeline就没有 responseList,只有 e 104 | pipeline2ResponseList.put(pipeline, e); 105 | } 106 | } 107 | List list = new ArrayList(); 108 | for (ResponseInfo responseInfo : responseInfos) { 109 | Object object = pipeline2ResponseList.get(responseInfo.yedisPipeline); 110 | if (object instanceof List) { 111 | List responseList = (List) object; 112 | Object response = (responseList != null) ? responseList.get(responseInfo.index) : null; 113 | list.add(response); 114 | } else { 115 | // 如果某个YedisPipeline 有异常,该pipeline就没有 responseList,只有 e 116 | list.add(object); 117 | } 118 | } 119 | return list; 120 | } 121 | 122 | public Response append(String key, String value) { 123 | return route(key).append(key, value); 124 | } 125 | 126 | public Response append(byte[] key, byte[] value) { 127 | return route(key).append(key, value); 128 | } 129 | 130 | public Response> blpop(String key) { 131 | return route(key).blpop(key); 132 | } 133 | 134 | public Response> brpop(String key) { 135 | return route(key).brpop(key); 136 | } 137 | 138 | public Response> blpop(byte[] key) { 139 | return route(key).blpop(key); 140 | } 141 | 142 | public Response> brpop(byte[] key) { 143 | return route(key).brpop(key); 144 | } 145 | 146 | public Response decr(String key) { 147 | return route(key).decr(key); 148 | } 149 | 150 | public Response decr(byte[] key) { 151 | return route(key).decr(key); 152 | } 153 | 154 | public Response decrBy(String key, long integer) { 155 | return route(key).decrBy(key, integer); 156 | } 157 | 158 | public Response decrBy(byte[] key, long integer) { 159 | return route(key).decrBy(key, integer); 160 | } 161 | 162 | public Response del(String key) { 163 | return route(key).del(key); 164 | } 165 | 166 | public Response del(byte[] key) { 167 | return route(key).del(key); 168 | } 169 | 170 | public Response exists(String key) { 171 | return route(key).exists(key); 172 | } 173 | 174 | public Response exists(byte[] key) { 175 | return route(key).exists(key); 176 | } 177 | 178 | public Response expire(String key, int seconds) { 179 | return route(key).expire(key, seconds); 180 | } 181 | 182 | public Response expire(byte[] key, int seconds) { 183 | return route(key).expire(key, seconds); 184 | } 185 | 186 | public Response expireAt(String key, long unixTime) { 187 | return route(key).expireAt(key, unixTime); 188 | } 189 | 190 | public Response expireAt(byte[] key, long unixTime) { 191 | return route(key).expireAt(key, unixTime); 192 | } 193 | 194 | public Response get(String key) { 195 | return route(key).get(key); 196 | } 197 | 198 | public Response get(byte[] key) { 199 | return route(key).get(key); 200 | } 201 | 202 | public Response getbit(String key, long offset) { 203 | return route(key).getbit(key, offset); 204 | } 205 | 206 | public Response getbit(byte[] key, long offset) { 207 | return route(key).getbit(key, offset); 208 | } 209 | 210 | public Response bitpos(String key, boolean value) { 211 | return route(key).bitpos(key, value); 212 | } 213 | 214 | public Response bitpos(String key, boolean value, BitPosParams params) { 215 | return route(key).bitpos(key, value, params); 216 | } 217 | 218 | public Response bitpos(byte[] key, boolean value) { 219 | return route(key).bitpos(key, value); 220 | } 221 | 222 | public Response bitpos(byte[] key, boolean value, BitPosParams params) { 223 | return route(key).bitpos(key, value, params); 224 | } 225 | 226 | public Response getrange(String key, long startOffset, long endOffset) { 227 | return route(key).getrange(key, startOffset, endOffset); 228 | } 229 | 230 | public Response getSet(String key, String value) { 231 | return route(key).getSet(key, value); 232 | } 233 | 234 | public Response getSet(byte[] key, byte[] value) { 235 | return route(key).getSet(key, value); 236 | } 237 | 238 | public Response getrange(byte[] key, long startOffset, long endOffset) { 239 | return route(key).getrange(key, startOffset, endOffset); 240 | } 241 | 242 | public Response hdel(String key, String... field) { 243 | return route(key).hdel(key, field); 244 | } 245 | 246 | public Response hdel(byte[] key, byte[]... field) { 247 | return route(key).hdel(key, field); 248 | } 249 | 250 | public Response sort(String key, SortingParams sortingParameters, String dstkey) { 251 | return route(key).sort(key, sortingParameters, dstkey); 252 | } 253 | 254 | public Response hexists(String key, String field) { 255 | return route(key).hexists(key, field); 256 | } 257 | 258 | public Response hexists(byte[] key, byte[] field) { 259 | return route(key).hexists(key, field); 260 | } 261 | 262 | public Response sort(byte[] key, SortingParams sortingParameters, byte[] dstkey) { 263 | return route(key).sort(key, sortingParameters, dstkey); 264 | } 265 | 266 | public Response hget(String key, String field) { 267 | return route(key).hget(key, field); 268 | } 269 | 270 | public Response sort(String key, String dstkey) { 271 | return route(key).sort(key, dstkey); 272 | } 273 | 274 | public Response hget(byte[] key, byte[] field) { 275 | return route(key).hget(key, field); 276 | } 277 | 278 | public Response sort(byte[] key, byte[] dstkey) { 279 | return route(key).sort(key, dstkey); 280 | } 281 | 282 | public Response> hgetAll(String key) { 283 | return route(key).hgetAll(key); 284 | } 285 | 286 | public Response> hgetAll(byte[] key) { 287 | return route(key).hgetAll(key); 288 | } 289 | 290 | public Response hincrBy(String key, String field, long value) { 291 | return route(key).hincrBy(key, field, value); 292 | } 293 | 294 | public Response hincrBy(byte[] key, byte[] field, long value) { 295 | return route(key).hincrBy(key, field, value); 296 | } 297 | 298 | public Response> hkeys(String key) { 299 | return route(key).hkeys(key); 300 | } 301 | 302 | public Response> hkeys(byte[] key) { 303 | return route(key).hkeys(key); 304 | } 305 | 306 | public Response hlen(String key) { 307 | return route(key).hlen(key); 308 | } 309 | 310 | public Response hlen(byte[] key) { 311 | return route(key).hlen(key); 312 | } 313 | 314 | public Response> hmget(String key, String... fields) { 315 | return route(key).hmget(key, fields); 316 | } 317 | 318 | public Response> hmget(byte[] key, byte[]... fields) { 319 | return route(key).hmget(key, fields); 320 | } 321 | 322 | public Response hmset(String key, Map hash) { 323 | return route(key).hmset(key, hash); 324 | } 325 | 326 | public Response hmset(byte[] key, Map hash) { 327 | return route(key).hmset(key, hash); 328 | } 329 | 330 | public Response hset(String key, String field, String value) { 331 | return route(key).hset(key, field, value); 332 | } 333 | 334 | public Response hset(byte[] key, byte[] field, byte[] value) { 335 | return route(key).hset(key, field, value); 336 | } 337 | 338 | public Response hsetnx(String key, String field, String value) { 339 | return route(key).hsetnx(key, field, value); 340 | } 341 | 342 | public Response hsetnx(byte[] key, byte[] field, byte[] value) { 343 | return route(key).hsetnx(key, field, value); 344 | } 345 | 346 | public Response> hvals(String key) { 347 | return route(key).hvals(key); 348 | } 349 | 350 | public Response> hvals(byte[] key) { 351 | return route(key).hvals(key); 352 | } 353 | 354 | public Response incr(String key) { 355 | return route(key).incr(key); 356 | } 357 | 358 | public Response incr(byte[] key) { 359 | return route(key).incr(key); 360 | } 361 | 362 | public Response incrBy(String key, long integer) { 363 | return route(key).incrBy(key, integer); 364 | } 365 | 366 | public Response incrBy(byte[] key, long integer) { 367 | return route(key).incrBy(key, integer); 368 | } 369 | 370 | public Response lindex(String key, long index) { 371 | return route(key).lindex(key, index); 372 | } 373 | 374 | public Response lindex(byte[] key, long index) { 375 | return route(key).lindex(key, index); 376 | } 377 | 378 | public Response linsert(String key, LIST_POSITION where, String pivot, String value) { 379 | return route(key).linsert(key, where, pivot, value); 380 | } 381 | 382 | public Response linsert(byte[] key, LIST_POSITION where, byte[] pivot, byte[] value) { 383 | return route(key).linsert(key, where, pivot, value); 384 | } 385 | 386 | public Response llen(String key) { 387 | return route(key).llen(key); 388 | } 389 | 390 | public Response llen(byte[] key) { 391 | return route(key).llen(key); 392 | } 393 | 394 | public Response lpop(String key) { 395 | return route(key).lpop(key); 396 | } 397 | 398 | public Response lpop(byte[] key) { 399 | return route(key).lpop(key); 400 | } 401 | 402 | public Response lpush(String key, String... string) { 403 | return route(key).lpush(key, string); 404 | } 405 | 406 | public Response lpush(byte[] key, byte[]... string) { 407 | return route(key).lpush(key, string); 408 | } 409 | 410 | public Response lpushx(String key, String... string) { 411 | return route(key).lpushx(key, string); 412 | } 413 | 414 | public Response lpushx(byte[] key, byte[]... bytes) { 415 | return route(key).lpushx(key, bytes); 416 | } 417 | 418 | public Response> lrange(String key, long start, long end) { 419 | return route(key).lrange(key, start, end); 420 | } 421 | 422 | public Response> lrange(byte[] key, long start, long end) { 423 | return route(key).lrange(key, start, end); 424 | } 425 | 426 | public Response lrem(String key, long count, String value) { 427 | return route(key).lrem(key, count, value); 428 | } 429 | 430 | public Response lrem(byte[] key, long count, byte[] value) { 431 | return route(key).lrem(key, count, value); 432 | } 433 | 434 | public Response lset(String key, long index, String value) { 435 | return route(key).lset(key, index, value); 436 | } 437 | 438 | public Response lset(byte[] key, long index, byte[] value) { 439 | return route(key).lset(key, index, value); 440 | } 441 | 442 | public Response ltrim(String key, long start, long end) { 443 | return route(key).ltrim(key, start, end); 444 | } 445 | 446 | public Response ltrim(byte[] key, long start, long end) { 447 | return route(key).ltrim(key, start, end); 448 | } 449 | 450 | public Response move(String key, int dbIndex) { 451 | return route(key).move(key, dbIndex); 452 | } 453 | 454 | public Response move(byte[] key, int dbIndex) { 455 | return route(key).move(key, dbIndex); 456 | } 457 | 458 | public Response persist(String key) { 459 | return route(key).persist(key); 460 | } 461 | 462 | public Response persist(byte[] key) { 463 | return route(key).persist(key); 464 | } 465 | 466 | public Response rpop(String key) { 467 | return route(key).rpop(key); 468 | } 469 | 470 | public Response rpop(byte[] key) { 471 | return route(key).rpop(key); 472 | } 473 | 474 | public Response rpush(String key, String... string) { 475 | return route(key).rpush(key, string); 476 | } 477 | 478 | public Response rpush(byte[] key, byte[]... string) { 479 | return route(key).rpush(key, string); 480 | } 481 | 482 | public Response rpushx(String key, String... string) { 483 | return route(key).rpushx(key, string); 484 | } 485 | 486 | public Response rpushx(byte[] key, byte[]... string) { 487 | return route(key).rpushx(key, string); 488 | } 489 | 490 | public Response sadd(String key, String... member) { 491 | return route(key).sadd(key, member); 492 | } 493 | 494 | public Response sadd(byte[] key, byte[]... member) { 495 | return route(key).sadd(key, member); 496 | } 497 | 498 | public Response scard(String key) { 499 | return route(key).scard(key); 500 | } 501 | 502 | public Response scard(byte[] key) { 503 | return route(key).scard(key); 504 | } 505 | 506 | public Response set(String key, String value) { 507 | return route(key).set(key, value); 508 | } 509 | 510 | public Response set(byte[] key, byte[] value) { 511 | return route(key).set(key, value); 512 | } 513 | 514 | public Response setbit(String key, long offset, boolean value) { 515 | return route(key).setbit(key, offset, value); 516 | } 517 | 518 | public Response setbit(byte[] key, long offset, byte[] value) { 519 | return route(key).setbit(key, offset, value); 520 | } 521 | 522 | public Response setex(String key, int seconds, String value) { 523 | return route(key).setex(key, seconds, value); 524 | } 525 | 526 | public Response setex(byte[] key, int seconds, byte[] value) { 527 | return route(key).setex(key, seconds, value); 528 | } 529 | 530 | public Response setnx(String key, String value) { 531 | return route(key).setnx(key, value); 532 | } 533 | 534 | public Response setnx(byte[] key, byte[] value) { 535 | return route(key).setnx(key, value); 536 | } 537 | 538 | public Response setrange(String key, long offset, String value) { 539 | return route(key).setrange(key, offset, value); 540 | } 541 | 542 | public Response setrange(byte[] key, long offset, byte[] value) { 543 | return route(key).setrange(key, offset, value); 544 | } 545 | 546 | public Response sismember(String key, String member) { 547 | return route(key).sismember(key, member); 548 | } 549 | 550 | public Response sismember(byte[] key, byte[] member) { 551 | return route(key).sismember(key, member); 552 | } 553 | 554 | public Response> smembers(String key) { 555 | return route(key).smembers(key); 556 | } 557 | 558 | public Response> smembers(byte[] key) { 559 | return route(key).smembers(key); 560 | } 561 | 562 | public Response> sort(String key) { 563 | return route(key).sort(key); 564 | } 565 | 566 | public Response> sort(byte[] key) { 567 | return route(key).sort(key); 568 | } 569 | 570 | public Response> sort(String key, SortingParams sortingParameters) { 571 | return route(key).sort(key, sortingParameters); 572 | } 573 | 574 | public Response> sort(byte[] key, SortingParams sortingParameters) { 575 | return route(key).sort(key, sortingParameters); 576 | } 577 | 578 | public Response spop(String key) { 579 | return route(key).spop(key); 580 | } 581 | 582 | public Response spop(byte[] key) { 583 | return route(key).spop(key); 584 | } 585 | 586 | public Response srandmember(String key) { 587 | return route(key).srandmember(key); 588 | } 589 | 590 | public Response> srandmember(String key, int count) { 591 | return route(key).srandmember(key, count); 592 | } 593 | 594 | public Response srandmember(byte[] key) { 595 | return route(key).srandmember(key); 596 | } 597 | 598 | public Response> srandmember(byte[] key, int count) { 599 | return route(key).srandmember(key, count); 600 | } 601 | 602 | public Response srem(String key, String... member) { 603 | return route(key).srem(key, member); 604 | } 605 | 606 | public Response srem(byte[] key, byte[]... member) { 607 | return route(key).srem(key, member); 608 | } 609 | 610 | public Response strlen(String key) { 611 | return route(key).strlen(key); 612 | } 613 | 614 | public Response strlen(byte[] key) { 615 | return route(key).strlen(key); 616 | } 617 | 618 | public Response substr(String key, int start, int end) { 619 | return route(key).substr(key, start, end); 620 | } 621 | 622 | public Response substr(byte[] key, int start, int end) { 623 | return route(key).substr(key, start, end); 624 | } 625 | 626 | public Response ttl(String key) { 627 | return route(key).ttl(key); 628 | } 629 | 630 | public Response ttl(byte[] key) { 631 | return route(key).ttl(key); 632 | } 633 | 634 | public Response type(String key) { 635 | return route(key).type(key); 636 | } 637 | 638 | public Response type(byte[] key) { 639 | return route(key).type(key); 640 | } 641 | 642 | public Response zadd(String key, double score, String member) { 643 | return route(key).zadd(key, score, member); 644 | } 645 | 646 | public Response zadd(String key, Map scoreMembers) { 647 | return route(key).zadd(key, scoreMembers); 648 | } 649 | 650 | public Response zadd(byte[] key, double score, byte[] member) { 651 | return route(key).zadd(key, score, member); 652 | } 653 | 654 | public Response zcard(String key) { 655 | return route(key).zcard(key); 656 | } 657 | 658 | public Response zcard(byte[] key) { 659 | return route(key).zcard(key); 660 | } 661 | 662 | public Response zcount(String key, double min, double max) { 663 | return route(key).zcount(key, min, max); 664 | } 665 | 666 | public Response zcount(String key, String min, String max) { 667 | return route(key).zcount(key, min, max); 668 | } 669 | 670 | public Response zcount(byte[] key, double min, double max) { 671 | return route(key).zcount(key, min, max); 672 | } 673 | 674 | public Response zincrby(String key, double score, String member) { 675 | return route(key).zincrby(key, score, member); 676 | } 677 | 678 | public Response zincrby(byte[] key, double score, byte[] member) { 679 | return route(key).zincrby(key, score, member); 680 | } 681 | 682 | public Response> zrange(String key, long start, long end) { 683 | return route(key).zrange(key, start, end); 684 | } 685 | 686 | public Response> zrange(byte[] key, long start, long end) { 687 | return route(key).zrange(key, start, end); 688 | } 689 | 690 | public Response> zrangeByScore(String key, double min, double max) { 691 | return route(key).zrangeByScore(key, min, max); 692 | } 693 | 694 | public Response> zrangeByScore(byte[] key, double min, double max) { 695 | return route(key).zrangeByScore(key, min, max); 696 | } 697 | 698 | public Response> zrangeByScore(String key, String min, String max) { 699 | return route(key).zrangeByScore(key, min, max); 700 | } 701 | 702 | public Response> zrangeByScore(byte[] key, byte[] min, byte[] max) { 703 | return route(key).zrangeByScore(key, min, max); 704 | } 705 | 706 | public Response> zrangeByScore(String key, double min, double max, int offset, int count) { 707 | return route(key).zrangeByScore(key, min, max, offset, count); 708 | } 709 | 710 | public Response> zrangeByScore(String key, String min, String max, int offset, int count) { 711 | return route(key).zrangeByScore(key, min, max, offset, count); 712 | } 713 | 714 | public Response> zrangeByScore(byte[] key, double min, double max, int offset, int count) { 715 | return route(key).zrangeByScore(key, min, max, offset, count); 716 | } 717 | 718 | public Response> zrangeByScore(byte[] key, byte[] min, byte[] max, int offset, int count) { 719 | return route(key).zrangeByScore(key, min, max, offset, count); 720 | } 721 | 722 | public Response> zrangeByScoreWithScores(String key, double min, double max) { 723 | return route(key).zrangeByScoreWithScores(key, min, max); 724 | } 725 | 726 | public Response> zrangeByScoreWithScores(String key, String min, String max) { 727 | return route(key).zrangeByScoreWithScores(key, min, max); 728 | } 729 | 730 | public Response> zrangeByScoreWithScores(byte[] key, double min, double max) { 731 | return route(key).zrangeByScoreWithScores(key, min, max); 732 | } 733 | 734 | public Response> zrangeByScoreWithScores(byte[] key, byte[] min, byte[] max) { 735 | return route(key).zrangeByScoreWithScores(key, min, max); 736 | } 737 | 738 | public Response> zrangeByScoreWithScores(String key, double min, double max, int offset, int count) { 739 | return route(key).zrangeByScoreWithScores(key, min, max, offset, count); 740 | } 741 | 742 | public Response> zrangeByScoreWithScores(String key, String min, String max, int offset, int count) { 743 | return route(key).zrangeByScoreWithScores(key, min, max, offset, count); 744 | } 745 | 746 | public Response> zrangeByScoreWithScores(byte[] key, double min, double max, int offset, int count) { 747 | return route(key).zrangeByScoreWithScores(key, min, max, offset, count); 748 | } 749 | 750 | public Response> zrangeByScoreWithScores(byte[] key, byte[] min, byte[] max, int offset, int count) { 751 | return route(key).zrangeByScoreWithScores(key, min, max, offset, count); 752 | } 753 | 754 | public Response> zrevrangeByScore(String key, double max, double min) { 755 | return route(key).zrevrangeByScore(key, max, min); 756 | } 757 | 758 | public Response> zrevrangeByScore(byte[] key, double max, double min) { 759 | return route(key).zrevrangeByScore(key, max, min); 760 | } 761 | 762 | public Response> zrevrangeByScore(String key, String max, String min) { 763 | return route(key).zrevrangeByScore(key, max, min); 764 | } 765 | 766 | public Response> zrevrangeByScore(byte[] key, byte[] max, byte[] min) { 767 | return route(key).zrevrangeByScore(key, max, min); 768 | } 769 | 770 | public Response> zrevrangeByScore(String key, double max, double min, int offset, int count) { 771 | return route(key).zrevrangeByScore(key, max, min, offset, count); 772 | } 773 | 774 | public Response> zrevrangeByScore(String key, String max, String min, int offset, int count) { 775 | return route(key).zrevrangeByScore(key, max, min, offset, count); 776 | } 777 | 778 | public Response> zrevrangeByScore(byte[] key, double max, double min, int offset, int count) { 779 | return route(key).zrevrangeByScore(key, max, min, offset, count); 780 | } 781 | 782 | public Response> zrevrangeByScore(byte[] key, byte[] max, byte[] min, int offset, int count) { 783 | return route(key).zrevrangeByScore(key, max, min, offset, count); 784 | } 785 | 786 | public Response> zrevrangeByScoreWithScores(String key, double max, double min) { 787 | return route(key).zrevrangeByScoreWithScores(key, max, min); 788 | } 789 | 790 | public Response> zrevrangeByScoreWithScores(String key, String max, String min) { 791 | return route(key).zrevrangeByScoreWithScores(key, max, min); 792 | } 793 | 794 | public Response> zrevrangeByScoreWithScores(byte[] key, double max, double min) { 795 | return route(key).zrevrangeByScoreWithScores(key, max, min); 796 | } 797 | 798 | public Response> zrevrangeByScoreWithScores(byte[] key, byte[] max, byte[] min) { 799 | return route(key).zrevrangeByScoreWithScores(key, max, min); 800 | } 801 | 802 | public Response> zrevrangeByScoreWithScores(String key, double max, double min, int offset, int count) { 803 | return route(key).zrevrangeByScoreWithScores(key, max, min, offset, count); 804 | } 805 | 806 | public Response> zrevrangeByScoreWithScores(String key, String max, String min, int offset, int count) { 807 | return route(key).zrevrangeByScoreWithScores(key, max, min, offset, count); 808 | } 809 | 810 | public Response> zrevrangeByScoreWithScores(byte[] key, double max, double min, int offset, int count) { 811 | return route(key).zrevrangeByScoreWithScores(key, max, min, offset, count); 812 | } 813 | 814 | public Response> zrevrangeByScoreWithScores(byte[] key, byte[] max, byte[] min, int offset, int count) { 815 | return route(key).zrevrangeByScoreWithScores(key, max, min, offset, count); 816 | } 817 | 818 | public Response> zrangeWithScores(String key, long start, long end) { 819 | return route(key).zrangeWithScores(key, start, end); 820 | } 821 | 822 | public Response> zrangeWithScores(byte[] key, long start, long end) { 823 | return route(key).zrangeWithScores(key, start, end); 824 | } 825 | 826 | public Response zrank(String key, String member) { 827 | return route(key).zrank(key, member); 828 | } 829 | 830 | public Response zrank(byte[] key, byte[] member) { 831 | return route(key).zrank(key, member); 832 | } 833 | 834 | public Response zrem(String key, String... member) { 835 | return route(key).zrem(key, member); 836 | } 837 | 838 | public Response zrem(byte[] key, byte[]... member) { 839 | return route(key).zrem(key, member); 840 | } 841 | 842 | public Response zremrangeByRank(String key, long start, long end) { 843 | return route(key).zremrangeByRank(key, start, end); 844 | } 845 | 846 | public Response zremrangeByRank(byte[] key, long start, long end) { 847 | return route(key).zremrangeByRank(key, start, end); 848 | } 849 | 850 | public Response zremrangeByScore(String key, double start, double end) { 851 | return route(key).zremrangeByScore(key, start, end); 852 | } 853 | 854 | public Response zremrangeByScore(String key, String start, String end) { 855 | return route(key).zremrangeByScore(key, start, end); 856 | } 857 | 858 | public Response zremrangeByScore(byte[] key, double start, double end) { 859 | return route(key).zremrangeByScore(key, start, end); 860 | } 861 | 862 | public Response zremrangeByScore(byte[] key, byte[] start, byte[] end) { 863 | return route(key).zremrangeByScore(key, start, end); 864 | } 865 | 866 | public Response> zrevrange(String key, long start, long end) { 867 | return route(key).zrevrange(key, start, end); 868 | } 869 | 870 | public Response> zrevrange(byte[] key, long start, long end) { 871 | return route(key).zrevrange(key, start, end); 872 | } 873 | 874 | public Response> zrevrangeWithScores(String key, long start, long end) { 875 | return route(key).zrevrangeWithScores(key, start, end); 876 | } 877 | 878 | public Response> zrevrangeWithScores(byte[] key, long start, long end) { 879 | return route(key).zrevrangeWithScores(key, start, end); 880 | } 881 | 882 | public Response zrevrank(String key, String member) { 883 | return route(key).zrevrank(key, member); 884 | } 885 | 886 | public Response zrevrank(byte[] key, byte[] member) { 887 | return route(key).zrevrank(key, member); 888 | } 889 | 890 | public Response zscore(String key, String member) { 891 | return route(key).zscore(key, member); 892 | } 893 | 894 | public Response zscore(byte[] key, byte[] member) { 895 | return route(key).zscore(key, member); 896 | } 897 | 898 | public Response bitcount(String key) { 899 | return route(key).bitcount(key); 900 | } 901 | 902 | public Response bitcount(String key, long start, long end) { 903 | return route(key).bitcount(key, start, end); 904 | } 905 | 906 | public Response bitcount(byte[] key) { 907 | return route(key).bitcount(key); 908 | } 909 | 910 | public Response bitcount(byte[] key, long start, long end) { 911 | return route(key).bitcount(key, start, end); 912 | } 913 | 914 | public Response dump(String key) { 915 | return route(key).dump(key); 916 | } 917 | 918 | public Response dump(byte[] key) { 919 | return route(key).dump(key); 920 | } 921 | 922 | public Response migrate(String host, int port, String key, int destinationDb, int timeout) { 923 | return route(key).migrate(host, port, key, destinationDb, timeout); 924 | } 925 | 926 | public Response migrate(byte[] host, int port, byte[] key, int destinationDb, int timeout) { 927 | return route(key).migrate(host, port, key, destinationDb, timeout); 928 | } 929 | 930 | public Response objectRefcount(String key) { 931 | return route(key).objectRefcount(key); 932 | } 933 | 934 | public Response objectRefcount(byte[] key) { 935 | return route(key).objectRefcount(key); 936 | } 937 | 938 | public Response objectEncoding(String key) { 939 | return route(key).objectEncoding(key); 940 | } 941 | 942 | public Response objectEncoding(byte[] key) { 943 | return route(key).objectEncoding(key); 944 | } 945 | 946 | public Response objectIdletime(String key) { 947 | return route(key).objectIdletime(key); 948 | } 949 | 950 | public Response objectIdletime(byte[] key) { 951 | return route(key).objectIdletime(key); 952 | } 953 | 954 | @Deprecated 955 | public Response pexpire(String key, int milliseconds) { 956 | return route(key).pexpire(key, milliseconds); 957 | } 958 | 959 | @Deprecated 960 | public Response pexpire(byte[] key, int milliseconds) { 961 | return route(key).pexpire(key, milliseconds); 962 | } 963 | 964 | public Response pexpire(String key, long milliseconds) { 965 | return route(key).pexpire(key, milliseconds); 966 | } 967 | 968 | public Response pexpire(byte[] key, long milliseconds) { 969 | return route(key).pexpire(key, milliseconds); 970 | } 971 | 972 | public Response pexpireAt(String key, long millisecondsTimestamp) { 973 | return route(key).pexpireAt(key, millisecondsTimestamp); 974 | } 975 | 976 | public Response pexpireAt(byte[] key, long millisecondsTimestamp) { 977 | return route(key).pexpireAt(key, millisecondsTimestamp); 978 | } 979 | 980 | public Response pttl(String key) { 981 | return route(key).pttl(key); 982 | } 983 | 984 | public Response pttl(byte[] key) { 985 | return route(key).pttl(key); 986 | } 987 | 988 | public Response restore(String key, int ttl, byte[] serializedValue) { 989 | return route(key).restore(key, ttl, serializedValue); 990 | } 991 | 992 | public Response restore(byte[] key, int ttl, byte[] serializedValue) { 993 | return route(key).restore(key, ttl, serializedValue); 994 | } 995 | 996 | public Response incrByFloat(String key, double increment) { 997 | return route(key).incrByFloat(key, increment); 998 | } 999 | 1000 | public Response incrByFloat(byte[] key, double increment) { 1001 | return route(key).incrByFloat(key, increment); 1002 | } 1003 | 1004 | public Response psetex(String key, int milliseconds, String value) { 1005 | return route(key).psetex(key, milliseconds, value); 1006 | } 1007 | 1008 | public Response psetex(byte[] key, int milliseconds, byte[] value) { 1009 | return route(key).psetex(key, milliseconds, value); 1010 | } 1011 | 1012 | public Response set(String key, String value, String nxxx) { 1013 | return route(key).set(key, value, nxxx); 1014 | } 1015 | 1016 | public Response set(byte[] key, byte[] value, byte[] nxxx) { 1017 | return route(key).set(key, value, nxxx); 1018 | } 1019 | 1020 | public Response set(String key, String value, String nxxx, String expx, int time) { 1021 | return route(key).set(key, value, nxxx, expx, time); 1022 | } 1023 | 1024 | public Response set(byte[] key, byte[] value, byte[] nxxx, byte[] expx, int time) { 1025 | return route(key).set(key, value, nxxx, expx, time); 1026 | } 1027 | 1028 | public Response hincrByFloat(String key, String field, double increment) { 1029 | return route(key).hincrByFloat(key, field, increment); 1030 | } 1031 | 1032 | public Response hincrByFloat(byte[] key, byte[] field, double increment) { 1033 | return route(key).hincrByFloat(key, field, increment); 1034 | } 1035 | 1036 | public Response pfadd(byte[] key, byte[]... elements) { 1037 | return route(key).pfadd(key, elements); 1038 | } 1039 | 1040 | public Response pfcount(byte[] key) { 1041 | return route(key).pfcount(key); 1042 | } 1043 | 1044 | public Response pfadd(String key, String... elements) { 1045 | return route(key).pfadd(key, elements); 1046 | } 1047 | 1048 | public Response pfcount(String key) { 1049 | return route(key).pfcount(key); 1050 | } 1051 | 1052 | } 1053 | -------------------------------------------------------------------------------- /src/main/java/com/yeahmobi/yedis/shard/AbstractShardingStrategy.java: -------------------------------------------------------------------------------- 1 | package com.yeahmobi.yedis.shard; 2 | 3 | import java.io.UnsupportedEncodingException; 4 | import java.util.List; 5 | 6 | import com.yeahmobi.yedis.common.YedisException; 7 | import com.yeahmobi.yedis.group.GroupYedis; 8 | 9 | public abstract class AbstractShardingStrategy implements ShardingStrategy { 10 | protected HashCodeComputingStrategy hashCodeComputingStrategy; 11 | protected static final String STRING_ENCODING = "utf-8"; 12 | 13 | protected AbstractShardingStrategy(List groups, 14 | HashCodeComputingStrategy hashCodeComputingStrategy) { 15 | if (groups == null || groups.isEmpty()) { 16 | throw new IllegalArgumentException( 17 | "You must init with at least one GroupYedis instance."); 18 | } 19 | 20 | if (hashCodeComputingStrategy == null) { 21 | throw new IllegalArgumentException( 22 | "You must init with an not null hashCodeComputingStrategy."); 23 | } 24 | 25 | this.hashCodeComputingStrategy = hashCodeComputingStrategy; 26 | } 27 | 28 | protected String bytesToArray(byte[] data) { 29 | try { 30 | return new String(data, STRING_ENCODING); 31 | } catch (UnsupportedEncodingException e) { 32 | throw new YedisException(e); 33 | } 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/com/yeahmobi/yedis/shard/DummyShardingStrategy.java: -------------------------------------------------------------------------------- 1 | package com.yeahmobi.yedis.shard; 2 | 3 | import java.util.List; 4 | 5 | import com.yeahmobi.yedis.group.GroupYedis; 6 | 7 | /** 8 | * @author Leo.Liang 9 | */ 10 | public class DummyShardingStrategy extends AbstractShardingStrategy { 11 | 12 | private List groups; 13 | 14 | public DummyShardingStrategy(List groups, HashCodeComputingStrategy hashCodeComputingStrategy) { 15 | super(groups, hashCodeComputingStrategy); 16 | this.groups = groups; 17 | } 18 | 19 | @Override 20 | public GroupYedis route(String key) { 21 | return groups.get(0); 22 | } 23 | 24 | @Override 25 | public GroupYedis route(byte[] key) { 26 | return groups.get(0); 27 | } 28 | 29 | @Override 30 | public void close() { 31 | for (GroupYedis group : groups) { 32 | try { 33 | group.close(); 34 | } catch (Exception e) { 35 | // ignore 36 | } 37 | } 38 | } 39 | 40 | @Override 41 | public void flushAll() { 42 | for (GroupYedis group : groups) { 43 | try { 44 | group.flushAll(); 45 | } catch (Exception e) { 46 | // ignore 47 | } 48 | } 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/com/yeahmobi/yedis/shard/HashCodeComputingStrategy.java: -------------------------------------------------------------------------------- 1 | package com.yeahmobi.yedis.shard; 2 | 3 | public interface HashCodeComputingStrategy { 4 | int hash(String key); 5 | } 6 | -------------------------------------------------------------------------------- /src/main/java/com/yeahmobi/yedis/shard/ShardedYedis.java: -------------------------------------------------------------------------------- 1 | package com.yeahmobi.yedis.shard; 2 | 3 | import java.util.Collection; 4 | import java.util.List; 5 | import java.util.Map; 6 | import java.util.Map.Entry; 7 | import java.util.Set; 8 | 9 | import redis.clients.jedis.BinaryClient.LIST_POSITION; 10 | import redis.clients.jedis.ScanResult; 11 | import redis.clients.jedis.SortingParams; 12 | import redis.clients.jedis.Tuple; 13 | 14 | import com.yeahmobi.yedis.group.GroupYedis; 15 | import com.yeahmobi.yedis.pipeline.ShardedYedisPipeline; 16 | 17 | /** 18 | * @author Leo.Liang 19 | */ 20 | public class ShardedYedis { 21 | 22 | private ShardingStrategy shardingStrategy; 23 | 24 | public ShardedYedis(List groups, ShardingAlgorithm algo, 25 | HashCodeComputingStrategy hashCodeComputingStrategy) { 26 | this.shardingStrategy = ShardingStrategyFactory.createShardingStrategy(groups, algo, hashCodeComputingStrategy); 27 | } 28 | 29 | public void close() { 30 | this.shardingStrategy.close(); 31 | } 32 | 33 | private GroupYedis route(String key) { 34 | return shardingStrategy.route(key); 35 | } 36 | 37 | private GroupYedis route(byte[] key) { 38 | return shardingStrategy.route(key); 39 | } 40 | 41 | public ShardedYedisPipeline pipeline(){ 42 | return new ShardedYedisPipeline(shardingStrategy); 43 | } 44 | 45 | public String set(byte[] key, byte[] value) { 46 | return route(key).set(key, value); 47 | } 48 | 49 | public byte[] get(byte[] key) { 50 | return route(key).get(key); 51 | } 52 | 53 | public Boolean exists(byte[] key) { 54 | return route(key).exists(key); 55 | } 56 | 57 | public Long persist(byte[] key) { 58 | return route(key).persist(key); 59 | } 60 | 61 | public String type(byte[] key) { 62 | return route(key).type(key); 63 | } 64 | 65 | public Long expire(byte[] key, int seconds) { 66 | return route(key).expire(key, seconds); 67 | } 68 | 69 | public Long expireAt(byte[] key, long unixTime) { 70 | return route(key).expireAt(key, unixTime); 71 | } 72 | 73 | public Long ttl(byte[] key) { 74 | return route(key).ttl(key); 75 | } 76 | 77 | public Boolean setbit(byte[] key, long offset, boolean value) { 78 | return route(key).setbit(key, offset, value); 79 | } 80 | 81 | public Boolean setbit(byte[] key, long offset, byte[] value) { 82 | return route(key).setbit(key, offset, value); 83 | } 84 | 85 | public Boolean getbit(byte[] key, long offset) { 86 | return route(key).getbit(key, offset); 87 | } 88 | 89 | public Long setrange(byte[] key, long offset, byte[] value) { 90 | return route(key).setrange(key, offset, value); 91 | } 92 | 93 | public byte[] getrange(byte[] key, long startOffset, long endOffset) { 94 | return route(key).getrange(key, startOffset, endOffset); 95 | } 96 | 97 | public byte[] getSet(byte[] key, byte[] value) { 98 | return route(key).getSet(key, value); 99 | } 100 | 101 | public Long setnx(byte[] key, byte[] value) { 102 | return route(key).setnx(key, value); 103 | } 104 | 105 | public String setex(byte[] key, int seconds, byte[] value) { 106 | return route(key).setex(key, seconds, value); 107 | } 108 | 109 | public Long decrBy(byte[] key, long integer) { 110 | return route(key).decrBy(key, integer); 111 | } 112 | 113 | public Long decr(byte[] key) { 114 | return route(key).decr(key); 115 | } 116 | 117 | public Long incrBy(byte[] key, long integer) { 118 | return route(key).incrBy(key, integer); 119 | } 120 | 121 | public Double incrByFloat(byte[] key, double value) { 122 | return route(key).incrByFloat(key, value); 123 | } 124 | 125 | public Long incr(byte[] key) { 126 | return route(key).incr(key); 127 | } 128 | 129 | public Long append(byte[] key, byte[] value) { 130 | return route(key).append(key, value); 131 | } 132 | 133 | public byte[] substr(byte[] key, int start, int end) { 134 | return route(key).substr(key, start, end); 135 | } 136 | 137 | public Long hset(byte[] key, byte[] field, byte[] value) { 138 | return route(key).hset(key, field, value); 139 | } 140 | 141 | public byte[] hget(byte[] key, byte[] field) { 142 | return route(key).hget(key, field); 143 | } 144 | 145 | public Long hsetnx(byte[] key, byte[] field, byte[] value) { 146 | return route(key).hsetnx(key, field, value); 147 | } 148 | 149 | public String hmset(byte[] key, Map hash) { 150 | return route(key).hmset(key, hash); 151 | } 152 | 153 | public List hmget(byte[] key, byte[]... fields) { 154 | return route(key).hmget(key, fields); 155 | } 156 | 157 | public Long hincrBy(byte[] key, byte[] field, long value) { 158 | return route(key).hincrBy(key, field, value); 159 | } 160 | 161 | public Double hincrByFloat(byte[] key, byte[] field, double value) { 162 | return route(key).hincrByFloat(key, field, value); 163 | } 164 | 165 | public Boolean hexists(byte[] key, byte[] field) { 166 | return route(key).hexists(key, field); 167 | } 168 | 169 | public Long hdel(byte[] key, byte[]... field) { 170 | return route(key).hdel(key, field); 171 | } 172 | 173 | public Long hlen(byte[] key) { 174 | return route(key).hlen(key); 175 | } 176 | 177 | public Set hkeys(byte[] key) { 178 | return route(key).hkeys(key); 179 | } 180 | 181 | public Collection hvals(byte[] key) { 182 | return route(key).hvals(key); 183 | } 184 | 185 | public Map hgetAll(byte[] key) { 186 | return route(key).hgetAll(key); 187 | } 188 | 189 | public Long rpush(byte[] key, byte[]... args) { 190 | return route(key).rpush(key, args); 191 | } 192 | 193 | public Long lpush(byte[] key, byte[]... args) { 194 | return route(key).lpush(key, args); 195 | } 196 | 197 | public Long llen(byte[] key) { 198 | return route(key).llen(key); 199 | } 200 | 201 | public List lrange(byte[] key, long start, long end) { 202 | return route(key).lrange(key, start, end); 203 | } 204 | 205 | public String ltrim(byte[] key, long start, long end) { 206 | return route(key).ltrim(key, start, end); 207 | } 208 | 209 | public byte[] lindex(byte[] key, long index) { 210 | return route(key).lindex(key, index); 211 | } 212 | 213 | public String lset(byte[] key, long index, byte[] value) { 214 | return route(key).lset(key, index, value); 215 | } 216 | 217 | public Long lrem(byte[] key, long count, byte[] value) { 218 | return route(key).lrem(key, count, value); 219 | } 220 | 221 | public byte[] lpop(byte[] key) { 222 | return route(key).lpop(key); 223 | } 224 | 225 | public byte[] rpop(byte[] key) { 226 | return route(key).rpop(key); 227 | } 228 | 229 | public Long sadd(byte[] key, byte[]... member) { 230 | return route(key).sadd(key, member); 231 | } 232 | 233 | public Set smembers(byte[] key) { 234 | return route(key).smembers(key); 235 | } 236 | 237 | public Long srem(byte[] key, byte[]... member) { 238 | return route(key).srem(key, member); 239 | } 240 | 241 | public byte[] spop(byte[] key) { 242 | return route(key).spop(key); 243 | } 244 | 245 | public Long scard(byte[] key) { 246 | return route(key).scard(key); 247 | } 248 | 249 | public Boolean sismember(byte[] key, byte[] member) { 250 | return route(key).sismember(key, member); 251 | } 252 | 253 | public byte[] srandmember(byte[] key) { 254 | return route(key).srandmember(key); 255 | } 256 | 257 | public Long strlen(byte[] key) { 258 | return route(key).strlen(key); 259 | } 260 | 261 | public Long zadd(byte[] key, double score, byte[] member) { 262 | return route(key).zadd(key, score, member); 263 | } 264 | 265 | public Long zadd(byte[] key, Map scoreMembers) { 266 | return route(key).zadd(key, scoreMembers); 267 | } 268 | 269 | public Set zrange(byte[] key, long start, long end) { 270 | return route(key).zrange(key, start, end); 271 | } 272 | 273 | public Long zrem(byte[] key, byte[]... member) { 274 | return route(key).zrem(key, member); 275 | } 276 | 277 | public Double zincrby(byte[] key, double score, byte[] member) { 278 | return route(key).zincrby(key, score, member); 279 | } 280 | 281 | public Long zrank(byte[] key, byte[] member) { 282 | return route(key).zrank(key, member); 283 | } 284 | 285 | public Long zrevrank(byte[] key, byte[] member) { 286 | return route(key).zrevrank(key, member); 287 | } 288 | 289 | public Set zrevrange(byte[] key, long start, long end) { 290 | return route(key).zrevrange(key, start, end); 291 | } 292 | 293 | public Set zrangeWithScores(byte[] key, long start, long end) { 294 | return route(key).zrangeWithScores(key, start, end); 295 | } 296 | 297 | public Set zrevrangeWithScores(byte[] key, long start, long end) { 298 | return route(key).zrevrangeWithScores(key, start, end); 299 | } 300 | 301 | public Long zcard(byte[] key) { 302 | return route(key).zcard(key); 303 | } 304 | 305 | public Double zscore(byte[] key, byte[] member) { 306 | return route(key).zscore(key, member); 307 | } 308 | 309 | public List sort(byte[] key) { 310 | return route(key).sort(key); 311 | } 312 | 313 | public List sort(byte[] key, SortingParams sortingParameters) { 314 | return route(key).sort(key, sortingParameters); 315 | } 316 | 317 | public Long zcount(byte[] key, double min, double max) { 318 | return route(key).zcount(key, min, max); 319 | } 320 | 321 | public Long zcount(byte[] key, byte[] min, byte[] max) { 322 | return route(key).zcount(key, min, max); 323 | } 324 | 325 | public Set zrangeByScore(byte[] key, double min, double max) { 326 | return route(key).zrangeByScore(key, min, max); 327 | } 328 | 329 | public Set zrangeByScore(byte[] key, byte[] min, byte[] max) { 330 | return route(key).zrangeByScore(key, min, max); 331 | } 332 | 333 | public Set zrevrangeByScore(byte[] key, double max, double min) { 334 | return route(key).zrevrangeByScore(key, max, min); 335 | } 336 | 337 | public Set zrangeByScore(byte[] key, double min, double max, int offset, int count) { 338 | return route(key).zrangeByScore(key, min, max); 339 | } 340 | 341 | public Set zrevrangeByScore(byte[] key, byte[] max, byte[] min) { 342 | return route(key).zrevrangeByScore(key, max, min); 343 | } 344 | 345 | public Set zrangeByScore(byte[] key, byte[] min, byte[] max, int offset, int count) { 346 | return route(key).zrangeByScore(key, min, max, offset, count); 347 | } 348 | 349 | public Set zrevrangeByScore(byte[] key, double max, double min, int offset, int count) { 350 | return route(key).zrevrangeByScore(key, max, min, offset, count); 351 | } 352 | 353 | public Set zrangeByScoreWithScores(byte[] key, double min, double max) { 354 | return route(key).zrangeByScoreWithScores(key, min, max); 355 | } 356 | 357 | public Set zrevrangeByScoreWithScores(byte[] key, double max, double min) { 358 | return route(key).zrevrangeByScoreWithScores(key, max, min); 359 | } 360 | 361 | public Set zrangeByScoreWithScores(byte[] key, double min, double max, int offset, int count) { 362 | return route(key).zrangeByScoreWithScores(key, min, max, offset, count); 363 | } 364 | 365 | public Set zrevrangeByScore(byte[] key, byte[] max, byte[] min, int offset, int count) { 366 | return route(key).zrevrangeByScore(key, max, min, offset, count); 367 | } 368 | 369 | public Set zrangeByScoreWithScores(byte[] key, byte[] min, byte[] max) { 370 | return route(key).zrangeByScoreWithScores(key, min, max); 371 | } 372 | 373 | public Set zrevrangeByScoreWithScores(byte[] key, byte[] max, byte[] min) { 374 | return route(key).zrevrangeByScoreWithScores(key, max, min); 375 | } 376 | 377 | public Set zrangeByScoreWithScores(byte[] key, byte[] min, byte[] max, int offset, int count) { 378 | return route(key).zrangeByScoreWithScores(key, min, max, offset, count); 379 | } 380 | 381 | public Set zrevrangeByScoreWithScores(byte[] key, double max, double min, int offset, int count) { 382 | return route(key).zrevrangeByScoreWithScores(key, max, min, offset, count); 383 | } 384 | 385 | public Set zrevrangeByScoreWithScores(byte[] key, byte[] max, byte[] min, int offset, int count) { 386 | return route(key).zrevrangeByScoreWithScores(key, max, min, offset, count); 387 | } 388 | 389 | public Long zremrangeByRank(byte[] key, long start, long end) { 390 | return route(key).zremrangeByRank(key, start, end); 391 | } 392 | 393 | public Long zremrangeByScore(byte[] key, double start, double end) { 394 | return route(key).zremrangeByScore(key, start, end); 395 | } 396 | 397 | public Long zremrangeByScore(byte[] key, byte[] start, byte[] end) { 398 | return route(key).zremrangeByScore(key, start, end); 399 | } 400 | 401 | public Long linsert(byte[] key, LIST_POSITION where, byte[] pivot, byte[] value) { 402 | return route(key).linsert(key, where, pivot, value); 403 | } 404 | 405 | public Long lpushx(byte[] key, byte[]... arg) { 406 | return route(key).lpushx(key, arg); 407 | } 408 | 409 | public Long rpushx(byte[] key, byte[]... arg) { 410 | return route(key).rpushx(key, arg); 411 | } 412 | 413 | public List blpop(byte[] arg) { 414 | return route(arg).blpop(arg); 415 | } 416 | 417 | public List brpop(byte[] arg) { 418 | return route(arg).brpop(arg); 419 | } 420 | 421 | public Long del(byte[] key) { 422 | return route(key).del(key); 423 | } 424 | 425 | public byte[] echo(byte[] arg) { 426 | return route(arg).echo(arg); 427 | } 428 | 429 | public Long move(byte[] key, int dbIndex) { 430 | return route(key).move(key, dbIndex); 431 | } 432 | 433 | public Long bitcount(byte[] key) { 434 | return route(key).bitcount(key); 435 | } 436 | 437 | public Long bitcount(byte[] key, long start, long end) { 438 | return route(key).bitcount(key, start, end); 439 | } 440 | 441 | public Long pfadd(byte[] key, byte[]... elements) { 442 | return route(key).pfadd(key, elements); 443 | } 444 | 445 | public long pfcount(byte[] key) { 446 | return route(key).pfcount(key); 447 | } 448 | 449 | public String set(String key, String value) { 450 | return route(key).set(key, value); 451 | } 452 | 453 | public String set(String key, String value, String nxxx, String expx, long time) { 454 | return route(key).set(key, value, nxxx, expx, time); 455 | } 456 | 457 | public String get(String key) { 458 | return route(key).get(key); 459 | } 460 | 461 | public Boolean exists(String key) { 462 | return route(key).exists(key); 463 | } 464 | 465 | public Long persist(String key) { 466 | return route(key).persist(key); 467 | } 468 | 469 | public String type(String key) { 470 | return route(key).type(key); 471 | } 472 | 473 | public Long expire(String key, int seconds) { 474 | return route(key).expire(key, seconds); 475 | } 476 | 477 | public Long expireAt(String key, long unixTime) { 478 | return route(key).expireAt(key, unixTime); 479 | } 480 | 481 | public Long ttl(String key) { 482 | return route(key).ttl(key); 483 | } 484 | 485 | public Boolean setbit(String key, long offset, boolean value) { 486 | return route(key).setbit(key, offset, value); 487 | } 488 | 489 | public Boolean setbit(String key, long offset, String value) { 490 | return route(key).setbit(key, offset, value); 491 | } 492 | 493 | public Boolean getbit(String key, long offset) { 494 | return route(key).getbit(key, offset); 495 | } 496 | 497 | public Long setrange(String key, long offset, String value) { 498 | return route(key).setrange(key, offset, value); 499 | } 500 | 501 | public String getrange(String key, long startOffset, long endOffset) { 502 | return route(key).getrange(key, startOffset, endOffset); 503 | } 504 | 505 | public String getSet(String key, String value) { 506 | return route(key).getSet(key, value); 507 | } 508 | 509 | public Long setnx(String key, String value) { 510 | return route(key).setnx(key, value); 511 | } 512 | 513 | public String setex(String key, int seconds, String value) { 514 | return route(key).setex(key, seconds, value); 515 | } 516 | 517 | public Long decrBy(String key, long integer) { 518 | return route(key).decrBy(key, integer); 519 | } 520 | 521 | public Long decr(String key) { 522 | return route(key).decr(key); 523 | } 524 | 525 | public Long incrBy(String key, long integer) { 526 | return route(key).incrBy(key, integer); 527 | } 528 | 529 | public Long incr(String key) { 530 | return route(key).incr(key); 531 | } 532 | 533 | public Long append(String key, String value) { 534 | return route(key).append(key, value); 535 | } 536 | 537 | public String substr(String key, int start, int end) { 538 | return route(key).substr(key, start, end); 539 | } 540 | 541 | public Long hset(String key, String field, String value) { 542 | return route(key).hset(key, field, value); 543 | } 544 | 545 | public String hget(String key, String field) { 546 | return route(key).hget(key, field); 547 | } 548 | 549 | public Long hsetnx(String key, String field, String value) { 550 | return route(key).hsetnx(key, field, value); 551 | } 552 | 553 | public String hmset(String key, Map hash) { 554 | return route(key).hmset(key, hash); 555 | } 556 | 557 | public List hmget(String key, String... fields) { 558 | return route(key).hmget(key, fields); 559 | } 560 | 561 | public Long hincrBy(String key, String field, long value) { 562 | return route(key).hincrBy(key, field, value); 563 | } 564 | 565 | public Boolean hexists(String key, String field) { 566 | return route(key).hexists(key, field); 567 | } 568 | 569 | public Long hdel(String key, String... field) { 570 | return route(key).hdel(key, field); 571 | } 572 | 573 | public Long hlen(String key) { 574 | return route(key).hlen(key); 575 | } 576 | 577 | public Set hkeys(String key) { 578 | return route(key).hkeys(key); 579 | } 580 | 581 | public List hvals(String key) { 582 | return route(key).hvals(key); 583 | } 584 | 585 | public Map hgetAll(String key) { 586 | return route(key).hgetAll(key); 587 | } 588 | 589 | public Long rpush(String key, String... string) { 590 | return route(key).rpush(key, string); 591 | } 592 | 593 | public Long lpush(String key, String... string) { 594 | return route(key).lpush(key, string); 595 | } 596 | 597 | public Long llen(String key) { 598 | return route(key).llen(key); 599 | } 600 | 601 | public List lrange(String key, long start, long end) { 602 | return route(key).lrange(key, start, end); 603 | } 604 | 605 | public String ltrim(String key, long start, long end) { 606 | return route(key).ltrim(key, start, end); 607 | } 608 | 609 | public String lindex(String key, long index) { 610 | return route(key).lindex(key, index); 611 | } 612 | 613 | public String lset(String key, long index, String value) { 614 | return route(key).lset(key, index, value); 615 | } 616 | 617 | public Long lrem(String key, long count, String value) { 618 | return route(key).lrem(key, count, value); 619 | } 620 | 621 | public String lpop(String key) { 622 | return route(key).lpop(key); 623 | } 624 | 625 | public String rpop(String key) { 626 | return route(key).rpop(key); 627 | } 628 | 629 | public Long sadd(String key, String... member) { 630 | return route(key).sadd(key, member); 631 | } 632 | 633 | public Set smembers(String key) { 634 | return route(key).smembers(key); 635 | } 636 | 637 | public Long srem(String key, String... member) { 638 | return route(key).srem(key, member); 639 | } 640 | 641 | public String spop(String key) { 642 | return route(key).spop(key); 643 | } 644 | 645 | public Long scard(String key) { 646 | return route(key).scard(key); 647 | } 648 | 649 | public Boolean sismember(String key, String member) { 650 | return route(key).sismember(key, member); 651 | } 652 | 653 | public String srandmember(String key) { 654 | return route(key).srandmember(key); 655 | } 656 | 657 | public Long strlen(String key) { 658 | return route(key).strlen(key); 659 | } 660 | 661 | public Long zadd(String key, double score, String member) { 662 | return route(key).zadd(key, score, member); 663 | } 664 | 665 | public Long zadd(String key, Map scoreMembers) { 666 | return route(key).zadd(key, scoreMembers); 667 | } 668 | 669 | public Set zrange(String key, long start, long end) { 670 | return route(key).zrange(key, start, end); 671 | } 672 | 673 | public Long zrem(String key, String... member) { 674 | return route(key).zrem(key, member); 675 | } 676 | 677 | public Double zincrby(String key, double score, String member) { 678 | return route(key).zincrby(key, score, member); 679 | } 680 | 681 | public Long zrank(String key, String member) { 682 | return route(key).zrank(key, member); 683 | } 684 | 685 | public Long zrevrank(String key, String member) { 686 | return route(key).zrevrank(key, member); 687 | } 688 | 689 | public Set zrevrange(String key, long start, long end) { 690 | return route(key).zrevrange(key, start, end); 691 | } 692 | 693 | public Set zrangeWithScores(String key, long start, long end) { 694 | return route(key).zrangeWithScores(key, start, end); 695 | } 696 | 697 | public Set zrevrangeWithScores(String key, long start, long end) { 698 | return route(key).zrevrangeWithScores(key, start, end); 699 | } 700 | 701 | public Long zcard(String key) { 702 | return route(key).zcard(key); 703 | } 704 | 705 | public Double zscore(String key, String member) { 706 | return route(key).zscore(key, member); 707 | } 708 | 709 | public List sort(String key) { 710 | return route(key).sort(key); 711 | } 712 | 713 | public List sort(String key, SortingParams sortingParameters) { 714 | return route(key).sort(key, sortingParameters); 715 | } 716 | 717 | public Long zcount(String key, double min, double max) { 718 | return route(key).zcount(key, min, max); 719 | } 720 | 721 | public Long zcount(String key, String min, String max) { 722 | return route(key).zcount(key, min, max); 723 | } 724 | 725 | public Set zrangeByScore(String key, double min, double max) { 726 | return route(key).zrangeByScore(key, min, max); 727 | } 728 | 729 | public Set zrangeByScore(String key, String min, String max) { 730 | return route(key).zrangeByScore(key, min, max); 731 | } 732 | 733 | public Set zrevrangeByScore(String key, double max, double min) { 734 | return route(key).zrevrangeByScore(key, max, min); 735 | } 736 | 737 | public Set zrangeByScore(String key, double min, double max, int offset, int count) { 738 | return route(key).zrangeByScore(key, min, max, offset, count); 739 | } 740 | 741 | public Set zrevrangeByScore(String key, String max, String min) { 742 | return route(key).zrevrangeByScore(key, max, min); 743 | } 744 | 745 | public Set zrangeByScore(String key, String min, String max, int offset, int count) { 746 | return route(key).zrangeByScore(key, min, max); 747 | } 748 | 749 | public Set zrevrangeByScore(String key, double max, double min, int offset, int count) { 750 | return route(key).zrevrangeByScore(key, max, min, offset, count); 751 | } 752 | 753 | public Set zrangeByScoreWithScores(String key, double min, double max) { 754 | return route(key).zrangeByScoreWithScores(key, min, max); 755 | } 756 | 757 | public Set zrevrangeByScoreWithScores(String key, double max, double min) { 758 | return route(key).zrevrangeByScoreWithScores(key, max, min); 759 | } 760 | 761 | public Set zrangeByScoreWithScores(String key, double min, double max, int offset, int count) { 762 | return route(key).zrangeByScoreWithScores(key, min, max, offset, count); 763 | } 764 | 765 | public Set zrevrangeByScore(String key, String max, String min, int offset, int count) { 766 | return route(key).zrevrangeByScore(key, max, min, offset, count); 767 | } 768 | 769 | public Set zrangeByScoreWithScores(String key, String min, String max) { 770 | return route(key).zrangeByScoreWithScores(key, min, max); 771 | } 772 | 773 | public Set zrevrangeByScoreWithScores(String key, String max, String min) { 774 | return route(key).zrevrangeByScoreWithScores(key, max, min); 775 | } 776 | 777 | public Set zrangeByScoreWithScores(String key, String min, String max, int offset, int count) { 778 | return route(key).zrangeByScoreWithScores(key, min, max, offset, count); 779 | } 780 | 781 | public Set zrevrangeByScoreWithScores(String key, double max, double min, int offset, int count) { 782 | return route(key).zrevrangeByScoreWithScores(key, max, min, offset, count); 783 | } 784 | 785 | public Set zrevrangeByScoreWithScores(String key, String max, String min, int offset, int count) { 786 | return route(key).zrevrangeByScoreWithScores(key, max, min, offset, count); 787 | } 788 | 789 | public Long zremrangeByRank(String key, long start, long end) { 790 | return route(key).zremrangeByRank(key, start, end); 791 | } 792 | 793 | public Long zremrangeByScore(String key, double start, double end) { 794 | return route(key).zremrangeByScore(key, start, end); 795 | } 796 | 797 | public Long zremrangeByScore(String key, String start, String end) { 798 | return route(key).zremrangeByScore(key, start, end); 799 | } 800 | 801 | public Long linsert(String key, LIST_POSITION where, String pivot, String value) { 802 | return route(key).linsert(key, where, pivot, value); 803 | } 804 | 805 | public Long lpushx(String key, String... string) { 806 | return route(key).lpushx(key, string); 807 | } 808 | 809 | public Long rpushx(String key, String... string) { 810 | return route(key).rpushx(key, string); 811 | } 812 | 813 | public List blpop(String arg) { 814 | return route(arg).blpop(arg); 815 | } 816 | 817 | public List brpop(String arg) { 818 | return route(arg).brpop(arg); 819 | } 820 | 821 | public Long del(String key) { 822 | return route(key).del(key); 823 | } 824 | 825 | public String echo(String string) { 826 | return route(string).echo(string); 827 | } 828 | 829 | public Long move(String key, int dbIndex) { 830 | return route(key).move(key, dbIndex); 831 | } 832 | 833 | public Long bitcount(String key) { 834 | return route(key).bitcount(key); 835 | } 836 | 837 | public Long bitcount(String key, long start, long end) { 838 | return route(key).bitcount(key, start, end); 839 | } 840 | 841 | @Deprecated 842 | public ScanResult> hscan(String key, int cursor) { 843 | return route(key).hscan(key, cursor); 844 | } 845 | 846 | @Deprecated 847 | public ScanResult sscan(String key, int cursor) { 848 | return route(key).sscan(key, cursor); 849 | } 850 | 851 | @Deprecated 852 | public ScanResult zscan(String key, int cursor) { 853 | return route(key).zscan(key, cursor); 854 | } 855 | 856 | public ScanResult> hscan(String key, String cursor) { 857 | return route(key).hscan(key, cursor); 858 | } 859 | 860 | public ScanResult sscan(String key, String cursor) { 861 | return route(key).sscan(key, cursor); 862 | } 863 | 864 | public ScanResult zscan(String key, String cursor) { 865 | return route(key).zscan(key, cursor); 866 | } 867 | 868 | public Long pfadd(String key, String... elements) { 869 | return route(key).pfadd(key, elements); 870 | } 871 | 872 | public long pfcount(String key) { 873 | return route(key).pfcount(key); 874 | } 875 | 876 | public void flushAll() { 877 | shardingStrategy.flushAll(); 878 | } 879 | 880 | } 881 | -------------------------------------------------------------------------------- /src/main/java/com/yeahmobi/yedis/shard/ShardingAlgorithm.java: -------------------------------------------------------------------------------- 1 | package com.yeahmobi.yedis.shard; 2 | 3 | public enum ShardingAlgorithm { 4 | SIMPLE_HASH, // 5 | ; 6 | } 7 | -------------------------------------------------------------------------------- /src/main/java/com/yeahmobi/yedis/shard/ShardingStrategy.java: -------------------------------------------------------------------------------- 1 | package com.yeahmobi.yedis.shard; 2 | 3 | import com.yeahmobi.yedis.group.GroupYedis; 4 | 5 | /** 6 | * @author Leo.Liang 7 | */ 8 | public interface ShardingStrategy { 9 | 10 | public GroupYedis route(String key); 11 | 12 | public GroupYedis route(byte[] key); 13 | 14 | public void flushAll(); 15 | 16 | public void close(); 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/com/yeahmobi/yedis/shard/ShardingStrategyFactory.java: -------------------------------------------------------------------------------- 1 | package com.yeahmobi.yedis.shard; 2 | 3 | import java.util.List; 4 | 5 | import com.yeahmobi.yedis.group.GroupYedis; 6 | 7 | public class ShardingStrategyFactory { 8 | 9 | private ShardingStrategyFactory() { 10 | 11 | } 12 | 13 | public static ShardingStrategy createShardingStrategy( 14 | List groups, ShardingAlgorithm algo, 15 | HashCodeComputingStrategy hashCodeComputingStrategy) { 16 | if (algo == ShardingAlgorithm.SIMPLE_HASH) { 17 | return new SimpleHashingShardingStrategy(groups, 18 | hashCodeComputingStrategy); 19 | } 20 | 21 | throw new IllegalArgumentException("Unsupported sharding algorithm."); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/com/yeahmobi/yedis/shard/SimpleHashingShardingStrategy.java: -------------------------------------------------------------------------------- 1 | package com.yeahmobi.yedis.shard; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import com.yeahmobi.yedis.group.GroupYedis; 7 | 8 | /** 9 | * @author Leo.Liang 10 | */ 11 | public class SimpleHashingShardingStrategy extends AbstractShardingStrategy { 12 | 13 | private ArrayList groups; 14 | private int size = 0; 15 | 16 | public SimpleHashingShardingStrategy(List groups, HashCodeComputingStrategy hashCodeComputingStrategy) { 17 | super(groups, hashCodeComputingStrategy); 18 | // For the sake of random accessing performance, 19 | // we should ensure the groups is an array based list. 20 | this.groups = new ArrayList(groups); 21 | this.size = this.groups.size(); 22 | } 23 | 24 | @Override 25 | public GroupYedis route(String key) { 26 | int hash = Math.abs(this.hashCodeComputingStrategy.hash(key)); 27 | return this.groups.get(hash % size); 28 | } 29 | 30 | @Override 31 | public GroupYedis route(byte[] key) { 32 | return this.groups.get(this.hashCodeComputingStrategy.hash(bytesToArray(key)) % size); 33 | } 34 | 35 | @Override 36 | public void close() { 37 | for (GroupYedis group : groups) { 38 | try { 39 | group.close(); 40 | } catch (Exception e) { 41 | // ignore 42 | } 43 | } 44 | } 45 | 46 | @Override 47 | public void flushAll() { 48 | for (GroupYedis group : groups) { 49 | try { 50 | group.flushAll(); 51 | } catch (Exception e) { 52 | // ignore 53 | } 54 | } 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /src/main/java/com/yeahmobi/yedis/util/RetribleExecutor.java: -------------------------------------------------------------------------------- 1 | package com.yeahmobi.yedis.util; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | 6 | import com.yeahmobi.yedis.common.YedisNetworkException; 7 | import com.yeahmobi.yedis.common.YedisTimeoutException; 8 | 9 | public final class RetribleExecutor { 10 | 11 | private static final Logger logger = LoggerFactory.getLogger(RetribleExecutor.class); 12 | 13 | public static T execute(RetriableOperator opr, int retryCount) { 14 | for (;;) { 15 | try { 16 | return opr.execute(); 17 | } catch (YedisNetworkException e) { 18 | if (retryCount-- <= 0) { 19 | throw e; 20 | } else { 21 | logger.warn("Error occur, message is:" + e.getMessage() + ", exception is " + e + ", retrying..."); 22 | continue; 23 | } 24 | } catch (YedisTimeoutException e) { 25 | if (retryCount-- <= 0) { 26 | throw e; 27 | } else { 28 | logger.warn("Error occur, message is:" + e.getMessage() + ", exception is " + e + ", retrying..."); 29 | continue; 30 | } 31 | } 32 | } 33 | } 34 | 35 | public static interface RetriableOperator { 36 | 37 | T execute(); 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/com/yeahmobi/yedis/util/SleepStrategy.java: -------------------------------------------------------------------------------- 1 | package com.yeahmobi.yedis.util; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | 6 | /** 7 | * 睡眠类 8 | * 9 | * @author atell 10 | */ 11 | public class SleepStrategy { 12 | 13 | private static Logger logger = LoggerFactory.getLogger(SleepStrategy.class); 14 | 15 | private int count = 0; 16 | private final int base; 17 | private final int interval; 18 | private final int upperbound; 19 | 20 | public SleepStrategy(int base, int interval, int upperbound) { 21 | super(); 22 | this.base = base; 23 | this.interval = interval; 24 | this.upperbound = upperbound; 25 | } 26 | 27 | public SleepStrategy() { 28 | this(100, 500, 10000); 29 | } 30 | 31 | public long sleep() { 32 | long sleepTime = base + (long) count++ * interval; 33 | if (sleepTime > upperbound) { 34 | sleepTime = upperbound; 35 | count = 0; 36 | } 37 | if (sleepTime > 0) { 38 | if (logger.isDebugEnabled()) { 39 | logger.debug("Sleep " + sleepTime + "ms."); 40 | } 41 | try { 42 | Thread.sleep(sleepTime); 43 | } catch (InterruptedException e) { 44 | Thread.currentThread().interrupt(); 45 | } 46 | } 47 | return sleepTime; 48 | } 49 | 50 | public void reset() { 51 | count = 0; 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /src/test/java/com/yeahmobi/yedis/base/DoubleServerYedisTestBase.java: -------------------------------------------------------------------------------- 1 | package com.yeahmobi.yedis.base; 2 | 3 | import java.io.IOException; 4 | 5 | import org.junit.Assert; 6 | 7 | import redis.embedded.RedisServer; 8 | 9 | public abstract class DoubleServerYedisTestBase extends Assert { 10 | 11 | private static RedisServer redisServer1; 12 | private static RedisServer redisServer2; 13 | 14 | protected static String host = "localhost"; 15 | // protected static String host = "172.20.0.100"; 16 | 17 | protected static int port1 = 63800; 18 | protected static int port2 = 63801; 19 | 20 | 21 | public static void startRedisServer() throws IOException { 22 | redisServer1 = new RedisServer(port1); 23 | redisServer1.start(); 24 | redisServer2 = new RedisServer(port2); 25 | redisServer2.start(); 26 | 27 | } 28 | 29 | 30 | public static void stopRedisServer() throws InterruptedException { 31 | // do some work 32 | redisServer1.stop(); 33 | redisServer2.stop(); 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/test/java/com/yeahmobi/yedis/base/YedisBaseTest.java: -------------------------------------------------------------------------------- 1 | package com.yeahmobi.yedis.base; 2 | 3 | import java.io.IOException; 4 | 5 | import org.junit.AfterClass; 6 | import org.junit.Assert; 7 | import org.junit.BeforeClass; 8 | 9 | import redis.embedded.RedisServer; 10 | 11 | public abstract class YedisBaseTest extends Assert { 12 | 13 | private static RedisServer redisServer; 14 | 15 | protected static String host = "localhost"; 16 | // protected static String host = "172.20.0.100"; 17 | 18 | protected static int port = 63799; 19 | 20 | @BeforeClass 21 | public static void startRedisServer() throws IOException { 22 | redisServer = new RedisServer(port); 23 | redisServer.start(); 24 | 25 | } 26 | 27 | @AfterClass 28 | public static void stopRedisServer() throws InterruptedException { 29 | // do some work 30 | redisServer.stop(); 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/test/java/com/yeahmobi/yedis/base/YedisTestBase.java: -------------------------------------------------------------------------------- 1 | package com.yeahmobi.yedis.base; 2 | 3 | import java.io.IOException; 4 | 5 | import org.junit.AfterClass; 6 | import org.junit.Assert; 7 | import org.junit.BeforeClass; 8 | 9 | import redis.embedded.RedisServer; 10 | 11 | public abstract class YedisTestBase extends Assert { 12 | 13 | private static RedisServer redisServer; 14 | 15 | protected static String host = "localhost"; 16 | // protected static String host = "172.20.0.100"; 17 | 18 | protected static int port = 63799; 19 | 20 | @BeforeClass 21 | public static void startRedisServer() throws IOException { 22 | redisServer = new RedisServer(port); 23 | redisServer.start(); 24 | 25 | } 26 | 27 | @AfterClass 28 | public static void stopRedisServer() throws InterruptedException { 29 | // do some work 30 | redisServer.stop(); 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/test/java/com/yeahmobi/yedis/example/GroupUseCase.java: -------------------------------------------------------------------------------- 1 | package com.yeahmobi.yedis.example; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | import java.util.concurrent.TimeUnit; 6 | 7 | import com.yeahmobi.yedis.common.ServerInfo; 8 | import com.yeahmobi.yedis.group.GroupConfig; 9 | import com.yeahmobi.yedis.group.GroupYedis; 10 | import com.yeahmobi.yedis.pipeline.YedisPipeline; 11 | 12 | public class GroupUseCase { 13 | 14 | public static void main(String[] args) throws InterruptedException { 15 | 16 | ServerInfo writeSeverInfo = new ServerInfo("127.0.0.1", 6379); 17 | ServerInfo readSeverInfo = new ServerInfo("127.0.0.1", 6379); 18 | List readSeverInfoList = new ArrayList(); 19 | readSeverInfoList.add(readSeverInfo); 20 | 21 | GroupConfig groupConfig = new GroupConfig(writeSeverInfo, readSeverInfoList); 22 | GroupYedis yedis = new GroupYedis(groupConfig); 23 | 24 | String key = "example_a"; 25 | while (true) { 26 | try { 27 | yedis.set(key, "test"); 28 | YedisPipeline pipeline = yedis.pipelined(); 29 | pipeline.set("p_1", "p_1"); 30 | pipeline.set("p_2", "p_2"); 31 | pipeline.get("p_1"); 32 | pipeline.get("1"); 33 | List response = pipeline.syncAndReturnAll(); 34 | // 或pipeline.sync(); 35 | System.out.println(response); 36 | System.out.println(yedis.get(key)); 37 | yedis.del(key); 38 | System.out.println(yedis.get(key)); 39 | System.out.println(yedis.get("p_2")); 40 | } catch (Exception e) { 41 | e.printStackTrace(); 42 | } 43 | TimeUnit.SECONDS.sleep(5); 44 | } 45 | 46 | // System.out.println("main done"); 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /src/test/java/com/yeahmobi/yedis/example/GroupUseCaseWithZK.java: -------------------------------------------------------------------------------- 1 | package com.yeahmobi.yedis.example; 2 | 3 | import java.util.concurrent.TimeUnit; 4 | 5 | import com.yeahmobi.yedis.group.GroupConfig; 6 | import com.yeahmobi.yedis.group.GroupYedis; 7 | import com.yeahmobi.yedis.group.ReadMode; 8 | 9 | public class GroupUseCaseWithZK { 10 | 11 | public static void main(String[] args) throws InterruptedException { 12 | 13 | GroupConfig groupConfig = new GroupConfig("cluster_dsp","172.20.0.100"); 14 | groupConfig.setReadMode(ReadMode.SLAVE); 15 | GroupYedis yedis = new GroupYedis(groupConfig); 16 | 17 | String key = "example_a"; 18 | while (true) { 19 | try { 20 | yedis.set(key, "test"); 21 | System.out.println(yedis.get(key)); 22 | } catch (Exception e) { 23 | e.printStackTrace(); 24 | } 25 | TimeUnit.SECONDS.sleep(1); 26 | } 27 | 28 | // System.out.println("main done"); 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/test/java/com/yeahmobi/yedis/example/PerformanceTest.java: -------------------------------------------------------------------------------- 1 | package com.yeahmobi.yedis.example; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | 6 | import redis.clients.jedis.Jedis; 7 | 8 | import com.yeahmobi.yedis.atomic.AtomConfig; 9 | import com.yeahmobi.yedis.atomic.Yedis; 10 | import com.yeahmobi.yedis.group.GroupConfig; 11 | import com.yeahmobi.yedis.group.GroupYedis; 12 | import com.yeahmobi.yedis.group.ReadMode; 13 | import com.yeahmobi.yedis.util.RetribleExecutor; 14 | import com.yeahmobi.yedis.util.RetribleExecutor.RetriableOperator; 15 | 16 | public class PerformanceTest { 17 | 18 | private final static Logger logger = LoggerFactory.getLogger(GroupYedis.class); 19 | 20 | public static void main(String[] args) throws InterruptedException { 21 | try { 22 | { 23 | final GroupYedis yedis = getGroupYedis(); 24 | Thread.sleep(3000);// 等待连接池构建完 25 | long start = System.currentTimeMillis(); 26 | for (int i = 0; i < 100000; i++) { 27 | RetribleExecutor.execute(new RetriableOperator() { 28 | 29 | public String execute() { 30 | return yedis.get("test_a"); 31 | } 32 | }, Integer.MAX_VALUE); 33 | } 34 | System.out.println(System.currentTimeMillis() - start); 35 | yedis.close(); 36 | } 37 | System.out.println("---------------------------------------------"); 38 | { 39 | Yedis yedis = getAtomYedis(); 40 | Thread.sleep(1000);// 等待连接池构建完 41 | long start = System.currentTimeMillis(); 42 | for (int i = 0; i < 10000; i++) { 43 | yedis.get("test_a"); 44 | } 45 | System.out.println(System.currentTimeMillis() - start); 46 | yedis.close(); 47 | } 48 | System.out.println("---------------------------------------------"); 49 | { 50 | Jedis jedis = getJedis(); 51 | long start = System.currentTimeMillis(); 52 | for (int i = 0; i < 10000; i++) { 53 | // jedis.set("test_a", "test_a"); 54 | jedis.get("test_a"); 55 | } 56 | System.out.println(System.currentTimeMillis() - start); 57 | jedis.close(); 58 | } 59 | } catch (Exception e) { 60 | System.out.println("-----"); 61 | e.printStackTrace(); 62 | logger.error(e.getMessage(), e); 63 | } 64 | } 65 | 66 | protected static Jedis getJedis() { 67 | Jedis jedis = new Jedis("172.20.0.100"); 68 | return jedis; 69 | } 70 | 71 | protected static Yedis getAtomYedis() { 72 | AtomConfig config = new AtomConfig("172.20.0.100"); 73 | Yedis yedis = new Yedis(config); 74 | return yedis; 75 | } 76 | 77 | private static GroupYedis getGroupYedis() { 78 | GroupConfig groupConfig = new GroupConfig("cluster_dsp", "172.20.0.100"); 79 | groupConfig.setReadMode(ReadMode.SLAVE); 80 | GroupYedis yedis = new GroupYedis(groupConfig); 81 | return yedis; 82 | } 83 | 84 | } 85 | -------------------------------------------------------------------------------- /src/test/java/com/yeahmobi/yedis/example/ShardedYedisPipelineCase.java: -------------------------------------------------------------------------------- 1 | package com.yeahmobi.yedis.example; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import com.yeahmobi.yedis.common.ServerInfo; 7 | import com.yeahmobi.yedis.group.GroupConfig; 8 | import com.yeahmobi.yedis.group.GroupYedis; 9 | import com.yeahmobi.yedis.pipeline.ShardedYedisPipeline; 10 | import com.yeahmobi.yedis.shard.DefaultHashCodeCoputingStrategy; 11 | import com.yeahmobi.yedis.shard.ShardedYedis; 12 | import com.yeahmobi.yedis.shard.ShardingAlgorithm; 13 | 14 | public class ShardedYedisPipelineCase { 15 | 16 | protected static String host = "localhost"; 17 | 18 | private static GroupYedis buildGroupYedis(int port) { 19 | ServerInfo writeSeverInfo = new ServerInfo(host, port); 20 | ServerInfo readSeverInfo = new ServerInfo(host, port); 21 | List readSeverInfoList = new ArrayList(); 22 | readSeverInfoList.add(readSeverInfo); 23 | 24 | GroupConfig groupConfig = new GroupConfig(writeSeverInfo, readSeverInfoList); 25 | groupConfig.getPipelinePoolConfig().setMaxTotal(1); 26 | GroupYedis groupYedis = new GroupYedis(groupConfig); 27 | return groupYedis; 28 | } 29 | 30 | public static void main(String[] args) { 31 | GroupYedis groupYedis1 = buildGroupYedis(6379); 32 | GroupYedis groupYedis2 = buildGroupYedis(6380); 33 | ArrayList groups = new ArrayList(); 34 | groups.add(groupYedis1); 35 | groups.add(groupYedis2); 36 | ShardedYedis yedis = new ShardedYedis(groups, ShardingAlgorithm.SIMPLE_HASH, new DefaultHashCodeCoputingStrategy()); 37 | 38 | ShardedYedisPipeline pipeline = yedis.pipeline(); 39 | pipeline.set("key1", "shard-value1"); 40 | pipeline.set("key2", "shard-value2"); 41 | pipeline.set("key3", "shard-value3"); 42 | pipeline.get("key3"); 43 | pipeline.get("key2"); 44 | pipeline.get("key1"); 45 | pipeline.get("key1"); 46 | pipeline.get("key2"); 47 | pipeline.get("key3"); 48 | System.out.println(pipeline.syncAndReturnAll()); 49 | pipeline.sync(); 50 | // System.out.println(pipeline.sync()); 51 | 52 | ShardedYedisPipeline pipeline2 = yedis.pipeline(); 53 | pipeline2.get("key1"); 54 | pipeline2.get("key2"); 55 | 56 | System.out.println(pipeline2.syncAndReturnAll()); 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /src/test/java/com/yeahmobi/yedis/example/YedisCase.java: -------------------------------------------------------------------------------- 1 | package com.yeahmobi.yedis.example; 2 | 3 | import java.util.List; 4 | 5 | import com.yeahmobi.yedis.atomic.AtomConfig; 6 | import com.yeahmobi.yedis.atomic.Yedis; 7 | import com.yeahmobi.yedis.pipeline.YedisPipeline; 8 | 9 | public class YedisCase { 10 | 11 | public static void main(String[] args) { 12 | AtomConfig config = new AtomConfig("127.0.0.1"); 13 | config.setSocketTimeout(1000); 14 | final Yedis yedis = new Yedis(config); 15 | 16 | { 17 | Thread t = new Thread() { 18 | 19 | @Override 20 | public void run() { 21 | while (true) { 22 | YedisPipeline pipeline = yedis.pipelined(); 23 | pipeline.set("p_1", "p_1"); 24 | pipeline.set("p_2", "p_2"); 25 | pipeline.get("p_1"); 26 | pipeline.get("1"); 27 | List response = pipeline.syncAndReturnAll(); 28 | // 或pipeline.sync(); 29 | System.out.println(response); 30 | // 能正常输出以下行,则没问题 31 | // [OK, OK, p_1, 0] 32 | // [OK, OK, p_1, 1] 33 | } 34 | } 35 | 36 | }; 37 | t.start(); 38 | } 39 | 40 | // 使用多线程进行干扰 41 | { 42 | Thread t = new Thread() { 43 | 44 | @Override 45 | public void run() { 46 | while (true) { 47 | yedis.set("1", "1"); 48 | yedis.set("1", "0"); 49 | // System.out.println(yedis.get("p_1")); 50 | } 51 | } 52 | 53 | }; 54 | t.start(); 55 | } 56 | 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /src/test/java/com/yeahmobi/yedis/group/GroupYedisHashTest.java: -------------------------------------------------------------------------------- 1 | package com.yeahmobi.yedis.group; 2 | 3 | import java.util.List; 4 | import java.util.Map; 5 | import java.util.Set; 6 | 7 | import org.junit.After; 8 | import org.junit.Before; 9 | import org.junit.Test; 10 | 11 | import com.google.common.collect.ImmutableMap; 12 | 13 | public class GroupYedisHashTest extends GroupYedisTest { 14 | 15 | private String key1 = "key1"; 16 | private String key2 = "key2"; 17 | private String key11 = "key11"; 18 | private String key12 = "key12"; 19 | private String key21 = "key21"; 20 | private String key22 = "key22"; 21 | 22 | @Before 23 | public void setup() { 24 | yedis.hset(key1, key11, "value11"); 25 | yedis.hset(key1, key12, "value12"); 26 | yedis.hset(key2, key21, "value21"); 27 | yedis.hset(key2, key22, "value22"); 28 | } 29 | 30 | @After 31 | public void tearDown() { 32 | yedis.flushAll(); 33 | } 34 | 35 | @Test 36 | public void hgetAndDel() { 37 | assertEquals(Long.valueOf(1), yedis.hdel(key1, key11)); 38 | assertEquals(null, yedis.hget(key1, key11)); 39 | } 40 | 41 | @Test 42 | public void hgetAndDelByte() { 43 | assertEquals(Long.valueOf(1), yedis.hdel(key1.getBytes(), key11.getBytes())); 44 | assertEquals(null, yedis.hget(key1.getBytes(), key11.getBytes())); 45 | } 46 | 47 | @Test 48 | public void hexists() { 49 | assertTrue(yedis.hexists(key1, key11)); 50 | assertFalse(yedis.hexists(key1, "nokey")); 51 | } 52 | 53 | @Test 54 | public void hexistsByte() { 55 | assertTrue(yedis.hexists(key1.getBytes(), key11.getBytes())); 56 | assertFalse(yedis.hexists(key1.getBytes(), "nokey".getBytes())); 57 | } 58 | 59 | @Test 60 | public void hgetall() { 61 | Map map = yedis.hgetAll(key1); 62 | assertEquals(2, map.size()); 63 | assertEquals("value11", map.get(key11)); 64 | } 65 | 66 | @Test 67 | public void hgetallByte() { 68 | Map map = yedis.hgetAll(key1.getBytes()); 69 | assertEquals(2, map.size()); 70 | assertEquals("value11", new String(map.get(key11.getBytes()))); 71 | } 72 | 73 | @Test 74 | public void hincby() { 75 | yedis.hset(key1, key11, "5"); 76 | yedis.hincrBy(key1, key11, 2); 77 | assertEquals("7", yedis.hget(key1, key11)); 78 | } 79 | 80 | @Test 81 | public void hincbyByte() { 82 | yedis.hset(key1, key11, "5"); 83 | yedis.hincrBy(key1.getBytes(), key11.getBytes(), 2); 84 | assertEquals("7", yedis.hget(key1, key11)); 85 | } 86 | 87 | @Test 88 | public void hincbyFloat() { 89 | yedis.hset(key1, key11, "5"); 90 | yedis.hincrByFloat(key1, key11, 2); 91 | assertEquals("7", yedis.hget(key1, key11)); 92 | } 93 | 94 | @Test 95 | public void hincbyFloatByte() { 96 | yedis.hset(key1, key11, "5"); 97 | yedis.hincrByFloat(key1.getBytes(), key11.getBytes(), 2); 98 | assertEquals("7", yedis.hget(key1, key11)); 99 | } 100 | 101 | @Test 102 | public void hkeys() { 103 | Set hkeys = yedis.hkeys(key1); 104 | assertEquals(2, hkeys.size()); 105 | } 106 | 107 | @Test 108 | public void hkeysByte() { 109 | Set hkeys = yedis.hkeys(key1.getBytes()); 110 | assertEquals(2, hkeys.size()); 111 | } 112 | 113 | @Test 114 | public void hlen() { 115 | Long len = yedis.hlen(key1); 116 | assertEquals(2, len.longValue()); 117 | } 118 | 119 | @Test 120 | public void hlenByte() { 121 | Long len = yedis.hlen(key1.getBytes()); 122 | assertEquals(2, len.longValue()); 123 | } 124 | 125 | @Test 126 | public void hmget() { 127 | List list = yedis.hmget(key1, key11, key12); 128 | assertEquals(2, list.size()); 129 | assertEquals("value11", list.get(0)); 130 | assertEquals("value12", list.get(1)); 131 | } 132 | 133 | @Test 134 | public void hmgetByte() { 135 | List list = yedis.hmget(key1.getBytes(), key11.getBytes(), key12.getBytes()); 136 | assertEquals(2, list.size()); 137 | assertEquals("value11", new String(list.get(0))); 138 | assertEquals("value12", new String(list.get(1))); 139 | } 140 | 141 | @Test 142 | public void hmset() { 143 | Map map = ImmutableMap.of(key11, "value", key12, "value"); 144 | yedis.hmset(key1, map); 145 | assertEquals("value", yedis.hget(key1, key11)); 146 | assertEquals("value", yedis.hget(key1, key12)); 147 | } 148 | 149 | @Test 150 | public void hmsetByte() { 151 | Map map = ImmutableMap.of(key11.getBytes(), "value".getBytes(), key12.getBytes(), 152 | "value".getBytes()); 153 | yedis.hmset(key1.getBytes(), map); 154 | assertEquals("value", new String(yedis.hget(key1, key11))); 155 | assertEquals("value", new String(yedis.hget(key1, key12))); 156 | } 157 | 158 | @Test 159 | public void hsetnx() { 160 | yedis.hsetnx(key1, key11, "value"); 161 | assertEquals("value11", yedis.hget(key1, key11)); 162 | } 163 | 164 | @Test 165 | public void hsetnxByte() { 166 | yedis.hsetnx(key1.getBytes(), key11.getBytes(), "value".getBytes()); 167 | assertEquals("value11", yedis.hget(key1, key11)); 168 | } 169 | 170 | @Test 171 | public void hvals() { 172 | List list = yedis.hvals(key1); 173 | assertEquals(2, list.size()); 174 | } 175 | 176 | @Test 177 | public void hvalsByte() { 178 | List list = yedis.hvals(key1.getBytes()); 179 | assertEquals(2, list.size()); 180 | } 181 | } 182 | -------------------------------------------------------------------------------- /src/test/java/com/yeahmobi/yedis/group/GroupYedisKeyTest.java: -------------------------------------------------------------------------------- 1 | package com.yeahmobi.yedis.group; 2 | 3 | import java.util.List; 4 | 5 | import org.junit.After; 6 | import org.junit.Before; 7 | import org.junit.Test; 8 | 9 | public class GroupYedisKeyTest extends GroupYedisTest { 10 | 11 | private String key1 = "key1"; 12 | private String key2 = "key2"; 13 | 14 | @Before 15 | public void setup() { 16 | yedis.set(key1, "value1"); 17 | yedis.set(key2, "value2"); 18 | } 19 | 20 | @After 21 | public void tearDown() { 22 | yedis.flushAll(); 23 | } 24 | 25 | @Test 26 | public void del() { 27 | assertEquals(Long.valueOf(1), yedis.del(key1)); 28 | assertEquals(Long.valueOf(0), yedis.del("key3")); 29 | } 30 | 31 | @Test 32 | public void delByte() { 33 | assertEquals(Long.valueOf(1), yedis.del(key1.getBytes())); 34 | assertEquals(Long.valueOf(0), yedis.del("key3".getBytes())); 35 | } 36 | 37 | @Test 38 | public void delMulti() { 39 | assertEquals(Long.valueOf(2), yedis.del(key1, key2)); 40 | } 41 | 42 | @Test 43 | public void delMultiByte() { 44 | assertEquals(Long.valueOf(2), yedis.del(key1.getBytes(), key2.getBytes())); 45 | } 46 | 47 | @Test 48 | public void dumpAndRestore() { 49 | byte[] dump = yedis.dump(key1); 50 | yedis.restore("key3", 0, dump); 51 | assertEquals("value1", yedis.get("key3")); 52 | } 53 | 54 | @Test 55 | public void dumpAndRestoreByte() { 56 | byte[] dump = yedis.dump(key1.getBytes()); 57 | yedis.restore("key3".getBytes(), 0, dump); 58 | assertEquals("value1", yedis.get("key3")); 59 | } 60 | 61 | @Test 62 | public void exists() { 63 | assertEquals(true, yedis.exists(key1)); 64 | assertEquals(false, yedis.exists("key3")); 65 | } 66 | 67 | @Test 68 | public void existsByte() { 69 | assertEquals(true, yedis.exists(key1.getBytes())); 70 | assertEquals(false, yedis.exists("key3".getBytes())); 71 | } 72 | 73 | @Test 74 | public void expire() { 75 | yedis.expire(key1, 0); 76 | assertNull(yedis.get(key1)); 77 | } 78 | 79 | @Test 80 | public void expireByte() { 81 | yedis.expire(key1.getBytes(), 0); 82 | assertNull(yedis.get(key1)); 83 | } 84 | 85 | @Test 86 | public void expireAt() { 87 | yedis.expireAt(key1, 1); 88 | assertNull(yedis.get(key1)); 89 | } 90 | 91 | @Test 92 | public void expireAtByte() { 93 | yedis.expireAt(key1.getBytes(), 1); 94 | assertNull(yedis.get(key1)); 95 | } 96 | 97 | @Test 98 | public void keys() { 99 | assertEquals(2, yedis.keys("key*").size()); 100 | } 101 | 102 | @Test 103 | public void keysByte() { 104 | assertEquals(2, yedis.keys("key*".getBytes()).size()); 105 | } 106 | 107 | @Test 108 | public void move() { 109 | yedis.move(key1, 1); 110 | assertNull(yedis.get(key1)); 111 | } 112 | 113 | @Test 114 | public void moveByte() { 115 | yedis.move(key1.getBytes(), 1); 116 | assertNull(yedis.get(key1)); 117 | } 118 | 119 | @Test 120 | public void persist() { 121 | yedis.expire(key1, 10); 122 | yedis.persist(key1); 123 | assertEquals(Long.valueOf(-1), yedis.ttl(key1)); 124 | } 125 | 126 | @Test 127 | public void persistByte() { 128 | yedis.expire(key1, 10); 129 | yedis.persist(key1.getBytes()); 130 | assertEquals(Long.valueOf(-1), yedis.ttl(key1)); 131 | } 132 | 133 | @SuppressWarnings("deprecation") 134 | @Test 135 | public void pexpire() { 136 | yedis.pexpire(key1, 0); 137 | assertNull(yedis.get(key1)); 138 | } 139 | 140 | @SuppressWarnings("deprecation") 141 | @Test 142 | public void pexpireByte() { 143 | yedis.pexpire(key1.getBytes(), 0); 144 | assertNull(yedis.get(key1)); 145 | } 146 | 147 | @Test 148 | public void pexpireAt() { 149 | yedis.pexpireAt(key1, 1); 150 | assertNull(yedis.get(key1)); 151 | } 152 | 153 | @Test 154 | public void pexpireAtByte() { 155 | yedis.pexpireAt(key1.getBytes(), 1); 156 | assertNull(yedis.get(key1)); 157 | } 158 | 159 | @Test 160 | public void ttl() { 161 | yedis.expire(key1, 10); 162 | yedis.persist(key1); 163 | assertEquals(Long.valueOf(-1), yedis.ttl(key1)); 164 | } 165 | 166 | @Test 167 | public void ttlByte() { 168 | yedis.expire(key1, 10); 169 | yedis.persist(key1.getBytes()); 170 | assertEquals(Long.valueOf(-1), yedis.ttl(key1)); 171 | } 172 | 173 | @Test 174 | public void pttl() { 175 | yedis.expire(key1, 10); 176 | yedis.persist(key1); 177 | assertEquals(Long.valueOf(-1), yedis.pttl(key1)); 178 | } 179 | 180 | @Test 181 | public void pttlByte() { 182 | yedis.expire(key1, 10); 183 | yedis.persist(key1.getBytes()); 184 | assertEquals(Long.valueOf(-1), yedis.pttl(key1)); 185 | } 186 | 187 | @Test 188 | public void randomKey() { 189 | assertNotNull(yedis.randomKey()); 190 | } 191 | 192 | @Test 193 | public void rename() { 194 | yedis.rename(key1, "key3"); 195 | assertEquals("value1", yedis.get("key3")); 196 | } 197 | 198 | @Test 199 | public void renameByte() { 200 | yedis.rename(key1.getBytes(), "key3".getBytes()); 201 | assertEquals("value1", yedis.get("key3")); 202 | } 203 | 204 | @Test 205 | public void renamenx() { 206 | yedis.renamenx(key1, "key2"); 207 | assertEquals("value1", yedis.get(key1)); 208 | } 209 | 210 | @Test 211 | public void renamenxByte() { 212 | yedis.renamenx(key1.getBytes(), "key2".getBytes()); 213 | assertEquals("value1", yedis.get(key1)); 214 | } 215 | 216 | @Test 217 | public void sort() { 218 | yedis.lpush("key3", "1", "2"); 219 | List sortList = yedis.sort("key3"); 220 | assertEquals("1", sortList.get(0)); 221 | } 222 | 223 | @Test 224 | public void sortByte() { 225 | yedis.lpush("key3", "1", "2"); 226 | List sortList = yedis.sort("key3".getBytes()); 227 | assertEquals("1", new String(sortList.get(0))); 228 | } 229 | 230 | @Test 231 | public void type() { 232 | assertEquals("string", yedis.type(key1)); 233 | } 234 | 235 | @Test 236 | public void typeByte() { 237 | assertEquals("string", yedis.type(key1.getBytes())); 238 | } 239 | 240 | } 241 | -------------------------------------------------------------------------------- /src/test/java/com/yeahmobi/yedis/group/GroupYedisListTest.java: -------------------------------------------------------------------------------- 1 | package com.yeahmobi.yedis.group; 2 | 3 | import java.util.List; 4 | 5 | import org.junit.After; 6 | import org.junit.Before; 7 | import org.junit.Test; 8 | 9 | import redis.clients.jedis.BinaryClient.LIST_POSITION; 10 | 11 | public class GroupYedisListTest extends GroupYedisTest { 12 | 13 | private static final int TIMEOUT = 1000; 14 | private String list1 = "list_1"; 15 | private String list2 = "list_2"; 16 | private String list3 = "list_3"; 17 | 18 | @Before 19 | public void setup() { 20 | yedis.lpush(list1, "value5", "value4", "value3", "value2", "value1"); 21 | yedis.lpush(list2, "value7", "value6", "value3", "value2", "value1"); 22 | yedis.lpush(list3, "value9", "value8", "value3", "value2", "value1"); 23 | } 24 | 25 | @After 26 | public void tearDown() { 27 | yedis.del(list1, list2, list3); 28 | } 29 | 30 | @Test 31 | public void blpop() { 32 | assertEquals("value1", yedis.blpop(TIMEOUT, list1).get(1)); 33 | } 34 | 35 | @Test 36 | public void blpopByte() { 37 | assertEquals("value1", new String(yedis.blpop(TIMEOUT, list1.getBytes()).get(1))); 38 | } 39 | 40 | @Test 41 | public void brpop() { 42 | assertEquals("value5", yedis.brpop(TIMEOUT, list1).get(1)); 43 | } 44 | 45 | @Test 46 | public void brpopByte() { 47 | assertEquals("value5", new String(yedis.brpop(TIMEOUT, list1.getBytes()).get(1))); 48 | } 49 | 50 | @Test 51 | public void brpoplpush() { 52 | assertEquals("value5", yedis.brpoplpush(list1, list2, TIMEOUT)); 53 | } 54 | 55 | @Test 56 | public void brpoplpushByte() { 57 | assertEquals("value5", new String(yedis.brpoplpush(list1.getBytes(), list2.getBytes(), TIMEOUT))); 58 | } 59 | 60 | @Test 61 | public void lindex() { 62 | assertEquals("value1", yedis.lindex(list1, 0)); 63 | } 64 | 65 | @Test 66 | public void lindexByte() { 67 | assertEquals("value1", new String(yedis.lindex(list1.getBytes(), 0))); 68 | } 69 | 70 | @Test 71 | public void llen() { 72 | assertEquals(Long.valueOf(5L), yedis.llen(list1)); 73 | } 74 | 75 | @Test 76 | public void llenByte() { 77 | assertEquals(Long.valueOf(5L), yedis.llen(list1.getBytes())); 78 | } 79 | 80 | @Test 81 | public void linsert() { 82 | assertEquals(Long.valueOf(6L), yedis.linsert(list1, LIST_POSITION.AFTER, "value1", "value")); 83 | } 84 | 85 | @Test 86 | public void linsertByte() { 87 | assertEquals(Long.valueOf(6L), 88 | yedis.linsert(list1.getBytes(), LIST_POSITION.AFTER, "value1".getBytes(), "value".getBytes())); 89 | } 90 | 91 | @Test 92 | public void lpop() { 93 | assertEquals("value1", yedis.lpop(list1)); 94 | } 95 | 96 | @Test 97 | public void lpopByte() { 98 | assertEquals("value1", new String(yedis.lpop(list1.getBytes()))); 99 | } 100 | 101 | @Test 102 | public void lpush() { 103 | assertEquals(Long.valueOf(6L), yedis.lpush(list1, "value")); 104 | } 105 | 106 | @Test 107 | public void lpushByte() { 108 | assertEquals(Long.valueOf(6L), yedis.lpush(list1.getBytes(), "value".getBytes())); 109 | } 110 | 111 | @Test 112 | public void lpushx() { 113 | assertEquals(Long.valueOf(0L), yedis.lpushx("list4", "value")); 114 | } 115 | 116 | @Test 117 | public void lpushxByte() { 118 | assertEquals(Long.valueOf(0L), yedis.lpushx("list4".getBytes(), "value".getBytes())); 119 | } 120 | 121 | @Test 122 | public void lrange() { 123 | List lrange = yedis.lrange(list1, 0, -1); 124 | assertEquals(5, lrange.size()); 125 | } 126 | 127 | @Test 128 | public void lrangeByte() { 129 | List lrange = yedis.lrange(list1.getBytes(), 0, -1); 130 | assertEquals(5, lrange.size()); 131 | } 132 | 133 | @Test 134 | public void lrem() { 135 | assertEquals(Long.valueOf(1), yedis.lrem(list1, 1, "value1")); 136 | } 137 | 138 | @Test 139 | public void lremByte() { 140 | assertEquals(Long.valueOf(1), yedis.lrem(list1.getBytes(), 1, "value1".getBytes())); 141 | } 142 | 143 | @Test 144 | public void lset() { 145 | yedis.lset(list1, 1, "value"); 146 | assertEquals("value", yedis.lindex(list1, 1)); 147 | } 148 | 149 | @Test 150 | public void lsetByte() { 151 | yedis.lset(list1.getBytes(), 1, "value".getBytes()); 152 | assertEquals("value", yedis.lindex(list1, 1)); 153 | } 154 | 155 | @Test 156 | public void ltrim() { 157 | yedis.ltrim(list1, 0, 1); 158 | assertEquals(Long.valueOf(2), yedis.llen(list1)); 159 | } 160 | 161 | @Test 162 | public void ltrimByte() { 163 | yedis.ltrim(list1.getBytes(), 0, 1); 164 | assertEquals(Long.valueOf(2), yedis.llen(list1)); 165 | } 166 | 167 | @Test 168 | public void rpop() { 169 | assertEquals("value5", yedis.rpop(list1)); 170 | } 171 | 172 | @Test 173 | public void rpopByte() { 174 | assertEquals("value5", new String(yedis.rpop(list1.getBytes()))); 175 | } 176 | 177 | @Test 178 | public void rpoplpush() { 179 | assertEquals("value5", yedis.rpoplpush(list1, list2)); 180 | } 181 | 182 | @Test 183 | public void rpoplpushByte() { 184 | assertEquals("value5", new String(yedis.rpoplpush(list1.getBytes(), list2.getBytes()))); 185 | } 186 | 187 | @Test 188 | public void rpush() { 189 | assertEquals(Long.valueOf(6L), yedis.rpush(list1, "value")); 190 | } 191 | 192 | @Test 193 | public void rpushByte() { 194 | assertEquals(Long.valueOf(6L), yedis.rpush(list1.getBytes(), "value".getBytes())); 195 | } 196 | 197 | @Test 198 | public void rpushx() { 199 | assertEquals(Long.valueOf(0L), yedis.rpushx("list4", "value")); 200 | } 201 | 202 | @Test 203 | public void rpushxByte() { 204 | assertEquals(Long.valueOf(0L), yedis.rpushx("list4".getBytes(), "value".getBytes())); 205 | } 206 | 207 | @Test 208 | public void flushAll() { 209 | yedis.flushAll(); 210 | assertEquals(false, yedis.exists(list1)); 211 | } 212 | 213 | } 214 | -------------------------------------------------------------------------------- /src/test/java/com/yeahmobi/yedis/group/GroupYedisSetTest.java: -------------------------------------------------------------------------------- 1 | package com.yeahmobi.yedis.group; 2 | 3 | import org.junit.After; 4 | import org.junit.Before; 5 | import org.junit.Test; 6 | 7 | public class GroupYedisSetTest extends GroupYedisTest { 8 | 9 | private String key1 = "key1"; 10 | private String key2 = "key2"; 11 | 12 | @Before 13 | public void setup() { 14 | yedis.sadd(key1, "value1", "value2"); 15 | yedis.sadd(key2, "value3", "value4"); 16 | } 17 | 18 | @After 19 | public void tearDown() { 20 | yedis.flushAll(); 21 | } 22 | 23 | @Test 24 | public void sadd() { 25 | yedis.sadd(key1, "value3", "value4"); 26 | assertEquals(Long.valueOf(4), yedis.scard(key1)); 27 | } 28 | 29 | @Test 30 | public void saddByte() { 31 | yedis.sadd(key1.getBytes(), "value3".getBytes(), "value4".getBytes()); 32 | assertEquals(Long.valueOf(4), yedis.scard(key1)); 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/test/java/com/yeahmobi/yedis/group/GroupYedisStringTest.java: -------------------------------------------------------------------------------- 1 | package com.yeahmobi.yedis.group; 2 | 3 | import java.util.List; 4 | 5 | import org.junit.After; 6 | import org.junit.Before; 7 | import org.junit.Test; 8 | 9 | import redis.clients.jedis.BitOP; 10 | 11 | public class GroupYedisStringTest extends GroupYedisTest { 12 | 13 | private String key1 = "key1"; 14 | private String key2 = "key2"; 15 | 16 | @Before 17 | public void setup() { 18 | yedis.set(key1, "value1"); 19 | yedis.set(key2, "value2"); 20 | } 21 | 22 | @After 23 | public void tearDown() { 24 | yedis.flushAll(); 25 | } 26 | 27 | @Test 28 | public void append() { 29 | yedis.append(key1, "_add"); 30 | assertEquals("value1_add", yedis.get(key1)); 31 | } 32 | 33 | @Test 34 | public void appendByte() { 35 | yedis.append(key1.getBytes(), "_add".getBytes()); 36 | assertEquals("value1_add", yedis.get(key1)); 37 | } 38 | 39 | @Test 40 | public void bitcount() { 41 | yedis.set(key1, ""); 42 | yedis.setbit(key1, 0, true); 43 | assertEquals(Long.valueOf(1), yedis.bitcount(key1)); 44 | } 45 | 46 | @Test 47 | public void bitcountByte() { 48 | yedis.set(key1, ""); 49 | yedis.setbit(key1, 0, true); 50 | assertEquals(Long.valueOf(1), yedis.bitcount(key1.getBytes())); 51 | } 52 | 53 | @Test 54 | public void bitop() { 55 | yedis.setbit("key3", 0, true); 56 | yedis.setbit("key4", 1, true); 57 | yedis.bitop(BitOP.AND, "key5", "key3", "key4"); 58 | assertFalse(yedis.getbit("key5", 1)); 59 | yedis.bitop(BitOP.OR, "key5", "key3", "key4"); 60 | assertTrue(yedis.getbit("key5", 1)); 61 | } 62 | 63 | @Test 64 | public void bitopByte() { 65 | yedis.setbit("key3", 0, true); 66 | yedis.setbit("key4", 1, true); 67 | yedis.bitop(BitOP.AND, "key5".getBytes(), "key3".getBytes(), "key4".getBytes()); 68 | assertFalse(yedis.getbit("key5", 1)); 69 | yedis.bitop(BitOP.OR, "key5".getBytes(), "key3".getBytes(), "key4".getBytes()); 70 | assertTrue(yedis.getbit("key5", 1)); 71 | } 72 | 73 | @Test 74 | public void decr() { 75 | yedis.set(key1, "5"); 76 | yedis.decr(key1); 77 | assertEquals("4", yedis.get(key1)); 78 | } 79 | 80 | @Test 81 | public void decrByte() { 82 | yedis.set(key1, "5"); 83 | yedis.decr(key1.getBytes()); 84 | assertEquals("4", yedis.get(key1)); 85 | } 86 | 87 | @Test 88 | public void decrBy() { 89 | yedis.set(key1, "5"); 90 | yedis.decrBy(key1, 2); 91 | assertEquals("3", yedis.get(key1)); 92 | } 93 | 94 | @Test 95 | public void decrByByte() { 96 | yedis.set(key1, "5"); 97 | yedis.decrBy(key1.getBytes(), 2); 98 | assertEquals("3", yedis.get(key1)); 99 | } 100 | 101 | @Test 102 | public void getrange() { 103 | assertEquals("value1", yedis.getrange(key1, 0, -1)); 104 | } 105 | 106 | @Test 107 | public void getrangeByte() { 108 | assertEquals("value1", new String(yedis.getrange(key1.getBytes(), 0, -1))); 109 | } 110 | 111 | @Test 112 | public void getset() { 113 | assertEquals("value1", yedis.getSet(key1, "value")); 114 | assertEquals("value", yedis.get(key1)); 115 | } 116 | 117 | @Test 118 | public void getsetByte() { 119 | assertEquals("value1", new String(yedis.getSet(key1.getBytes(), "value".getBytes()))); 120 | assertEquals("value", yedis.get(key1)); 121 | } 122 | 123 | @Test 124 | public void incr() { 125 | yedis.set(key1, "5"); 126 | yedis.incr(key1); 127 | assertEquals("6", yedis.get(key1)); 128 | } 129 | 130 | @Test 131 | public void incrByte() { 132 | yedis.set(key1, "5"); 133 | yedis.incr(key1.getBytes()); 134 | assertEquals("6", yedis.get(key1)); 135 | } 136 | 137 | @Test 138 | public void incrBy() { 139 | yedis.set(key1, "5"); 140 | yedis.incrBy(key1, 2); 141 | assertEquals("7", yedis.get(key1)); 142 | } 143 | 144 | @Test 145 | public void incrByByte() { 146 | yedis.set(key1, "5"); 147 | yedis.incrBy(key1.getBytes(), 2); 148 | assertEquals("7", yedis.get(key1)); 149 | } 150 | 151 | @Test 152 | public void msetAndGet() { 153 | yedis.mset(key1, "5", key2, "6"); 154 | List list = yedis.mget(key1, key2); 155 | assertEquals("5", list.get(0)); 156 | assertEquals("6", list.get(1)); 157 | } 158 | 159 | @Test 160 | public void msetAndGetByte() { 161 | yedis.mset(key1, "5", key2, "6"); 162 | List list = yedis.mget(key1.getBytes(), key2.getBytes()); 163 | assertEquals("5", new String(list.get(0))); 164 | assertEquals("6", new String(list.get(1))); 165 | } 166 | 167 | @Test 168 | public void msetnx() { 169 | yedis.msetnx(key1, "5", key2, "6"); 170 | assertEquals("value1", yedis.get(key1)); 171 | assertEquals("value2", yedis.get(key2)); 172 | } 173 | 174 | @Test 175 | public void msetnxByte() { 176 | yedis.msetnx(key1.getBytes(), "5".getBytes(), key2.getBytes(), "6".getBytes()); 177 | assertEquals("value1", yedis.get(key1)); 178 | assertEquals("value2", yedis.get(key2)); 179 | } 180 | 181 | @Test 182 | public void psetex() { 183 | yedis.psetex(key1, 1000, "5"); 184 | assertTrue(yedis.pttl(key1).compareTo(1000L) <= 0); 185 | } 186 | 187 | @Test 188 | public void psetexByte() { 189 | yedis.psetex(key1.getBytes(), 1000, "5".getBytes()); 190 | assertTrue(yedis.pttl(key1).compareTo(1000L) <= 0); 191 | } 192 | 193 | @Test 194 | public void setex() { 195 | yedis.setex(key1, 10, "5"); 196 | assertTrue(yedis.ttl(key1).compareTo(10L) <= 0); 197 | } 198 | 199 | @Test 200 | public void setexByte() { 201 | yedis.setex(key1.getBytes(), 10, "5".getBytes()); 202 | assertTrue(yedis.ttl(key1).compareTo(10L) <= 0); 203 | } 204 | 205 | @Test 206 | public void setnx() { 207 | yedis.setnx(key1, "5"); 208 | assertEquals("value1", yedis.get(key1)); 209 | } 210 | 211 | @Test 212 | public void setnxByte() { 213 | yedis.setnx(key1.getBytes(), "5".getBytes()); 214 | assertEquals("value1", yedis.get(key1)); 215 | } 216 | 217 | @Test 218 | public void setrange() { 219 | yedis.setrange(key1, 0, "a"); 220 | assertEquals("aalue1", yedis.get(key1)); 221 | } 222 | 223 | @Test 224 | public void setrangeByte() { 225 | yedis.setrange(key1.getBytes(), 0, "a".getBytes()); 226 | assertEquals("aalue1", yedis.get(key1)); 227 | } 228 | 229 | @Test 230 | public void strlen() { 231 | assertEquals(Long.valueOf(6), yedis.strlen(key1)); 232 | } 233 | 234 | @Test 235 | public void strlenByte() { 236 | assertEquals(Long.valueOf(6), yedis.strlen(key1.getBytes())); 237 | } 238 | 239 | } 240 | -------------------------------------------------------------------------------- /src/test/java/com/yeahmobi/yedis/group/GroupYedisTest.java: -------------------------------------------------------------------------------- 1 | package com.yeahmobi.yedis.group; 2 | 3 | import java.io.IOException; 4 | import java.util.ArrayList; 5 | import java.util.List; 6 | 7 | import org.junit.AfterClass; 8 | import org.junit.BeforeClass; 9 | 10 | import com.yeahmobi.yedis.base.YedisTestBase; 11 | import com.yeahmobi.yedis.common.ServerInfo; 12 | 13 | public abstract class GroupYedisTest extends YedisTestBase { 14 | 15 | protected static GroupYedis yedis; 16 | 17 | @BeforeClass 18 | public static void initGroupYedis() throws IOException { 19 | ServerInfo writeSeverInfo = new ServerInfo(host, port); 20 | ServerInfo readSeverInfo = new ServerInfo(host, port); 21 | List readSeverInfoList = new ArrayList(); 22 | readSeverInfoList.add(readSeverInfo); 23 | 24 | GroupConfig groupConfig = new GroupConfig(writeSeverInfo, readSeverInfoList); 25 | yedis = new GroupYedis(groupConfig); 26 | } 27 | 28 | @AfterClass 29 | public static void shutdown(){ 30 | yedis.close(); 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/test/java/com/yeahmobi/yedis/loadbalance/RandomLoadBalancerTest.java: -------------------------------------------------------------------------------- 1 | package com.yeahmobi.yedis.loadbalance; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Collections; 5 | import java.util.List; 6 | 7 | import org.junit.BeforeClass; 8 | import org.junit.Test; 9 | 10 | import com.yeahmobi.yedis.atomic.AtomConfig; 11 | import com.yeahmobi.yedis.atomic.Yedis; 12 | import com.yeahmobi.yedis.base.YedisTestBase; 13 | 14 | public class RandomLoadBalancerTest extends YedisTestBase { 15 | 16 | private static List yedisList = new ArrayList(); 17 | 18 | private static Yedis yedis1; 19 | private static Yedis yedis2; 20 | 21 | @BeforeClass 22 | public static void init() { 23 | AtomConfig config1 = new AtomConfig(host, port); 24 | yedis1 = new Yedis(config1); 25 | AtomConfig config2 = new AtomConfig(host, port); 26 | yedis2 = new Yedis(config2); 27 | yedisList.add(yedis1); 28 | yedisList.add(yedis2); 29 | } 30 | 31 | private RandomLoadBalancer lb = new RandomLoadBalancer(yedisList); 32 | 33 | @Test 34 | public void testType() { 35 | assertEquals(LoadBalancer.Type.RANDOM, lb.getType()); 36 | } 37 | 38 | @Test 39 | public void testRoute() { 40 | Yedis yedis = lb.route(); 41 | assertTrue(yedis == yedis1 || yedis == yedis2); 42 | } 43 | 44 | @Test(expected = IllegalArgumentException.class) 45 | public void testException() { 46 | new RandomLoadBalancer(null); 47 | } 48 | 49 | @SuppressWarnings("unchecked") 50 | @Test(expected = IllegalArgumentException.class) 51 | public void testException2() { 52 | new RandomLoadBalancer(Collections.EMPTY_LIST); 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /src/test/java/com/yeahmobi/yedis/loadbalance/RoundRobinLoadBalancerTest.java: -------------------------------------------------------------------------------- 1 | package com.yeahmobi.yedis.loadbalance; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Collections; 5 | import java.util.List; 6 | 7 | import org.junit.BeforeClass; 8 | import org.junit.Test; 9 | 10 | import com.yeahmobi.yedis.atomic.AtomConfig; 11 | import com.yeahmobi.yedis.atomic.Yedis; 12 | import com.yeahmobi.yedis.base.YedisTestBase; 13 | 14 | public class RoundRobinLoadBalancerTest extends YedisTestBase { 15 | 16 | private static List yedisList = new ArrayList(); 17 | 18 | private static Yedis yedis1; 19 | private static Yedis yedis2; 20 | 21 | @BeforeClass 22 | public static void init() { 23 | AtomConfig config1 = new AtomConfig(host, port); 24 | yedis1 = new Yedis(config1); 25 | AtomConfig config2 = new AtomConfig(host, port); 26 | yedis2 = new Yedis(config2); 27 | yedisList.add(yedis1); 28 | yedisList.add(yedis2); 29 | 30 | } 31 | 32 | private RoundRobinLoadBalancer lb = new RoundRobinLoadBalancer(yedisList); 33 | 34 | @Test 35 | public void testType() { 36 | assertEquals(LoadBalancer.Type.ROUND_ROBIN, lb.getType()); 37 | } 38 | 39 | @Test 40 | public void testRoute() { 41 | Yedis yedis = lb.route(); 42 | assertTrue(yedis == yedis1 || yedis == yedis2); 43 | } 44 | 45 | @Test(expected = IllegalArgumentException.class) 46 | public void testException() { 47 | new RoundRobinLoadBalancer(null); 48 | } 49 | 50 | @SuppressWarnings("unchecked") 51 | @Test(expected = IllegalArgumentException.class) 52 | public void testException2() { 53 | new RoundRobinLoadBalancer(Collections.EMPTY_LIST); 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /src/test/java/com/yeahmobi/yedis/shard/AbstractShardedYedisTest.java: -------------------------------------------------------------------------------- 1 | package com.yeahmobi.yedis.shard; 2 | 3 | import java.io.IOException; 4 | import java.util.ArrayList; 5 | import java.util.List; 6 | 7 | import org.junit.AfterClass; 8 | import org.junit.BeforeClass; 9 | 10 | import com.yeahmobi.yedis.base.DoubleServerYedisTestBase; 11 | import com.yeahmobi.yedis.common.ServerInfo; 12 | import com.yeahmobi.yedis.group.GroupConfig; 13 | import com.yeahmobi.yedis.group.GroupYedis; 14 | 15 | public abstract class AbstractShardedYedisTest extends DoubleServerYedisTestBase { 16 | 17 | protected static ShardedYedis yedis; 18 | 19 | protected static List groups; 20 | 21 | @BeforeClass 22 | public static void initGroupYedis() throws IOException { 23 | startRedisServer(); 24 | GroupYedis groupYedis1 = buildGroupYedis(port1); 25 | GroupYedis groupYedis2 = buildGroupYedis(port2); 26 | groups = new ArrayList(); 27 | groups.add(groupYedis1); 28 | groups.add(groupYedis2); 29 | yedis = new ShardedYedis(groups, ShardingAlgorithm.SIMPLE_HASH, new DefaultHashCodeCoputingStrategy()); 30 | } 31 | 32 | @AfterClass 33 | public static void shutdown() throws InterruptedException { 34 | yedis.close(); 35 | stopRedisServer(); 36 | } 37 | 38 | private static GroupYedis buildGroupYedis(int port) { 39 | ServerInfo writeSeverInfo = new ServerInfo(host, port); 40 | ServerInfo readSeverInfo = new ServerInfo(host, port); 41 | List readSeverInfoList = new ArrayList(); 42 | readSeverInfoList.add(readSeverInfo); 43 | 44 | GroupConfig groupConfig = new GroupConfig(writeSeverInfo, readSeverInfoList); 45 | GroupYedis groupYedis = new GroupYedis(groupConfig); 46 | return groupYedis; 47 | } 48 | 49 | void flushAll() { 50 | for(GroupYedis groupYedis:groups){ 51 | groupYedis.flushAll(); 52 | } 53 | } 54 | 55 | 56 | } 57 | -------------------------------------------------------------------------------- /src/test/java/com/yeahmobi/yedis/shard/DefaultHashCodeCoputingStrategy.java: -------------------------------------------------------------------------------- 1 | package com.yeahmobi.yedis.shard; 2 | 3 | public class DefaultHashCodeCoputingStrategy implements HashCodeComputingStrategy{ 4 | 5 | @Override 6 | public int hash(String key) { 7 | return key.hashCode(); 8 | } 9 | 10 | } 11 | -------------------------------------------------------------------------------- /src/test/java/com/yeahmobi/yedis/shard/ShardedYedisHashTest.java: -------------------------------------------------------------------------------- 1 | package com.yeahmobi.yedis.shard; 2 | 3 | import java.util.List; 4 | import java.util.Map; 5 | import java.util.Set; 6 | 7 | import org.junit.After; 8 | import org.junit.Before; 9 | import org.junit.Test; 10 | 11 | import com.google.common.collect.ImmutableMap; 12 | 13 | public class ShardedYedisHashTest extends AbstractShardedYedisTest { 14 | 15 | private String key1 = "key1"; 16 | private String key2 = "key2"; 17 | private String key11 = "key11"; 18 | private String key12 = "key12"; 19 | private String key21 = "key21"; 20 | private String key22 = "key22"; 21 | 22 | @Before 23 | public void setup() { 24 | yedis.hset(key1, key11, "value11"); 25 | yedis.hset(key1, key12, "value12"); 26 | yedis.hset(key2, key21, "value21"); 27 | yedis.hset(key2, key22, "value22"); 28 | } 29 | 30 | @After 31 | public void tearDown() { 32 | flushAll(); 33 | } 34 | 35 | 36 | @Test 37 | public void hgetAndDel() { 38 | assertEquals(Long.valueOf(1), yedis.hdel(key1, key11)); 39 | assertEquals(null, yedis.hget(key1, key11)); 40 | } 41 | 42 | @Test 43 | public void hgetAndDelByte() { 44 | assertEquals(Long.valueOf(1), yedis.hdel(key1.getBytes(), key11.getBytes())); 45 | assertEquals(null, yedis.hget(key1.getBytes(), key11.getBytes())); 46 | } 47 | 48 | @Test 49 | public void hexists() { 50 | assertTrue(yedis.hexists(key1, key11)); 51 | assertFalse(yedis.hexists(key1, "nokey")); 52 | } 53 | 54 | @Test 55 | public void hexistsByte() { 56 | assertTrue(yedis.hexists(key1.getBytes(), key11.getBytes())); 57 | assertFalse(yedis.hexists(key1.getBytes(), "nokey".getBytes())); 58 | } 59 | 60 | @Test 61 | public void hgetall() { 62 | Map map = yedis.hgetAll(key1); 63 | assertEquals(2, map.size()); 64 | assertEquals("value11", map.get(key11)); 65 | } 66 | 67 | @Test 68 | public void hgetallByte() { 69 | Map map = yedis.hgetAll(key1.getBytes()); 70 | assertEquals(2, map.size()); 71 | assertEquals("value11", new String(map.get(key11.getBytes()))); 72 | } 73 | 74 | @Test 75 | public void hincby() { 76 | yedis.hset(key1, key11, "5"); 77 | yedis.hincrBy(key1, key11, 2); 78 | assertEquals("7", yedis.hget(key1, key11)); 79 | } 80 | 81 | @Test 82 | public void hincbyByte() { 83 | yedis.hset(key1, key11, "5"); 84 | yedis.hincrBy(key1.getBytes(), key11.getBytes(), 2); 85 | assertEquals("7", yedis.hget(key1, key11)); 86 | } 87 | 88 | @Test 89 | public void hincbyFloatByte() { 90 | yedis.hset(key1, key11, "5"); 91 | yedis.hincrByFloat(key1.getBytes(), key11.getBytes(), 2); 92 | assertEquals("7", yedis.hget(key1, key11)); 93 | } 94 | 95 | @Test 96 | public void hkeys() { 97 | Set hkeys = yedis.hkeys(key1); 98 | assertEquals(2, hkeys.size()); 99 | } 100 | 101 | @Test 102 | public void hkeysByte() { 103 | Set hkeys = yedis.hkeys(key1.getBytes()); 104 | assertEquals(2, hkeys.size()); 105 | } 106 | 107 | @Test 108 | public void hlen() { 109 | Long len = yedis.hlen(key1); 110 | assertEquals(2, len.longValue()); 111 | } 112 | 113 | @Test 114 | public void hlenByte() { 115 | Long len = yedis.hlen(key1.getBytes()); 116 | assertEquals(2, len.longValue()); 117 | } 118 | 119 | @Test 120 | public void hmget() { 121 | List list = yedis.hmget(key1, key11, key12); 122 | assertEquals(2, list.size()); 123 | assertEquals("value11", list.get(0)); 124 | assertEquals("value12", list.get(1)); 125 | } 126 | 127 | @Test 128 | public void hmgetByte() { 129 | List list = yedis.hmget(key1.getBytes(), key11.getBytes(), key12.getBytes()); 130 | assertEquals(2, list.size()); 131 | assertEquals("value11", new String(list.get(0))); 132 | assertEquals("value12", new String(list.get(1))); 133 | } 134 | 135 | @Test 136 | public void hmset() { 137 | Map map = ImmutableMap.of(key11, "value", key12, "value"); 138 | yedis.hmset(key1, map); 139 | assertEquals("value", yedis.hget(key1, key11)); 140 | assertEquals("value", yedis.hget(key1, key12)); 141 | } 142 | 143 | @Test 144 | public void hmsetByte() { 145 | Map map = ImmutableMap.of(key11.getBytes(), "value".getBytes(), key12.getBytes(), 146 | "value".getBytes()); 147 | yedis.hmset(key1.getBytes(), map); 148 | assertEquals("value", new String(yedis.hget(key1, key11))); 149 | assertEquals("value", new String(yedis.hget(key1, key12))); 150 | } 151 | 152 | @Test 153 | public void hsetnx() { 154 | yedis.hsetnx(key1, key11, "value"); 155 | assertEquals("value11", yedis.hget(key1, key11)); 156 | } 157 | 158 | @Test 159 | public void hsetnxByte() { 160 | yedis.hsetnx(key1.getBytes(), key11.getBytes(), "value".getBytes()); 161 | assertEquals("value11", yedis.hget(key1, key11)); 162 | } 163 | 164 | @Test 165 | public void hvals() { 166 | List list = yedis.hvals(key1); 167 | assertEquals(2, list.size()); 168 | } 169 | 170 | } 171 | -------------------------------------------------------------------------------- /src/test/java/com/yeahmobi/yedis/shard/ShardedYedisKeyTest.java: -------------------------------------------------------------------------------- 1 | package com.yeahmobi.yedis.shard; 2 | 3 | import java.util.List; 4 | 5 | import org.junit.After; 6 | import org.junit.Before; 7 | import org.junit.Test; 8 | 9 | public class ShardedYedisKeyTest extends AbstractShardedYedisTest { 10 | 11 | private String key1 = "key1"; 12 | private String key2 = "key2"; 13 | 14 | @Before 15 | public void setup() { 16 | yedis.set(key1, "value1"); 17 | yedis.set(key2, "value2"); 18 | } 19 | 20 | @After 21 | public void tearDown() { 22 | flushAll(); 23 | } 24 | 25 | @Test 26 | public void del() { 27 | assertEquals(Long.valueOf(1), yedis.del(key1)); 28 | assertEquals(Long.valueOf(0), yedis.del("key3")); 29 | } 30 | 31 | @Test 32 | public void delByte() { 33 | assertEquals(Long.valueOf(1), yedis.del(key1.getBytes())); 34 | assertEquals(Long.valueOf(0), yedis.del("key3".getBytes())); 35 | } 36 | 37 | @Test 38 | public void exists() { 39 | assertEquals(true, yedis.exists(key1)); 40 | assertEquals(false, yedis.exists("key3")); 41 | } 42 | 43 | @Test 44 | public void existsByte() { 45 | assertEquals(true, yedis.exists(key1.getBytes())); 46 | assertEquals(false, yedis.exists("key3".getBytes())); 47 | } 48 | 49 | @Test 50 | public void expire() { 51 | yedis.expire(key1, 0); 52 | assertNull(yedis.get(key1)); 53 | } 54 | 55 | @Test 56 | public void expireByte() { 57 | yedis.expire(key1.getBytes(), 0); 58 | assertNull(yedis.get(key1)); 59 | } 60 | 61 | @Test 62 | public void expireAt() { 63 | yedis.expireAt(key1, 1); 64 | assertNull(yedis.get(key1)); 65 | } 66 | 67 | @Test 68 | public void expireAtByte() { 69 | yedis.expireAt(key1.getBytes(), 1); 70 | assertNull(yedis.get(key1)); 71 | } 72 | 73 | @Test 74 | public void move() { 75 | yedis.move(key1, 1); 76 | assertNull(yedis.get(key1)); 77 | } 78 | 79 | @Test 80 | public void moveByte() { 81 | yedis.move(key1.getBytes(), 1); 82 | assertNull(yedis.get(key1)); 83 | } 84 | 85 | @Test 86 | public void persist() { 87 | yedis.expire(key1, 10); 88 | yedis.persist(key1); 89 | assertEquals(Long.valueOf(-1), yedis.ttl(key1)); 90 | } 91 | 92 | @Test 93 | public void persistByte() { 94 | yedis.expire(key1, 10); 95 | yedis.persist(key1.getBytes()); 96 | assertEquals(Long.valueOf(-1), yedis.ttl(key1)); 97 | } 98 | 99 | @Test 100 | public void ttl() { 101 | yedis.expire(key1, 10); 102 | yedis.persist(key1); 103 | assertEquals(Long.valueOf(-1), yedis.ttl(key1)); 104 | } 105 | 106 | @Test 107 | public void ttlByte() { 108 | yedis.expire(key1, 10); 109 | yedis.persist(key1.getBytes()); 110 | assertEquals(Long.valueOf(-1), yedis.ttl(key1)); 111 | } 112 | 113 | @Test 114 | public void sort() { 115 | yedis.lpush("key3", "1", "2"); 116 | List sortList = yedis.sort("key3"); 117 | assertEquals("1", sortList.get(0)); 118 | } 119 | 120 | @Test 121 | public void sortByte() { 122 | yedis.lpush("key3", "1", "2"); 123 | List sortList = yedis.sort("key3".getBytes()); 124 | assertEquals("1", new String(sortList.get(0))); 125 | } 126 | 127 | @Test 128 | public void type() { 129 | assertEquals("string", yedis.type(key1)); 130 | } 131 | 132 | @Test 133 | public void typeByte() { 134 | assertEquals("string", yedis.type(key1.getBytes())); 135 | } 136 | 137 | } 138 | -------------------------------------------------------------------------------- /src/test/java/com/yeahmobi/yedis/shard/ShardedYedisListTest.java: -------------------------------------------------------------------------------- 1 | package com.yeahmobi.yedis.shard; 2 | 3 | import java.util.List; 4 | 5 | import org.junit.After; 6 | import org.junit.Before; 7 | import org.junit.Test; 8 | 9 | import redis.clients.jedis.BinaryClient.LIST_POSITION; 10 | 11 | public class ShardedYedisListTest extends AbstractShardedYedisTest { 12 | 13 | private String list1 = "list_1"; 14 | private String list2 = "list_2"; 15 | private String list3 = "list_3"; 16 | 17 | @Before 18 | public void setup() { 19 | yedis.lpush(list1, "value5", "value4", "value3", "value2", "value1"); 20 | yedis.lpush(list2, "value7", "value6", "value3", "value2", "value1"); 21 | yedis.lpush(list3, "value9", "value8", "value3", "value2", "value1"); 22 | } 23 | 24 | @After 25 | public void tearDown() { 26 | flushAll(); 27 | } 28 | 29 | 30 | @Test 31 | public void lindex() { 32 | assertEquals("value1", yedis.lindex(list1, 0)); 33 | } 34 | 35 | @Test 36 | public void lindexByte() { 37 | assertEquals("value1", new String(yedis.lindex(list1.getBytes(), 0))); 38 | } 39 | 40 | @Test 41 | public void llen() { 42 | assertEquals(Long.valueOf(5L), yedis.llen(list1)); 43 | } 44 | 45 | @Test 46 | public void llenByte() { 47 | assertEquals(Long.valueOf(5L), yedis.llen(list1.getBytes())); 48 | } 49 | 50 | @Test 51 | public void linsert() { 52 | assertEquals(Long.valueOf(6L), yedis.linsert(list1, LIST_POSITION.AFTER, "value1", "value")); 53 | } 54 | 55 | @Test 56 | public void linsertByte() { 57 | assertEquals(Long.valueOf(6L), 58 | yedis.linsert(list1.getBytes(), LIST_POSITION.AFTER, "value1".getBytes(), "value".getBytes())); 59 | } 60 | 61 | @Test 62 | public void lpop() { 63 | assertEquals("value1", yedis.lpop(list1)); 64 | } 65 | 66 | @Test 67 | public void lpopByte() { 68 | assertEquals("value1", new String(yedis.lpop(list1.getBytes()))); 69 | } 70 | 71 | @Test 72 | public void lpush() { 73 | assertEquals(Long.valueOf(6L), yedis.lpush(list1, "value")); 74 | } 75 | 76 | @Test 77 | public void lpushByte() { 78 | assertEquals(Long.valueOf(6L), yedis.lpush(list1.getBytes(), "value".getBytes())); 79 | } 80 | 81 | @Test 82 | public void lpushx() { 83 | assertEquals(Long.valueOf(0L), yedis.lpushx("list4", "value")); 84 | } 85 | 86 | @Test 87 | public void lpushxByte() { 88 | assertEquals(Long.valueOf(0L), yedis.lpushx("list4".getBytes(), "value".getBytes())); 89 | } 90 | 91 | @Test 92 | public void lrange() { 93 | List lrange = yedis.lrange(list1, 0, -1); 94 | assertEquals(5, lrange.size()); 95 | } 96 | 97 | @Test 98 | public void lrangeByte() { 99 | List lrange = yedis.lrange(list1.getBytes(), 0, -1); 100 | assertEquals(5, lrange.size()); 101 | } 102 | 103 | @Test 104 | public void lrem() { 105 | assertEquals(Long.valueOf(1), yedis.lrem(list1, 1, "value1")); 106 | } 107 | 108 | @Test 109 | public void lremByte() { 110 | assertEquals(Long.valueOf(1), yedis.lrem(list1.getBytes(), 1, "value1".getBytes())); 111 | } 112 | 113 | @Test 114 | public void lset() { 115 | yedis.lset(list1, 1, "value"); 116 | assertEquals("value", yedis.lindex(list1, 1)); 117 | } 118 | 119 | @Test 120 | public void lsetByte() { 121 | yedis.lset(list1.getBytes(), 1, "value".getBytes()); 122 | assertEquals("value", yedis.lindex(list1, 1)); 123 | } 124 | 125 | @Test 126 | public void ltrim() { 127 | yedis.ltrim(list1, 0, 1); 128 | assertEquals(Long.valueOf(2), yedis.llen(list1)); 129 | } 130 | 131 | @Test 132 | public void ltrimByte() { 133 | yedis.ltrim(list1.getBytes(), 0, 1); 134 | assertEquals(Long.valueOf(2), yedis.llen(list1)); 135 | } 136 | 137 | @Test 138 | public void rpop() { 139 | assertEquals("value5", yedis.rpop(list1)); 140 | } 141 | 142 | @Test 143 | public void rpopByte() { 144 | assertEquals("value5", new String(yedis.rpop(list1.getBytes()))); 145 | } 146 | 147 | @Test 148 | public void rpush() { 149 | assertEquals(Long.valueOf(6L), yedis.rpush(list1, "value")); 150 | } 151 | 152 | @Test 153 | public void rpushByte() { 154 | assertEquals(Long.valueOf(6L), yedis.rpush(list1.getBytes(), "value".getBytes())); 155 | } 156 | 157 | @Test 158 | public void rpushx() { 159 | assertEquals(Long.valueOf(0L), yedis.rpushx("list4", "value")); 160 | } 161 | 162 | @Test 163 | public void rpushxByte() { 164 | assertEquals(Long.valueOf(0L), yedis.rpushx("list4".getBytes(), "value".getBytes())); 165 | } 166 | 167 | } 168 | -------------------------------------------------------------------------------- /src/test/java/com/yeahmobi/yedis/shard/ShardedYedisSetTest.java: -------------------------------------------------------------------------------- 1 | package com.yeahmobi.yedis.shard; 2 | 3 | import org.junit.After; 4 | import org.junit.Before; 5 | import org.junit.Test; 6 | 7 | public class ShardedYedisSetTest extends AbstractShardedYedisTest { 8 | 9 | private String key1 = "key1"; 10 | private String key2 = "key2"; 11 | 12 | @Before 13 | public void setup() { 14 | yedis.sadd(key1, "value1", "value2"); 15 | yedis.sadd(key2, "value3", "value4"); 16 | } 17 | 18 | @After 19 | public void tearDown() { 20 | flushAll(); 21 | } 22 | 23 | @Test 24 | public void sadd() { 25 | yedis.sadd(key1, "value3", "value4"); 26 | assertEquals(Long.valueOf(4), yedis.scard(key1)); 27 | } 28 | 29 | @Test 30 | public void saddByte() { 31 | yedis.sadd(key1.getBytes(), "value3".getBytes(), "value4".getBytes()); 32 | assertEquals(Long.valueOf(4), yedis.scard(key1)); 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/test/java/com/yeahmobi/yedis/shard/ShardedYedisStringTest.java: -------------------------------------------------------------------------------- 1 | package com.yeahmobi.yedis.shard; 2 | 3 | import org.junit.After; 4 | import org.junit.Before; 5 | import org.junit.Test; 6 | 7 | public class ShardedYedisStringTest extends AbstractShardedYedisTest { 8 | 9 | private String key1 = "key1"; 10 | private String key2 = "key2"; 11 | 12 | @Before 13 | public void setup() { 14 | yedis.set(key1, "value1"); 15 | yedis.set(key2, "value2"); 16 | } 17 | 18 | @After 19 | public void tearDown() { 20 | flushAll(); 21 | } 22 | 23 | @Test 24 | public void append() { 25 | yedis.append(key1, "_add"); 26 | assertEquals("value1_add", yedis.get(key1)); 27 | } 28 | 29 | @Test 30 | public void appendByte() { 31 | yedis.append(key1.getBytes(), "_add".getBytes()); 32 | assertEquals("value1_add", yedis.get(key1)); 33 | } 34 | 35 | @Test 36 | public void bitcount() { 37 | yedis.set(key1, ""); 38 | yedis.setbit(key1, 0, true); 39 | assertEquals(Long.valueOf(1), yedis.bitcount(key1)); 40 | } 41 | 42 | @Test 43 | public void bitcountByte() { 44 | yedis.set(key1, ""); 45 | yedis.setbit(key1, 0, true); 46 | assertEquals(Long.valueOf(1), yedis.bitcount(key1.getBytes())); 47 | } 48 | 49 | @Test 50 | public void decr() { 51 | yedis.set(key1, "5"); 52 | yedis.decr(key1); 53 | assertEquals("4", yedis.get(key1)); 54 | } 55 | 56 | @Test 57 | public void decrByte() { 58 | yedis.set(key1, "5"); 59 | yedis.decr(key1.getBytes()); 60 | assertEquals("4", yedis.get(key1)); 61 | } 62 | 63 | @Test 64 | public void decrBy() { 65 | yedis.set(key1, "5"); 66 | yedis.decrBy(key1, 2); 67 | assertEquals("3", yedis.get(key1)); 68 | } 69 | 70 | @Test 71 | public void decrByByte() { 72 | yedis.set(key1, "5"); 73 | yedis.decrBy(key1.getBytes(), 2); 74 | assertEquals("3", yedis.get(key1)); 75 | } 76 | 77 | @Test 78 | public void getrange() { 79 | assertEquals("value1", yedis.getrange(key1, 0, -1)); 80 | } 81 | 82 | @Test 83 | public void getrangeByte() { 84 | assertEquals("value1", new String(yedis.getrange(key1.getBytes(), 0, -1))); 85 | } 86 | 87 | @Test 88 | public void getset() { 89 | assertEquals("value1", yedis.getSet(key1, "value")); 90 | assertEquals("value", yedis.get(key1)); 91 | } 92 | 93 | @Test 94 | public void getsetByte() { 95 | assertEquals("value1", new String(yedis.getSet(key1.getBytes(), "value".getBytes()))); 96 | assertEquals("value", yedis.get(key1)); 97 | } 98 | 99 | @Test 100 | public void incr() { 101 | yedis.set(key1, "5"); 102 | yedis.incr(key1); 103 | assertEquals("6", yedis.get(key1)); 104 | } 105 | 106 | @Test 107 | public void incrByte() { 108 | yedis.set(key1, "5"); 109 | yedis.incr(key1.getBytes()); 110 | assertEquals("6", yedis.get(key1)); 111 | } 112 | 113 | @Test 114 | public void incrBy() { 115 | yedis.set(key1, "5"); 116 | yedis.incrBy(key1, 2); 117 | assertEquals("7", yedis.get(key1)); 118 | } 119 | 120 | @Test 121 | public void incrByByte() { 122 | yedis.set(key1, "5"); 123 | yedis.incrBy(key1.getBytes(), 2); 124 | assertEquals("7", yedis.get(key1)); 125 | } 126 | 127 | @Test 128 | public void setex() { 129 | yedis.setex(key1, 10, "5"); 130 | assertTrue(yedis.ttl(key1).compareTo(10L) <= 0); 131 | } 132 | 133 | @Test 134 | public void setexByte() { 135 | yedis.setex(key1.getBytes(), 10, "5".getBytes()); 136 | assertTrue(yedis.ttl(key1).compareTo(10L) <= 0); 137 | } 138 | 139 | @Test 140 | public void setnx() { 141 | yedis.setnx(key1, "5"); 142 | assertEquals("value1", yedis.get(key1)); 143 | } 144 | 145 | @Test 146 | public void setnxByte() { 147 | yedis.setnx(key1.getBytes(), "5".getBytes()); 148 | assertEquals("value1", yedis.get(key1)); 149 | } 150 | 151 | @Test 152 | public void setrange() { 153 | yedis.setrange(key1, 0, "a"); 154 | assertEquals("aalue1", yedis.get(key1)); 155 | } 156 | 157 | @Test 158 | public void setrangeByte() { 159 | yedis.setrange(key1.getBytes(), 0, "a".getBytes()); 160 | assertEquals("aalue1", yedis.get(key1)); 161 | } 162 | 163 | @Test 164 | public void strlen() { 165 | assertEquals(Long.valueOf(6), yedis.strlen(key1)); 166 | } 167 | 168 | @Test 169 | public void strlenByte() { 170 | assertEquals(Long.valueOf(6), yedis.strlen(key1.getBytes())); 171 | } 172 | 173 | } 174 | -------------------------------------------------------------------------------- /src/test/java/com/yeahmobi/yedis/shard/ShardedYedisTest.java: -------------------------------------------------------------------------------- 1 | package com.yeahmobi.yedis.shard; 2 | 3 | import org.junit.Test; 4 | 5 | public class ShardedYedisTest extends AbstractShardedYedisTest { 6 | 7 | @Test 8 | public void hashStrategyTest() { 9 | yedis.set("key1", "value1"); 10 | yedis.set("key2", "value2"); 11 | int size = groups.size(); 12 | assertEquals("value1", groups.get(hash("key1", size)).get("key1")); 13 | assertEquals("value2", groups.get(hash("key2", size)).get("key2")); 14 | flushAll(); 15 | groups.get(hash("key1", size)).set("key1", "value1"); 16 | groups.get(hash("key2", size)).set("key2", "value2"); 17 | assertEquals("value1", yedis.get("key1")); 18 | assertEquals("value2", yedis.get("key2")); 19 | flushAll(); 20 | 21 | } 22 | 23 | private int hash(String str, int size) { 24 | return Math.abs(str.hashCode()) % size; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/test/java/com/yeahmobi/yedis/util/RetribleExecutorTest.java: -------------------------------------------------------------------------------- 1 | package com.yeahmobi.yedis.util; 2 | 3 | import org.junit.Assert; 4 | import org.junit.Test; 5 | 6 | import com.yeahmobi.yedis.common.YedisNetworkException; 7 | import com.yeahmobi.yedis.common.YedisTimeoutException; 8 | import com.yeahmobi.yedis.util.RetribleExecutor.RetriableOperator; 9 | 10 | public class RetribleExecutorTest extends Assert { 11 | 12 | @Test 13 | public void test1() { 14 | int retryCount = 3; 15 | RetribleExecutor.execute(new RetriableOperator() { 16 | 17 | int i = 0; 18 | 19 | public String execute() { 20 | if (i == 0) { 21 | i++; 22 | throw new YedisTimeoutException(); 23 | } else if (i == 1) { 24 | i++; 25 | throw new YedisNetworkException(); 26 | } 27 | return "done"; 28 | } 29 | }, retryCount); 30 | } 31 | 32 | @Test(expected = YedisNetworkException.class) 33 | public void testException1() { 34 | int retryCount = 1; 35 | RetribleExecutor.execute(new RetriableOperator() { 36 | 37 | int i = 0; 38 | 39 | public String execute() { 40 | if (i == 0) { 41 | i++; 42 | throw new YedisTimeoutException(); 43 | } else if (i == 1) { 44 | i++; 45 | throw new YedisNetworkException(); 46 | } 47 | return "done"; 48 | } 49 | }, retryCount); 50 | } 51 | 52 | @Test(expected = YedisTimeoutException.class) 53 | public void testException2() { 54 | int retryCount = 0; 55 | RetribleExecutor.execute(new RetriableOperator() { 56 | 57 | int i = 0; 58 | 59 | public String execute() { 60 | if (i == 0) { 61 | i++; 62 | throw new YedisTimeoutException(); 63 | } else if (i == 1) { 64 | i++; 65 | throw new YedisNetworkException(); 66 | } 67 | return "done"; 68 | } 69 | }, retryCount); 70 | } 71 | 72 | } 73 | -------------------------------------------------------------------------------- /src/test/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | [%level] %d{yyyy-MM-dd HH:mm:ss.SSS} [%X{aliUsername} %X{req.uriWithQueryString}] [%thread] %logger - %msg%n 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | --------------------------------------------------------------------------------