• spring-boot-starter-data-redis2.X连接redis7


    由于redis7引入了acl机制,可以配置用户权限,

    比如配置了一个普通用户 test,权限为  test_ 前缀的key可操作

    springboot想要连接,并没有设置用户名的地方,

    跟了源码,jedis客户端是支持的,但是springboot自动配置类并没有用用户名去连接,因此需要手动覆盖一些源码去实现该功能;可能高版本springboot没这个问题,但由于项目用的1.8,高版本需要升级jdk,不可能的;

    以下实现方式纯属跟代码去改造的,可能还有其他方式,但是我在网上也没有搜到解决办法

    我的项目使用的是jedis,lettuce我没看

    1. <dependency>
    2. <groupId>org.springframework.boot</groupId>
    3. <artifactId>spring-boot-starter-data-redis</artifactId>
    4. <version>2.3.7.RELEASE</version>
    5. <exclusions>
    6. <exclusion>
    7. <groupId>io.lettuce</groupId>
    8. <artifactId>lettuce-core</artifactId>
    9. </exclusion>
    10. </exclusions>
    11. </dependency>
    12. <dependency>
    13. <groupId>redis.clients</groupId>
    14. <artifactId>jedis</artifactId>
    15. <version>3.3.0</version>
    16. </dependency>

    springboot通过用户名连接单机版redis7,

    连接配置如下

    1. spring:
    2. redis:
    3. host: ip
    4. port: 6379
    5. # 密码
    6. user: test
    7. password: test@123

    只需要覆盖一个文件

    新建包目录   redis.clients.jedis

    新建类BinaryClient.java

    1. package redis.clients.jedis;
    2. import org.apache.commons.lang3.StringUtils;
    3. import redis.clients.jedis.Protocol.Keyword;
    4. import redis.clients.jedis.params.*;
    5. import redis.clients.jedis.util.SafeEncoder;
    6. import javax.net.ssl.HostnameVerifier;
    7. import javax.net.ssl.SSLParameters;
    8. import javax.net.ssl.SSLSocketFactory;
    9. import java.util.ArrayList;
    10. import java.util.List;
    11. import java.util.Map;
    12. import java.util.Map.Entry;
    13. import static redis.clients.jedis.Protocol.Command.EXISTS;
    14. import static redis.clients.jedis.Protocol.Command.GET;
    15. import static redis.clients.jedis.Protocol.Command.KEYS;
    16. import static redis.clients.jedis.Protocol.Command.PING;
    17. import static redis.clients.jedis.Protocol.Command.PSUBSCRIBE;
    18. import static redis.clients.jedis.Protocol.Command.PUNSUBSCRIBE;
    19. import static redis.clients.jedis.Protocol.Command.SET;
    20. import static redis.clients.jedis.Protocol.Command.SUBSCRIBE;
    21. import static redis.clients.jedis.Protocol.Command.TIME;
    22. import static redis.clients.jedis.Protocol.Command.UNSUBSCRIBE;
    23. import static redis.clients.jedis.Protocol.Command.*;
    24. import static redis.clients.jedis.Protocol.Keyword.*;
    25. import static redis.clients.jedis.Protocol.toByteArray;
    26. public class BinaryClient extends Connection {
    27. private boolean isInMulti;
    28. private String user;
    29. private String password;
    30. private int db;
    31. private boolean isInWatch;
    32. {
    33. String user = SpringUtils.getApplicationContext().getEnvironment().getProperty("spring.redis.user");
    34. if(StringUtils.isNotBlank(user)){
    35. this.user = user;
    36. }
    37. }
    38. public BinaryClient() {
    39. super();
    40. }
    41. public BinaryClient(final String host) {
    42. super(host);
    43. }
    44. public BinaryClient(final String host, final int port) {
    45. super(host, port);
    46. }
    47. public BinaryClient(final String host, final int port, final boolean ssl) {
    48. super(host, port, ssl);
    49. }
    50. public BinaryClient(final String host, final int port, final boolean ssl,
    51. final SSLSocketFactory sslSocketFactory, final SSLParameters sslParameters,
    52. final HostnameVerifier hostnameVerifier) {
    53. super(host, port, ssl, sslSocketFactory, sslParameters, hostnameVerifier);
    54. }
    55. public BinaryClient(final JedisSocketFactory jedisSocketFactory) {
    56. super(jedisSocketFactory);
    57. }
    58. public boolean isInMulti() {
    59. return isInMulti;
    60. }
    61. public boolean isInWatch() {
    62. return isInWatch;
    63. }
    64. private byte[][] joinParameters(byte[] first, byte[][] rest) {
    65. byte[][] result = new byte[rest.length + 1][];
    66. result[0] = first;
    67. System.arraycopy(rest, 0, result, 1, rest.length);
    68. return result;
    69. }
    70. private byte[][] joinParameters(byte[] first, byte[] second, byte[][] rest) {
    71. byte[][] result = new byte[rest.length + 2][];
    72. result[0] = first;
    73. result[1] = second;
    74. System.arraycopy(rest, 0, result, 2, rest.length);
    75. return result;
    76. }
    77. public void setUser(final String user) { this.user = user; }
    78. public void setPassword(final String password) {
    79. this.password = password;
    80. }
    81. public void setDb(int db) {
    82. this.db = db;
    83. }
    84. @Override
    85. public void connect() {
    86. if (!isConnected()) {
    87. super.connect();
    88. if (user != null&&password !=null) {
    89. auth(user, password);
    90. getStatusCodeReply();
    91. } else if (password != null) {
    92. auth(password);
    93. getStatusCodeReply();
    94. }
    95. if (db > 0) {
    96. select(db);
    97. getStatusCodeReply();
    98. }
    99. }
    100. }
    101. public void ping() {
    102. sendCommand(PING);
    103. }
    104. public void ping(final byte[] message) {
    105. sendCommand(PING, message);
    106. }
    107. public void set(final byte[] key, final byte[] value) {
    108. sendCommand(SET, key, value);
    109. }
    110. public void set(final byte[] key, final byte[] value, final SetParams params) {
    111. sendCommand(SET, params.getByteParams(key, value));
    112. }
    113. public void get(final byte[] key) {
    114. sendCommand(GET, key);
    115. }
    116. public void quit() {
    117. db = 0;
    118. sendCommand(QUIT);
    119. }
    120. public void exists(final byte[]... keys) {
    121. sendCommand(EXISTS, keys);
    122. }
    123. public void del(final byte[]... keys) {
    124. sendCommand(DEL, keys);
    125. }
    126. public void unlink(final byte[]... keys) {
    127. sendCommand(UNLINK, keys);
    128. }
    129. public void type(final byte[] key) {
    130. sendCommand(TYPE, key);
    131. }
    132. public void flushDB() {
    133. sendCommand(FLUSHDB);
    134. }
    135. public void keys(final byte[] pattern) {
    136. sendCommand(KEYS, pattern);
    137. }
    138. public void randomKey() {
    139. sendCommand(RANDOMKEY);
    140. }
    141. public void rename(final byte[] oldkey, final byte[] newkey) {
    142. sendCommand(RENAME, oldkey, newkey);
    143. }
    144. public void renamenx(final byte[] oldkey, final byte[] newkey) {
    145. sendCommand(RENAMENX, oldkey, newkey);
    146. }
    147. public void dbSize() {
    148. sendCommand(DBSIZE);
    149. }
    150. public void expire(final byte[] key, final int seconds) {
    151. sendCommand(EXPIRE, key, toByteArray(seconds));
    152. }
    153. public void expireAt(final byte[] key, final long unixTime) {
    154. sendCommand(EXPIREAT, key, toByteArray(unixTime));
    155. }
    156. public void ttl(final byte[] key) {
    157. sendCommand(TTL, key);
    158. }
    159. public void touch(final byte[]... keys) {
    160. sendCommand(TOUCH, keys);
    161. }
    162. public void select(final int index) {
    163. sendCommand(SELECT, toByteArray(index));
    164. }
    165. public void swapDB(final int index1, final int index2) {
    166. sendCommand(SWAPDB, toByteArray(index1), toByteArray(index2));
    167. }
    168. public void move(final byte[] key, final int dbIndex) {
    169. sendCommand(MOVE, key, toByteArray(dbIndex));
    170. }
    171. public void flushAll() {
    172. sendCommand(FLUSHALL);
    173. }
    174. public void getSet(final byte[] key, final byte[] value) {
    175. sendCommand(GETSET, key, value);
    176. }
    177. public void mget(final byte[]... keys) {
    178. sendCommand(MGET, keys);
    179. }
    180. public void setnx(final byte[] key, final byte[] value) {
    181. sendCommand(SETNX, key, value);
    182. }
    183. public void setex(final byte[] key, final int seconds, final byte[] value) {
    184. sendCommand(SETEX, key, toByteArray(seconds), value);
    185. }
    186. public void mset(final byte[]... keysvalues) {
    187. sendCommand(MSET, keysvalues);
    188. }
    189. public void msetnx(final byte[]... keysvalues) {
    190. sendCommand(MSETNX, keysvalues);
    191. }
    192. public void decrBy(final byte[] key, final long decrement) {
    193. sendCommand(DECRBY, key, toByteArray(decrement));
    194. }
    195. public void decr(final byte[] key) {
    196. sendCommand(DECR, key);
    197. }
    198. public void incrBy(final byte[] key, final long increment) {
    199. sendCommand(INCRBY, key, toByteArray(increment));
    200. }
    201. public void incrByFloat(final byte[] key, final double increment) {
    202. sendCommand(INCRBYFLOAT, key, toByteArray(increment));
    203. }
    204. public void incr(final byte[] key) {
    205. sendCommand(INCR, key);
    206. }
    207. public void append(final byte[] key, final byte[] value) {
    208. sendCommand(APPEND, key, value);
    209. }
    210. public void substr(final byte[] key, final int start, final int end) {
    211. sendCommand(SUBSTR, key, toByteArray(start), toByteArray(end));
    212. }
    213. public void hset(final byte[] key, final byte[] field, final byte[] value) {
    214. sendCommand(HSET, key, field, value);
    215. }
    216. public void hset(final byte[] key, final Map hash) {
    217. final byte[][] params = new byte[1 + hash.size() * 2][];
    218. int index = 0;
    219. params[index++] = key;
    220. for (final Entry entry : hash.entrySet()) {
    221. params[index++] = entry.getKey();
    222. params[index++] = entry.getValue();
    223. }
    224. sendCommand(HSET, params);
    225. }
    226. public void hget(final byte[] key, final byte[] field) {
    227. sendCommand(HGET, key, field);
    228. }
    229. public void hsetnx(final byte[] key, final byte[] field, final byte[] value) {
    230. sendCommand(HSETNX, key, field, value);
    231. }
    232. public void hmset(final byte[] key, final Map hash) {
    233. final List params = new ArrayList<>();
    234. params.add(key);
    235. for (final Entry entry : hash.entrySet()) {
    236. params.add(entry.getKey());
    237. params.add(entry.getValue());
    238. }
    239. sendCommand(HMSET, params.toArray(new byte[params.size()][]));
    240. }
    241. public void hmget(final byte[] key, final byte[]... fields) {
    242. sendCommand(HMGET, joinParameters(key, fields));
    243. }
    244. public void hincrBy(final byte[] key, final byte[] field, final long value) {
    245. sendCommand(HINCRBY, key, field, toByteArray(value));
    246. }
    247. public void hexists(final byte[] key, final byte[] field) {
    248. sendCommand(HEXISTS, key, field);
    249. }
    250. public void hdel(final byte[] key, final byte[]... fields) {
    251. sendCommand(HDEL, joinParameters(key, fields));
    252. }
    253. public void hlen(final byte[] key) {
    254. sendCommand(HLEN, key);
    255. }
    256. public void hkeys(final byte[] key) {
    257. sendCommand(HKEYS, key);
    258. }
    259. public void hvals(final byte[] key) {
    260. sendCommand(HVALS, key);
    261. }
    262. public void hgetAll(final byte[] key) {
    263. sendCommand(HGETALL, key);
    264. }
    265. public void rpush(final byte[] key, final byte[]... strings) {
    266. sendCommand(RPUSH, joinParameters(key, strings));
    267. }
    268. public void lpush(final byte[] key, final byte[]... strings) {
    269. sendCommand(LPUSH, joinParameters(key, strings));
    270. }
    271. public void llen(final byte[] key) {
    272. sendCommand(LLEN, key);
    273. }
    274. public void lrange(final byte[] key, final long start, final long stop) {
    275. sendCommand(LRANGE, key, toByteArray(start), toByteArray(stop));
    276. }
    277. public void ltrim(final byte[] key, final long start, final long stop) {
    278. sendCommand(LTRIM, key, toByteArray(start), toByteArray(stop));
    279. }
    280. public void lindex(final byte[] key, final long index) {
    281. sendCommand(LINDEX, key, toByteArray(index));
    282. }
    283. public void lset(final byte[] key, final long index, final byte[] value) {
    284. sendCommand(LSET, key, toByteArray(index), value);
    285. }
    286. public void lrem(final byte[] key, final long count, final byte[] value) {
    287. sendCommand(LREM, key, toByteArray(count), value);
    288. }
    289. public void lpop(final byte[] key) {
    290. sendCommand(LPOP, key);
    291. }
    292. public void rpop(final byte[] key) {
    293. sendCommand(RPOP, key);
    294. }
    295. public void rpoplpush(final byte[] srckey, final byte[] dstkey) {
    296. sendCommand(RPOPLPUSH, srckey, dstkey);
    297. }
    298. public void sadd(final byte[] key, final byte[]... members) {
    299. sendCommand(SADD, joinParameters(key, members));
    300. }
    301. public void smembers(final byte[] key) {
    302. sendCommand(SMEMBERS, key);
    303. }
    304. public void srem(final byte[] key, final byte[]... members) {
    305. sendCommand(SREM, joinParameters(key, members));
    306. }
    307. public void spop(final byte[] key) {
    308. sendCommand(SPOP, key);
    309. }
    310. public void spop(final byte[] key, final long count) {
    311. sendCommand(SPOP, key, toByteArray(count));
    312. }
    313. public void smove(final byte[] srckey, final byte[] dstkey, final byte[] member) {
    314. sendCommand(SMOVE, srckey, dstkey, member);
    315. }
    316. public void scard(final byte[] key) {
    317. sendCommand(SCARD, key);
    318. }
    319. public void sismember(final byte[] key, final byte[] member) {
    320. sendCommand(SISMEMBER, key, member);
    321. }
    322. public void sinter(final byte[]... keys) {
    323. sendCommand(SINTER, keys);
    324. }
    325. public void sinterstore(final byte[] dstkey, final byte[]... keys) {
    326. sendCommand(SINTERSTORE, joinParameters(dstkey, keys));
    327. }
    328. public void sunion(final byte[]... keys) {
    329. sendCommand(SUNION, keys);
    330. }
    331. public void sunionstore(final byte[] dstkey, final byte[]... keys) {
    332. sendCommand(SUNIONSTORE, joinParameters(dstkey, keys));
    333. }
    334. public void sdiff(final byte[]... keys) {
    335. sendCommand(SDIFF, keys);
    336. }
    337. public void sdiffstore(final byte[] dstkey, final byte[]... keys) {
    338. sendCommand(SDIFFSTORE, joinParameters(dstkey, keys));
    339. }
    340. public void srandmember(final byte[] key) {
    341. sendCommand(SRANDMEMBER, key);
    342. }
    343. public void zadd(final byte[] key, final double score, final byte[] member) {
    344. sendCommand(ZADD, key, toByteArray(score), member);
    345. }
    346. public void zadd(final byte[] key, final double score, final byte[] member,
    347. final ZAddParams params) {
    348. sendCommand(ZADD, params.getByteParams(key, toByteArray(score), member));
    349. }
    350. public void zadd(final byte[] key, final Map scoreMembers) {
    351. ArrayList args = new ArrayList<>(scoreMembers.size() * 2 + 1);
    352. args.add(key);
    353. args.addAll(convertScoreMembersToByteArrays(scoreMembers));
    354. byte[][] argsArray = new byte[args.size()][];
    355. args.toArray(argsArray);
    356. sendCommand(ZADD, argsArray);
    357. }
    358. public void zadd(final byte[] key, final Map scoreMembers, final ZAddParams params) {
    359. ArrayList args = convertScoreMembersToByteArrays(scoreMembers);
    360. byte[][] argsArray = new byte[args.size()][];
    361. args.toArray(argsArray);
    362. sendCommand(ZADD, params.getByteParams(key, argsArray));
    363. }
    364. public void zrange(final byte[] key, final long start, final long stop) {
    365. sendCommand(ZRANGE, key, toByteArray(start), toByteArray(stop));
    366. }
    367. public void zrem(final byte[] key, final byte[]... members) {
    368. sendCommand(ZREM, joinParameters(key, members));
    369. }
    370. public void zincrby(final byte[] key, final double increment, final byte[] member) {
    371. sendCommand(ZINCRBY, key, toByteArray(increment), member);
    372. }
    373. public void zincrby(final byte[] key, final double increment, final byte[] member,
    374. final ZIncrByParams params) {
    375. // Note that it actually calls ZADD with INCR option, so it requires Redis 3.0.2 or upper.
    376. sendCommand(ZADD, params.getByteParams(key, toByteArray(increment), member));
    377. }
    378. public void zrank(final byte[] key, final byte[] member) {
    379. sendCommand(ZRANK, key, member);
    380. }
    381. public void zrevrank(final byte[] key, final byte[] member) {
    382. sendCommand(ZREVRANK, key, member);
    383. }
    384. public void zrevrange(final byte[] key, final long start, final long stop) {
    385. sendCommand(ZREVRANGE, key, toByteArray(start), toByteArray(stop));
    386. }
    387. public void zrangeWithScores(final byte[] key, final long start, final long stop) {
    388. sendCommand(ZRANGE, key, toByteArray(start), toByteArray(stop), WITHSCORES.raw);
    389. }
    390. public void zrevrangeWithScores(final byte[] key, final long start, final long stop) {
    391. sendCommand(ZREVRANGE, key, toByteArray(start), toByteArray(stop), WITHSCORES.raw);
    392. }
    393. public void zcard(final byte[] key) {
    394. sendCommand(ZCARD, key);
    395. }
    396. public void zscore(final byte[] key, final byte[] member) {
    397. sendCommand(ZSCORE, key, member);
    398. }
    399. public void zpopmax(final byte[] key) {
    400. sendCommand(ZPOPMAX, key);
    401. }
    402. public void zpopmax(final byte[] key, final int count) {
    403. sendCommand(ZPOPMAX, key, toByteArray(count));
    404. }
    405. public void zpopmin(final byte[] key) {
    406. sendCommand(ZPOPMIN, key);
    407. }
    408. public void zpopmin(final byte[] key, final long count) {
    409. sendCommand(ZPOPMIN, key, toByteArray(count));
    410. }
    411. public void multi() {
    412. sendCommand(MULTI);
    413. isInMulti = true;
    414. }
    415. public void discard() {
    416. sendCommand(DISCARD);
    417. isInMulti = false;
    418. isInWatch = false;
    419. }
    420. public void exec() {
    421. sendCommand(EXEC);
    422. isInMulti = false;
    423. isInWatch = false;
    424. }
    425. public void watch(final byte[]... keys) {
    426. sendCommand(WATCH, keys);
    427. isInWatch = true;
    428. }
    429. public void unwatch() {
    430. sendCommand(UNWATCH);
    431. isInWatch = false;
    432. }
    433. public void sort(final byte[] key) {
    434. sendCommand(SORT, key);
    435. }
    436. public void sort(final byte[] key, final SortingParams sortingParameters) {
    437. final List args = new ArrayList<>();
    438. args.add(key);
    439. args.addAll(sortingParameters.getParams());
    440. sendCommand(SORT, args.toArray(new byte[args.size()][]));
    441. }
    442. public void blpop(final byte[][] args) {
    443. sendCommand(BLPOP, args);
    444. }
    445. public void blpop(final int timeout, final byte[]... keys) {
    446. final List args = new ArrayList<>();
    447. for (final byte[] arg : keys) {
    448. args.add(arg);
    449. }
    450. args.add(Protocol.toByteArray(timeout));
    451. blpop(args.toArray(new byte[args.size()][]));
    452. }
    453. public void sort(final byte[] key, final SortingParams sortingParameters, final byte[] dstkey) {
    454. final List args = new ArrayList<>();
    455. args.add(key);
    456. args.addAll(sortingParameters.getParams());
    457. args.add(STORE.raw);
    458. args.add(dstkey);
    459. sendCommand(SORT, args.toArray(new byte[args.size()][]));
    460. }
    461. public void sort(final byte[] key, final byte[] dstkey) {
    462. sendCommand(SORT, key, STORE.raw, dstkey);
    463. }
    464. public void brpop(final byte[][] args) {
    465. sendCommand(BRPOP, args);
    466. }
    467. public void brpop(final int timeout, final byte[]... keys) {
    468. final List args = new ArrayList<>();
    469. for (final byte[] arg : keys) {
    470. args.add(arg);
    471. }
    472. args.add(Protocol.toByteArray(timeout));
    473. brpop(args.toArray(new byte[args.size()][]));
    474. }
    475. public void auth(final String password) {
    476. setPassword(password);
    477. sendCommand(AUTH, password);
    478. }
    479. public void auth(final String user, final String password) {
    480. setUser(user);
    481. setPassword(password);
    482. sendCommand(AUTH, user, password);
    483. }
    484. public void subscribe(final byte[]... channels) {
    485. sendCommand(SUBSCRIBE, channels);
    486. }
    487. public void publish(final byte[] channel, final byte[] message) {
    488. sendCommand(PUBLISH, channel, message);
    489. }
    490. public void unsubscribe() {
    491. sendCommand(UNSUBSCRIBE);
    492. }
    493. public void unsubscribe(final byte[]... channels) {
    494. sendCommand(UNSUBSCRIBE, channels);
    495. }
    496. public void psubscribe(final byte[]... patterns) {
    497. sendCommand(PSUBSCRIBE, patterns);
    498. }
    499. public void punsubscribe() {
    500. sendCommand(PUNSUBSCRIBE);
    501. }
    502. public void punsubscribe(final byte[]... patterns) {
    503. sendCommand(PUNSUBSCRIBE, patterns);
    504. }
    505. public void pubsub(final byte[]... args) {
    506. sendCommand(PUBSUB, args);
    507. }
    508. public void zcount(final byte[] key, final double min, final double max) {
    509. sendCommand(ZCOUNT, key, toByteArray(min), toByteArray(max));
    510. }
    511. public void zcount(final byte[] key, final byte[] min, final byte[] max) {
    512. sendCommand(ZCOUNT, key, min, max);
    513. }
    514. public void zrangeByScore(final byte[] key, final double min, final double max) {
    515. sendCommand(ZRANGEBYSCORE, key, toByteArray(min), toByteArray(max));
    516. }
    517. public void zrangeByScore(final byte[] key, final byte[] min, final byte[] max) {
    518. sendCommand(ZRANGEBYSCORE, key, min, max);
    519. }
    520. public void zrevrangeByScore(final byte[] key, final double max, final double min) {
    521. sendCommand(ZREVRANGEBYSCORE, key, toByteArray(max), toByteArray(min));
    522. }
    523. public void zrevrangeByScore(final byte[] key, final byte[] max, final byte[] min) {
    524. sendCommand(ZREVRANGEBYSCORE, key, max, min);
    525. }
    526. public void zrangeByScore(final byte[] key, final double min, final double max, final int offset,
    527. final int count) {
    528. sendCommand(ZRANGEBYSCORE, key, toByteArray(min), toByteArray(max), LIMIT.raw, toByteArray(offset),
    529. toByteArray(count));
    530. }
    531. public void zrevrangeByScore(final byte[] key, final double max, final double min,
    532. final int offset, final int count) {
    533. sendCommand(ZREVRANGEBYSCORE, key, toByteArray(max), toByteArray(min), LIMIT.raw, toByteArray(offset),
    534. toByteArray(count));
    535. }
    536. public void zrangeByScoreWithScores(final byte[] key, final double min, final double max) {
    537. sendCommand(ZRANGEBYSCORE, key, toByteArray(min), toByteArray(max), WITHSCORES.raw);
    538. }
    539. public void zrevrangeByScoreWithScores(final byte[] key, final double max, final double min) {
    540. sendCommand(ZREVRANGEBYSCORE, key, toByteArray(max), toByteArray(min), WITHSCORES.raw);
    541. }
    542. public void zrangeByScoreWithScores(final byte[] key, final double min, final double max,
    543. final int offset, final int count) {
    544. sendCommand(ZRANGEBYSCORE, key, toByteArray(min), toByteArray(max), LIMIT.raw, toByteArray(offset),
    545. toByteArray(count), WITHSCORES.raw);
    546. }
    547. public void zrevrangeByScoreWithScores(final byte[] key, final double max, final double min,
    548. final int offset, final int count) {
    549. sendCommand(ZREVRANGEBYSCORE, key, toByteArray(max), toByteArray(min), LIMIT.raw, toByteArray(offset),
    550. toByteArray(count), WITHSCORES.raw);
    551. }
    552. public void zrangeByScore(final byte[] key, final byte[] min, final byte[] max, final int offset,
    553. final int count) {
    554. sendCommand(ZRANGEBYSCORE, key, min, max, LIMIT.raw, toByteArray(offset), toByteArray(count));
    555. }
    556. public void zrevrangeByScore(final byte[] key, final byte[] max, final byte[] min,
    557. final int offset, final int count) {
    558. sendCommand(ZREVRANGEBYSCORE, key, max, min, LIMIT.raw, toByteArray(offset), toByteArray(count));
    559. }
    560. public void zrangeByScoreWithScores(final byte[] key, final byte[] min, final byte[] max) {
    561. sendCommand(ZRANGEBYSCORE, key, min, max, WITHSCORES.raw);
    562. }
    563. public void zrevrangeByScoreWithScores(final byte[] key, final byte[] max, final byte[] min) {
    564. sendCommand(ZREVRANGEBYSCORE, key, max, min, WITHSCORES.raw);
    565. }
    566. public void zrangeByScoreWithScores(final byte[] key, final byte[] min, final byte[] max,
    567. final int offset, final int count) {
    568. sendCommand(ZRANGEBYSCORE, key, min, max, LIMIT.raw, toByteArray(offset), toByteArray(count),
    569. WITHSCORES.raw);
    570. }
    571. public void zrevrangeByScoreWithScores(final byte[] key, final byte[] max, final byte[] min,
    572. final int offset, final int count) {
    573. sendCommand(ZREVRANGEBYSCORE, key, max, min, LIMIT.raw, toByteArray(offset),
    574. toByteArray(count), WITHSCORES.raw);
    575. }
    576. public void zremrangeByRank(final byte[] key, final long start, final long stop) {
    577. sendCommand(ZREMRANGEBYRANK, key, toByteArray(start), toByteArray(stop));
    578. }
    579. public void zremrangeByScore(final byte[] key, final double min, final double max) {
    580. sendCommand(ZREMRANGEBYSCORE, key, toByteArray(min), toByteArray(max));
    581. }
    582. public void zremrangeByScore(final byte[] key, final byte[] min, final byte[] max) {
    583. sendCommand(ZREMRANGEBYSCORE, key, min, max);
    584. }
    585. public void zunionstore(final byte[] dstkey, final byte[]... sets) {
    586. sendCommand(ZUNIONSTORE, joinParameters(dstkey, toByteArray(sets.length), sets));
    587. }
    588. public void zunionstore(final byte[] dstkey, final ZParams params, final byte[]... sets) {
    589. final List args = new ArrayList<>();
    590. args.add(dstkey);
    591. args.add(Protocol.toByteArray(sets.length));
    592. for (final byte[] set : sets) {
    593. args.add(set);
    594. }
    595. args.addAll(params.getParams());
    596. sendCommand(ZUNIONSTORE, args.toArray(new byte[args.size()][]));
    597. }
    598. public void zinterstore(final byte[] dstkey, final byte[]... sets) {
    599. sendCommand(ZINTERSTORE, joinParameters(dstkey, Protocol.toByteArray(sets.length), sets));
    600. }
    601. public void zinterstore(final byte[] dstkey, final ZParams params, final byte[]... sets) {
    602. final List args = new ArrayList<>();
    603. args.add(dstkey);
    604. args.add(Protocol.toByteArray(sets.length));
    605. for (final byte[] set : sets) {
    606. args.add(set);
    607. }
    608. args.addAll(params.getParams());
    609. sendCommand(ZINTERSTORE, args.toArray(new byte[args.size()][]));
    610. }
    611. public void zlexcount(final byte[] key, final byte[] min, final byte[] max) {
    612. sendCommand(ZLEXCOUNT, key, min, max);
    613. }
    614. public void zrangeByLex(final byte[] key, final byte[] min, final byte[] max) {
    615. sendCommand(ZRANGEBYLEX, key, min, max);
    616. }
    617. public void zrangeByLex(final byte[] key, final byte[] min, final byte[] max, final int offset,
    618. final int count) {
    619. sendCommand(ZRANGEBYLEX, key, min, max, LIMIT.raw, toByteArray(offset), toByteArray(count));
    620. }
    621. public void zrevrangeByLex(final byte[] key, final byte[] max, final byte[] min) {
    622. sendCommand(ZREVRANGEBYLEX, key, max, min);
    623. }
    624. public void zrevrangeByLex(final byte[] key, final byte[] max, final byte[] min,
    625. final int offset, final int count) {
    626. sendCommand(ZREVRANGEBYLEX, key, max, min, LIMIT.raw, toByteArray(offset), toByteArray(count));
    627. }
    628. public void zremrangeByLex(final byte[] key, final byte[] min, final byte[] max) {
    629. sendCommand(ZREMRANGEBYLEX, key, min, max);
    630. }
    631. public void save() {
    632. sendCommand(SAVE);
    633. }
    634. public void bgsave() {
    635. sendCommand(BGSAVE);
    636. }
    637. public void bgrewriteaof() {
    638. sendCommand(BGREWRITEAOF);
    639. }
    640. public void lastsave() {
    641. sendCommand(LASTSAVE);
    642. }
    643. public void shutdown() {
    644. sendCommand(SHUTDOWN);
    645. }
    646. public void info() {
    647. sendCommand(INFO);
    648. }
    649. public void info(final String section) {
    650. sendCommand(INFO, section);
    651. }
    652. public void monitor() {
    653. sendCommand(MONITOR);
    654. }
    655. public void slaveof(final String host, final int port) {
    656. sendCommand(SLAVEOF, host, String.valueOf(port));
    657. }
    658. public void slaveofNoOne() {
    659. sendCommand(SLAVEOF, NO.raw, ONE.raw);
    660. }
    661. public void configGet(final byte[] pattern) {
    662. sendCommand(CONFIG, Keyword.GET.raw, pattern);
    663. }
    664. public void configSet(final byte[] parameter, final byte[] value) {
    665. sendCommand(CONFIG, Keyword.SET.raw, parameter, value);
    666. }
    667. public void strlen(final byte[] key) {
    668. sendCommand(STRLEN, key);
    669. }
    670. public void sync() {
    671. sendCommand(SYNC);
    672. }
    673. public void lpushx(final byte[] key, final byte[]... string) {
    674. sendCommand(LPUSHX, joinParameters(key, string));
    675. }
    676. public void persist(final byte[] key) {
    677. sendCommand(PERSIST, key);
    678. }
    679. public void rpushx(final byte[] key, final byte[]... string) {
    680. sendCommand(RPUSHX, joinParameters(key, string));
    681. }
    682. public void echo(final byte[] string) {
    683. sendCommand(ECHO, string);
    684. }
    685. public void linsert(final byte[] key, final ListPosition where, final byte[] pivot,
    686. final byte[] value) {
    687. sendCommand(LINSERT, key, where.raw, pivot, value);
    688. }
    689. public void debug(final DebugParams params) {
    690. sendCommand(DEBUG, params.getCommand());
    691. }
    692. public void brpoplpush(final byte[] source, final byte[] destination, final int timeout) {
    693. sendCommand(BRPOPLPUSH, source, destination, toByteArray(timeout));
    694. }
    695. public void configResetStat() {
    696. sendCommand(CONFIG, Keyword.RESETSTAT.raw);
    697. }
    698. public void configRewrite() {
    699. sendCommand(CONFIG, Keyword.REWRITE.raw);
    700. }
    701. public void setbit(final byte[] key, final long offset, final byte[] value) {
    702. sendCommand(SETBIT, key, toByteArray(offset), value);
    703. }
    704. public void setbit(final byte[] key, final long offset, final boolean value) {
    705. sendCommand(SETBIT, key, toByteArray(offset), toByteArray(value));
    706. }
    707. public void getbit(final byte[] key, final long offset) {
    708. sendCommand(GETBIT, key, toByteArray(offset));
    709. }
    710. public void bitpos(final byte[] key, final boolean value, final BitPosParams params) {
    711. final List args = new ArrayList<>();
    712. args.add(key);
    713. args.add(toByteArray(value));
    714. args.addAll(params.getParams());
    715. sendCommand(BITPOS, args.toArray(new byte[args.size()][]));
    716. }
    717. public void setrange(final byte[] key, final long offset, final byte[] value) {
    718. sendCommand(SETRANGE, key, toByteArray(offset), value);
    719. }
    720. public void getrange(final byte[] key, final long startOffset, final long endOffset) {
    721. sendCommand(GETRANGE, key, toByteArray(startOffset), toByteArray(endOffset));
    722. }
    723. public int getDB() {
    724. return db;
    725. }
    726. @Override
    727. public void disconnect() {
    728. db = 0;
    729. super.disconnect();
    730. }
    731. @Override
    732. public void close() {
    733. db = 0;
    734. super.close();
    735. }
    736. public void resetState() {
    737. if (isInWatch()) {
    738. unwatch();
    739. getStatusCodeReply();
    740. }
    741. }
    742. public void eval(final byte[] script, final byte[] keyCount, final byte[][] params) {
    743. sendCommand(EVAL, joinParameters(script, keyCount, params));
    744. }
    745. public void eval(final byte[] script, final int keyCount, final byte[]... params) {
    746. sendCommand(EVAL, joinParameters(script, toByteArray(keyCount), params));
    747. }
    748. public void evalsha(final byte[] sha1, final byte[] keyCount, final byte[]... params) {
    749. sendCommand(EVALSHA, joinParameters(sha1, keyCount, params));
    750. }
    751. public void evalsha(final byte[] sha1, final int keyCount, final byte[]... params) {
    752. sendCommand(EVALSHA, joinParameters(sha1, toByteArray(keyCount), params));
    753. }
    754. public void scriptFlush() {
    755. sendCommand(SCRIPT, Keyword.FLUSH.raw);
    756. }
    757. public void scriptExists(final byte[]... sha1) {
    758. sendCommand(SCRIPT, joinParameters(Keyword.EXISTS.raw, sha1));
    759. }
    760. public void scriptLoad(final byte[] script) {
    761. sendCommand(SCRIPT, Keyword.LOAD.raw, script);
    762. }
    763. public void scriptKill() {
    764. sendCommand(SCRIPT, Keyword.KILL.raw);
    765. }
    766. public void slowlogGet() {
    767. sendCommand(SLOWLOG, Keyword.GET.raw);
    768. }
    769. public void slowlogGet(final long entries) {
    770. sendCommand(SLOWLOG, Keyword.GET.raw, toByteArray(entries));
    771. }
    772. public void slowlogReset() {
    773. sendCommand(SLOWLOG, RESET.raw);
    774. }
    775. public void slowlogLen() {
    776. sendCommand(SLOWLOG, LEN.raw);
    777. }
    778. public void objectRefcount(final byte[] key) {
    779. sendCommand(OBJECT, REFCOUNT.raw, key);
    780. }
    781. public void objectIdletime(final byte[] key) {
    782. sendCommand(OBJECT, IDLETIME.raw, key);
    783. }
    784. public void objectEncoding(final byte[] key) {
    785. sendCommand(OBJECT, ENCODING.raw, key);
    786. }
    787. public void objectHelp() {
    788. sendCommand(OBJECT, HELP.raw);
    789. }
    790. public void objectFreq(final byte[] key) {
    791. sendCommand(OBJECT, FREQ.raw, key);
    792. }
    793. public void bitcount(final byte[] key) {
    794. sendCommand(BITCOUNT, key);
    795. }
    796. public void bitcount(final byte[] key, final long start, final long end) {
    797. sendCommand(BITCOUNT, key, toByteArray(start), toByteArray(end));
    798. }
    799. public void bitop(final BitOP op, final byte[] destKey, final byte[]... srcKeys) {
    800. sendCommand(BITOP, joinParameters(op.raw, destKey, srcKeys));
    801. }
    802. public void sentinel(final byte[]... args) {
    803. sendCommand(SENTINEL, args);
    804. }
    805. public void dump(final byte[] key) {
    806. sendCommand(DUMP, key);
    807. }
    808. public void restore(final byte[] key, final int ttl, final byte[] serializedValue) {
    809. sendCommand(RESTORE, key, toByteArray(ttl), serializedValue);
    810. }
    811. public void restoreReplace(final byte[] key, final int ttl, final byte[] serializedValue) {
    812. sendCommand(RESTORE, key, toByteArray(ttl), serializedValue, Keyword.REPLACE.raw);
    813. }
    814. public void pexpire(final byte[] key, final long milliseconds) {
    815. sendCommand(PEXPIRE, key, toByteArray(milliseconds));
    816. }
    817. public void pexpireAt(final byte[] key, final long millisecondsTimestamp) {
    818. sendCommand(PEXPIREAT, key, toByteArray(millisecondsTimestamp));
    819. }
    820. public void pttl(final byte[] key) {
    821. sendCommand(PTTL, key);
    822. }
    823. public void psetex(final byte[] key, final long milliseconds, final byte[] value) {
    824. sendCommand(PSETEX, key, toByteArray(milliseconds), value);
    825. }
    826. public void srandmember(final byte[] key, final int count) {
    827. sendCommand(SRANDMEMBER, key, toByteArray(count));
    828. }
    829. public void memoryDoctor() {
    830. sendCommand(MEMORY, Keyword.DOCTOR.raw);
    831. }
    832. public void clientKill(final byte[] ipPort) {
    833. sendCommand(CLIENT, Keyword.KILL.raw, ipPort);
    834. }
    835. public void clientKill(final String ip, final int port) {
    836. sendCommand(CLIENT, Keyword.KILL.name(), ip + ':' + port);
    837. }
    838. public void clientKill(ClientKillParams params) {
    839. sendCommand(CLIENT, joinParameters(Keyword.KILL.raw, params.getByteParams()));
    840. }
    841. public void clientGetname() {
    842. sendCommand(CLIENT, Keyword.GETNAME.raw);
    843. }
    844. public void clientList() {
    845. sendCommand(CLIENT, Keyword.LIST.raw);
    846. }
    847. public void clientSetname(final byte[] name) {
    848. sendCommand(CLIENT, Keyword.SETNAME.raw, name);
    849. }
    850. public void clientPause(final long timeout) {
    851. sendCommand(CLIENT, Keyword.PAUSE.raw, toByteArray(timeout));
    852. }
    853. public void time() {
    854. sendCommand(TIME);
    855. }
    856. public void migrate(final String host, final int port, final byte[] key, final int destinationDb,
    857. final int timeout) {
    858. sendCommand(MIGRATE, SafeEncoder.encode(host), toByteArray(port), key,
    859. toByteArray(destinationDb), toByteArray(timeout));
    860. }
    861. public void migrate(final String host, final int port, final int destinationDB,
    862. final int timeout, final MigrateParams params, final byte[]... keys) {
    863. byte[][] bparams = params.getByteParams();
    864. int len = 5 + bparams.length + 1 + keys.length;
    865. byte[][] args = new byte[len][];
    866. int i = 0;
    867. args[i++] = SafeEncoder.encode(host);
    868. args[i++] = toByteArray(port);
    869. args[i++] = new byte[0];
    870. args[i++] = toByteArray(destinationDB);
    871. args[i++] = toByteArray(timeout);
    872. System.arraycopy(bparams, 0, args, i, bparams.length);
    873. i += bparams.length;
    874. args[i++] = Keyword.KEYS.raw;
    875. System.arraycopy(keys, 0, args, i, keys.length);
    876. sendCommand(MIGRATE, args);
    877. }
    878. public void hincrByFloat(final byte[] key, final byte[] field, final double increment) {
    879. sendCommand(HINCRBYFLOAT, key, field, toByteArray(increment));
    880. }
    881. public void scan(final byte[] cursor, final ScanParams params) {
    882. final List args = new ArrayList<>();
    883. args.add(cursor);
    884. args.addAll(params.getParams());
    885. sendCommand(SCAN, args.toArray(new byte[args.size()][]));
    886. }
    887. public void hscan(final byte[] key, final byte[] cursor, final ScanParams params) {
    888. final List args = new ArrayList<>();
    889. args.add(key);
    890. args.add(cursor);
    891. args.addAll(params.getParams());
    892. sendCommand(HSCAN, args.toArray(new byte[args.size()][]));
    893. }
    894. public void sscan(final byte[] key, final byte[] cursor, final ScanParams params) {
    895. final List args = new ArrayList<>();
    896. args.add(key);
    897. args.add(cursor);
    898. args.addAll(params.getParams());
    899. sendCommand(SSCAN, args.toArray(new byte[args.size()][]));
    900. }
    901. public void zscan(final byte[] key, final byte[] cursor, final ScanParams params) {
    902. final List args = new ArrayList<>();
    903. args.add(key);
    904. args.add(cursor);
    905. args.addAll(params.getParams());
    906. sendCommand(ZSCAN, args.toArray(new byte[args.size()][]));
    907. }
    908. public void waitReplicas(final int replicas, final long timeout) {
    909. sendCommand(WAIT, toByteArray(replicas), toByteArray(timeout));
    910. }
    911. public void cluster(final byte[]... args) {
    912. sendCommand(CLUSTER, args);
    913. }
    914. public void asking() {
    915. sendCommand(ASKING);
    916. }
    917. public void pfadd(final byte[] key, final byte[]... elements) {
    918. sendCommand(PFADD, joinParameters(key, elements));
    919. }
    920. public void pfcount(final byte[] key) {
    921. sendCommand(PFCOUNT, key);
    922. }
    923. public void pfcount(final byte[]... keys) {
    924. sendCommand(PFCOUNT, keys);
    925. }
    926. public void pfmerge(final byte[] destkey, final byte[]... sourcekeys) {
    927. sendCommand(PFMERGE, joinParameters(destkey, sourcekeys));
    928. }
    929. public void readonly() {
    930. sendCommand(READONLY);
    931. }
    932. public void geoadd(final byte[] key, final double longitude, final double latitude, final byte[] member) {
    933. sendCommand(GEOADD, key, toByteArray(longitude), toByteArray(latitude), member);
    934. }
    935. public void geoadd(final byte[] key, final Map memberCoordinateMap) {
    936. List args = new ArrayList<>(memberCoordinateMap.size() * 3 + 1);
    937. args.add(key);
    938. args.addAll(convertGeoCoordinateMapToByteArrays(memberCoordinateMap));
    939. byte[][] argsArray = new byte[args.size()][];
    940. args.toArray(argsArray);
    941. sendCommand(GEOADD, argsArray);
    942. }
    943. public void geodist(final byte[] key, final byte[] member1, final byte[] member2) {
    944. sendCommand(GEODIST, key, member1, member2);
    945. }
    946. public void geodist(final byte[] key, final byte[] member1, final byte[] member2, final GeoUnit unit) {
    947. sendCommand(GEODIST, key, member1, member2, unit.raw);
    948. }
    949. public void geohash(final byte[] key, final byte[]... members) {
    950. sendCommand(GEOHASH, joinParameters(key, members));
    951. }
    952. public void geopos(final byte[] key, final byte[][] members) {
    953. sendCommand(GEOPOS, joinParameters(key, members));
    954. }
    955. public void georadius(final byte[] key, final double longitude, final double latitude, final double radius, final GeoUnit unit) {
    956. sendCommand(GEORADIUS, key, toByteArray(longitude), toByteArray(latitude), toByteArray(radius),
    957. unit.raw);
    958. }
    959. public void georadiusReadonly(final byte[] key, final double longitude, final double latitude, final double radius, final GeoUnit unit) {
    960. sendCommand(GEORADIUS_RO, key, toByteArray(longitude), toByteArray(latitude), toByteArray(radius),
    961. unit.raw);
    962. }
    963. public void georadius(final byte[] key, final double longitude, final double latitude, final double radius, final GeoUnit unit,
    964. final GeoRadiusParam param) {
    965. sendCommand(GEORADIUS, param.getByteParams(key, toByteArray(longitude), toByteArray(latitude),
    966. toByteArray(radius), unit.raw));
    967. }
    968. public void georadiusReadonly(final byte[] key, final double longitude, final double latitude, final double radius, final GeoUnit unit,
    969. final GeoRadiusParam param) {
    970. sendCommand(GEORADIUS_RO, param.getByteParams(key, toByteArray(longitude), toByteArray(latitude),
    971. toByteArray(radius), unit.raw));
    972. }
    973. public void georadiusByMember(final byte[] key, final byte[] member, final double radius, final GeoUnit unit) {
    974. sendCommand(GEORADIUSBYMEMBER, key, member, toByteArray(radius), unit.raw);
    975. }
    976. public void georadiusByMemberReadonly(final byte[] key, final byte[] member, final double radius, final GeoUnit unit) {
    977. sendCommand(GEORADIUSBYMEMBER_RO, key, member, toByteArray(radius), unit.raw);
    978. }
    979. public void georadiusByMember(final byte[] key, final byte[] member, final double radius, final GeoUnit unit,
    980. final GeoRadiusParam param) {
    981. sendCommand(GEORADIUSBYMEMBER, param.getByteParams(key, member, toByteArray(radius), unit.raw));
    982. }
    983. public void georadiusByMemberReadonly(final byte[] key, final byte[] member, final double radius, final GeoUnit unit,
    984. final GeoRadiusParam param) {
    985. sendCommand(GEORADIUSBYMEMBER_RO, param.getByteParams(key, member, toByteArray(radius), unit.raw));
    986. }
    987. public void moduleLoad(final byte[] path) {
    988. sendCommand(MODULE, Keyword.LOAD.raw, path);
    989. }
    990. public void moduleList() {
    991. sendCommand(MODULE, Keyword.LIST.raw);
    992. }
    993. public void moduleUnload(final byte[] name) {
    994. sendCommand(MODULE, Keyword.UNLOAD.raw, name);
    995. }
    996. private ArrayList convertScoreMembersToByteArrays(final Map scoreMembers) {
    997. ArrayList args = new ArrayList<>(scoreMembers.size() * 2);
    998. for (EntryDouble> entry : scoreMembers.entrySet()) {
    999. args.add(toByteArray(entry.getValue()));
    1000. args.add(entry.getKey());
    1001. }
    1002. return args;
    1003. }
    1004. public void aclWhoAmI() { sendCommand(ACL, Keyword.WHOAMI.raw); }
    1005. public void aclGenPass() { sendCommand(ACL, Keyword.GENPASS.raw); }
    1006. public void aclList() { sendCommand(ACL, Keyword.LIST.raw); }
    1007. public void aclUsers() { sendCommand(ACL, Keyword.USERS.raw); }
    1008. public void aclCat() { sendCommand(ACL, Keyword.CAT.raw); }
    1009. public void aclCat(final byte[] category) {
    1010. sendCommand(ACL, Keyword.CAT.raw, category);
    1011. }
    1012. public void aclSetUser(final byte[] name) {
    1013. sendCommand(ACL, Keyword.SETUSER.raw, name);
    1014. }
    1015. public void aclGetUser(final byte[] name) {
    1016. sendCommand(ACL, Keyword.GETUSER.raw, name);
    1017. }
    1018. public void aclSetUser(final byte[] name, byte[][] parameters) {
    1019. sendCommand(ACL, joinParameters(Keyword.SETUSER.raw,name, parameters));
    1020. }
    1021. public void aclDelUser(final byte[] name) {
    1022. sendCommand(ACL, Keyword.DELUSER.raw, name);
    1023. }
    1024. private List convertGeoCoordinateMapToByteArrays(
    1025. final Map memberCoordinateMap) {
    1026. List args = new ArrayList<>(memberCoordinateMap.size() * 3);
    1027. for (EntryGeoCoordinate> entry : memberCoordinateMap.entrySet()) {
    1028. GeoCoordinate coordinate = entry.getValue();
    1029. args.add(toByteArray(coordinate.getLongitude()));
    1030. args.add(toByteArray(coordinate.getLatitude()));
    1031. args.add(entry.getKey());
    1032. }
    1033. return args;
    1034. }
    1035. public void bitfield(final byte[] key, final byte[]... value) {
    1036. sendCommand(BITFIELD, joinParameters(key, value));
    1037. }
    1038. public void bitfieldReadonly(final byte[] key, final byte[]... arguments) {
    1039. sendCommand(BITFIELD_RO, joinParameters(key, arguments));
    1040. }
    1041. public void hstrlen(final byte[] key, final byte[] field) {
    1042. sendCommand(HSTRLEN, key, field);
    1043. }
    1044. public void xadd(final byte[] key, final byte[] id, final Map hash, long maxLen, boolean approximateLength) {
    1045. int maxLexArgs = 0;
    1046. if(maxLen < Long.MAX_VALUE) { // optional arguments
    1047. if(approximateLength) {
    1048. maxLexArgs = 3; // e.g. MAXLEN ~ 1000
    1049. } else {
    1050. maxLexArgs = 2; // e.g. MAXLEN 1000
    1051. }
    1052. }
    1053. final byte[][] params = new byte[2 + maxLexArgs + hash.size() * 2][];
    1054. int index = 0;
    1055. params[index++] = key;
    1056. if(maxLen < Long.MAX_VALUE) {
    1057. params[index++] = Keyword.MAXLEN.raw;
    1058. if(approximateLength) {
    1059. params[index++] = Protocol.BYTES_TILDE;
    1060. }
    1061. params[index++] = toByteArray(maxLen);
    1062. }
    1063. params[index++] = id;
    1064. for (final Entry entry : hash.entrySet()) {
    1065. params[index++] = entry.getKey();
    1066. params[index++] = entry.getValue();
    1067. }
    1068. sendCommand(XADD, params);
    1069. }
    1070. public void xlen(final byte[] key) {
    1071. sendCommand(XLEN, key);
    1072. }
    1073. public void xrange(final byte[] key, final byte[] start, final byte[] end, final long count) {
    1074. sendCommand(XRANGE, key, start, end, Keyword.COUNT.raw, toByteArray(count));
    1075. }
    1076. public void xrevrange(final byte[] key, final byte[] end, final byte[] start, final int count) {
    1077. sendCommand(XREVRANGE, key, end, start, Keyword.COUNT.raw, toByteArray(count));
    1078. }
    1079. public void xread(final int count, final long block, final Map streams) {
    1080. final byte[][] params = new byte[3 + streams.size() * 2 + (block > 0 ? 2 : 0)][];
    1081. int streamsIndex = 0;
    1082. params[streamsIndex++] = Keyword.COUNT.raw;
    1083. params[streamsIndex++] = toByteArray(count);
    1084. if(block > 0) {
    1085. params[streamsIndex++] = Keyword.BLOCK.raw;
    1086. params[streamsIndex++] = toByteArray(block);
    1087. }
    1088. params[streamsIndex++] = Keyword.STREAMS.raw;
    1089. int idsIndex = streamsIndex + streams.size();
    1090. for (final Entry entry : streams.entrySet()) {
    1091. params[streamsIndex++] = entry.getKey();
    1092. params[idsIndex++] = entry.getValue();
    1093. }
    1094. sendCommand(XREAD, params);
    1095. }
    1096. public void xack(final byte[] key, final byte[] group, final byte[]... ids) {
    1097. final byte[][] params = new byte[2 + ids.length][];
    1098. int index = 0;
    1099. params[index++] = key;
    1100. params[index++] = group;
    1101. for (final byte[] id : ids) {
    1102. params[index++] = id;
    1103. }
    1104. sendCommand(XACK, params);
    1105. }
    1106. public void xgroupCreate(final byte[] key, final byte[] groupname, final byte[] id, boolean makeStream) {
    1107. if(makeStream) {
    1108. sendCommand(XGROUP, Keyword.CREATE.raw, key, groupname, id, Keyword.MKSTREAM.raw);
    1109. } else {
    1110. sendCommand(XGROUP, Keyword.CREATE.raw, key, groupname, id);
    1111. }
    1112. }
    1113. public void xgroupSetID(final byte[] key, final byte[] groupname, final byte[] id) {
    1114. sendCommand(XGROUP, Keyword.SETID.raw, key, groupname, id);
    1115. }
    1116. public void xgroupDestroy(final byte[] key, final byte[] groupname) {
    1117. sendCommand(XGROUP, Keyword.DESTROY.raw, key, groupname);
    1118. }
    1119. public void xgroupDelConsumer(final byte[] key, final byte[] groupname, final byte[] consumerName) {
    1120. sendCommand(XGROUP, Keyword.DELCONSUMER.raw, key, groupname, consumerName);
    1121. }
    1122. public void xdel(final byte[] key, final byte[]... ids) {
    1123. final byte[][] params = new byte[1 + ids.length][];
    1124. int index = 0;
    1125. params[index++] = key;
    1126. for (final byte[] id : ids) {
    1127. params[index++] = id;
    1128. }
    1129. sendCommand(XDEL, params);
    1130. }
    1131. public void xtrim(byte[] key, long maxLen, boolean approximateLength) {
    1132. if(approximateLength) {
    1133. sendCommand(XTRIM, key, Keyword.MAXLEN.raw, Protocol.BYTES_TILDE ,toByteArray(maxLen));
    1134. } else {
    1135. sendCommand(XTRIM, key, Keyword.MAXLEN.raw, toByteArray(maxLen));
    1136. }
    1137. }
    1138. public void xreadGroup(byte[] groupname, byte[] consumer, int count, long block, boolean noAck, Map streams) {
    1139. int optional = 0;
    1140. if(count>0) {
    1141. optional += 2;
    1142. }
    1143. if(block > 0) {
    1144. optional += 2;
    1145. }
    1146. if(noAck) {
    1147. optional += 1;
    1148. }
    1149. final byte[][] params = new byte[4 + optional + streams.size() * 2][];
    1150. int streamsIndex = 0;
    1151. params[streamsIndex++] = Keyword.GROUP.raw;
    1152. params[streamsIndex++] = groupname;
    1153. params[streamsIndex++] = consumer;
    1154. if(count>0) {
    1155. params[streamsIndex++] = Keyword.COUNT.raw;
    1156. params[streamsIndex++] = toByteArray(count);
    1157. }
    1158. if(block > 0) {
    1159. params[streamsIndex++] = Keyword.BLOCK.raw;
    1160. params[streamsIndex++] = toByteArray(block);
    1161. }
    1162. if(noAck) {
    1163. params[streamsIndex++] = Keyword.NOACK.raw;
    1164. }
    1165. params[streamsIndex++] = Keyword.STREAMS.raw;
    1166. int idsIndex = streamsIndex + streams.size();
    1167. for (final Entry entry : streams.entrySet()) {
    1168. params[streamsIndex++] = entry.getKey();
    1169. params[idsIndex++] = entry.getValue();
    1170. }
    1171. sendCommand(XREADGROUP, params);
    1172. }
    1173. public void xpending(byte[] key, byte[] groupname, byte[] start, byte[] end, int count, byte[] consumername) {
    1174. if(consumername == null) {
    1175. sendCommand(XPENDING, key, groupname, start, end, toByteArray(count));
    1176. } else {
    1177. sendCommand(XPENDING, key, groupname, start, end, toByteArray(count), consumername);
    1178. }
    1179. }
    1180. public void xclaim(byte[] key, byte[] groupname, byte[] consumername, long minIdleTime, long newIdleTime, int retries, boolean force, byte[][] ids) {
    1181. ArrayList arguments = new ArrayList<>(10 + ids.length);
    1182. arguments.add(key);
    1183. arguments.add(groupname);
    1184. arguments.add(consumername);
    1185. arguments.add(toByteArray(minIdleTime));
    1186. for(byte[] id : ids) {
    1187. arguments.add(id);
    1188. }
    1189. if(newIdleTime > 0) {
    1190. arguments.add(Keyword.IDLE.raw);
    1191. arguments.add(toByteArray(newIdleTime));
    1192. }
    1193. if(retries > 0) {
    1194. arguments.add(Keyword.RETRYCOUNT.raw);
    1195. arguments.add(toByteArray(retries));
    1196. }
    1197. if(force) {
    1198. arguments.add(Keyword.FORCE.raw);
    1199. }
    1200. sendCommand(XCLAIM, arguments.toArray(new byte[arguments.size()][]));
    1201. }
    1202. public void xinfoStream(byte[] key) {
    1203. sendCommand(XINFO,Keyword.STREAM.raw,key);
    1204. }
    1205. public void xinfoGroup(byte[] key) {
    1206. sendCommand(XINFO,Keyword.GROUPS.raw,key);
    1207. }
    1208. public void xinfoConsumers (byte[] key, byte[] group) {
    1209. sendCommand(XINFO,Keyword.CONSUMERS.raw,key,group);
    1210. }
    1211. }

     springboot通过用户名连接redis-cluster   redis7,

    连接配置如下

    1. spring:
    2. redis:
    3. cluster:
    4. # 集群节点
    5. nodes: 172.4.2.65:30001,172.4.2.65:30002,172.4.2.65:30003,172.4.2.65:30004,172.4.2.65:30005,172.4.2.65:30006
    6. # 最大重定向次数
    7. max-redirects: 5
    8. # 密码
    9. user: test
    10. password: test@123

    多覆盖一个文件

    新建包目录   redis.clients.jedis

    新建类BinaryJedis.java

    1. package redis.clients.jedis;
    2. import static redis.clients.jedis.Protocol.toByteArray;
    3. import java.io.Closeable;
    4. import java.io.Serializable;
    5. import java.net.URI;
    6. import java.util.AbstractMap;
    7. import java.util.AbstractSet;
    8. import java.util.ArrayList;
    9. import java.util.Collection;
    10. import java.util.Collections;
    11. import java.util.Iterator;
    12. import java.util.LinkedHashSet;
    13. import java.util.List;
    14. import java.util.Map;
    15. import java.util.Set;
    16. import javax.net.ssl.HostnameVerifier;
    17. import javax.net.ssl.SSLParameters;
    18. import javax.net.ssl.SSLSocketFactory;
    19. import org.apache.commons.lang3.StringUtils;
    20. import redis.clients.jedis.commands.AdvancedBinaryJedisCommands;
    21. import redis.clients.jedis.commands.BasicCommands;
    22. import redis.clients.jedis.commands.BinaryJedisCommands;
    23. import redis.clients.jedis.commands.BinaryScriptingCommands;
    24. import redis.clients.jedis.commands.MultiKeyBinaryCommands;
    25. import redis.clients.jedis.commands.ProtocolCommand;
    26. import redis.clients.jedis.exceptions.InvalidURIException;
    27. import redis.clients.jedis.exceptions.JedisDataException;
    28. import redis.clients.jedis.exceptions.JedisException;
    29. import redis.clients.jedis.params.ClientKillParams;
    30. import redis.clients.jedis.params.GeoRadiusParam;
    31. import redis.clients.jedis.params.MigrateParams;
    32. import redis.clients.jedis.params.SetParams;
    33. import redis.clients.jedis.params.ZAddParams;
    34. import redis.clients.jedis.params.ZIncrByParams;
    35. import redis.clients.jedis.util.JedisByteHashMap;
    36. import redis.clients.jedis.util.JedisURIHelper;
    37. public class BinaryJedis implements BasicCommands, BinaryJedisCommands, MultiKeyBinaryCommands,
    38. AdvancedBinaryJedisCommands, BinaryScriptingCommands, Closeable {
    39. protected Client client = null;
    40. protected Transaction transaction = null;
    41. protected Pipeline pipeline = null;
    42. private final byte[][] dummyArray = new byte[0][];
    43. private String user;
    44. {
    45. String user = SpringUtils.getApplicationContext().getEnvironment().getProperty("spring.redis.user");
    46. if(StringUtils.isNotBlank(user)){
    47. this.user = user;
    48. }
    49. }
    50. public BinaryJedis() {
    51. client = new Client();
    52. }
    53. public BinaryJedis(final String host) {
    54. URI uri = URI.create(host);
    55. if (JedisURIHelper.isValid(uri)) {
    56. initializeClientFromURI(uri);
    57. } else {
    58. client = new Client(host);
    59. }
    60. }
    61. public BinaryJedis(final HostAndPort hp) {
    62. this(hp.getHost(), hp.getPort());
    63. }
    64. public BinaryJedis(final String host, final int port) {
    65. client = new Client(host, port);
    66. }
    67. public BinaryJedis(final String host, final int port, final boolean ssl) {
    68. client = new Client(host, port, ssl);
    69. }
    70. public BinaryJedis(final String host, final int port, final boolean ssl,
    71. final SSLSocketFactory sslSocketFactory, final SSLParameters sslParameters,
    72. final HostnameVerifier hostnameVerifier) {
    73. client = new Client(host, port, ssl, sslSocketFactory, sslParameters, hostnameVerifier);
    74. }
    75. public BinaryJedis(final String host, final int port, final int timeout) {
    76. this(host, port, timeout, timeout);
    77. }
    78. public BinaryJedis(final String host, final int port, final int timeout, final boolean ssl) {
    79. this(host, port, timeout, timeout, ssl);
    80. }
    81. public BinaryJedis(final String host, final int port, final int timeout, final boolean ssl,
    82. final SSLSocketFactory sslSocketFactory, final SSLParameters sslParameters,
    83. final HostnameVerifier hostnameVerifier) {
    84. this(host, port, timeout, timeout, ssl, sslSocketFactory, sslParameters, hostnameVerifier);
    85. }
    86. public BinaryJedis(final String host, final int port, final int connectionTimeout,
    87. final int soTimeout) {
    88. client = new Client(host, port);
    89. client.setConnectionTimeout(connectionTimeout);
    90. client.setSoTimeout(soTimeout);
    91. }
    92. public BinaryJedis(final String host, final int port, final int connectionTimeout,
    93. final int soTimeout, final boolean ssl) {
    94. client = new Client(host, port, ssl);
    95. client.setConnectionTimeout(connectionTimeout);
    96. client.setSoTimeout(soTimeout);
    97. }
    98. public BinaryJedis(final String host, final int port, final int connectionTimeout,
    99. final int soTimeout, final boolean ssl, final SSLSocketFactory sslSocketFactory,
    100. final SSLParameters sslParameters, final HostnameVerifier hostnameVerifier) {
    101. client = new Client(host, port, ssl, sslSocketFactory, sslParameters, hostnameVerifier);
    102. client.setConnectionTimeout(connectionTimeout);
    103. client.setSoTimeout(soTimeout);
    104. }
    105. public BinaryJedis(final JedisShardInfo shardInfo) {
    106. client = new Client(shardInfo.getHost(), shardInfo.getPort(), shardInfo.getSsl(),
    107. shardInfo.getSslSocketFactory(), shardInfo.getSslParameters(),
    108. shardInfo.getHostnameVerifier());
    109. client.setConnectionTimeout(shardInfo.getConnectionTimeout());
    110. client.setSoTimeout(shardInfo.getSoTimeout());
    111. client.setUser(shardInfo.getUser());
    112. client.setPassword(shardInfo.getPassword());
    113. client.setDb(shardInfo.getDb());
    114. }
    115. public BinaryJedis(URI uri) {
    116. initializeClientFromURI(uri);
    117. }
    118. public BinaryJedis(URI uri, final SSLSocketFactory sslSocketFactory,
    119. final SSLParameters sslParameters, final HostnameVerifier hostnameVerifier) {
    120. initializeClientFromURI(uri, sslSocketFactory, sslParameters, hostnameVerifier);
    121. }
    122. public BinaryJedis(final URI uri, final int timeout) {
    123. this(uri, timeout, timeout);
    124. }
    125. public BinaryJedis(final URI uri, final int timeout, final SSLSocketFactory sslSocketFactory,
    126. final SSLParameters sslParameters, final HostnameVerifier hostnameVerifier) {
    127. this(uri, timeout, timeout, sslSocketFactory, sslParameters, hostnameVerifier);
    128. }
    129. public BinaryJedis(final URI uri, final int connectionTimeout, final int soTimeout) {
    130. initializeClientFromURI(uri);
    131. client.setConnectionTimeout(connectionTimeout);
    132. client.setSoTimeout(soTimeout);
    133. }
    134. public BinaryJedis(final URI uri, final int connectionTimeout, final int soTimeout,
    135. final SSLSocketFactory sslSocketFactory,final SSLParameters sslParameters,
    136. final HostnameVerifier hostnameVerifier) {
    137. initializeClientFromURI(uri, sslSocketFactory, sslParameters, hostnameVerifier);
    138. client.setConnectionTimeout(connectionTimeout);
    139. client.setSoTimeout(soTimeout);
    140. }
    141. public BinaryJedis(final JedisSocketFactory jedisSocketFactory) {
    142. client = new Client(jedisSocketFactory);
    143. }
    144. private void initializeClientFromURI(URI uri) {
    145. initializeClientFromURI(uri, null, null, null);
    146. }
    147. private void initializeClientFromURI(URI uri, final SSLSocketFactory sslSocketFactory,
    148. final SSLParameters sslParameters, final HostnameVerifier hostnameVerifier) {
    149. if (!JedisURIHelper.isValid(uri)) {
    150. throw new InvalidURIException(String.format(
    151. "Cannot open Redis connection due invalid URI. %s", uri.toString()));
    152. }
    153. client = new Client(uri.getHost(), uri.getPort(), JedisURIHelper.isRedisSSLScheme(uri),
    154. sslSocketFactory, sslParameters, hostnameVerifier);
    155. String password = JedisURIHelper.getPassword(uri);
    156. if (password != null) {
    157. String user = JedisURIHelper.getUser(uri);
    158. if (user == null) {
    159. client.auth(password);
    160. } else {
    161. client.auth(user, password);
    162. }
    163. client.getStatusCodeReply();
    164. }
    165. int dbIndex = JedisURIHelper.getDBIndex(uri);
    166. if (dbIndex > 0) {
    167. client.select(dbIndex);
    168. client.getStatusCodeReply();
    169. client.setDb(dbIndex);
    170. }
    171. }
    172. @Override
    173. public String ping() {
    174. checkIsInMultiOrPipeline();
    175. client.ping();
    176. return client.getStatusCodeReply();
    177. }
    178. /**
    179. * Works same as ping() but returns argument message instead of PONG.
    180. * @param message
    181. * @return message
    182. */
    183. public byte[] ping(final byte[] message) {
    184. checkIsInMultiOrPipeline();
    185. client.ping(message);
    186. return client.getBinaryBulkReply();
    187. }
    188. /**
    189. * Set the string value as value of the key. The string can't be longer than 1073741824 bytes (1
    190. * GB).
    191. *

    192. * Time complexity: O(1)
    193. * @param key
    194. * @param value
    195. * @return Status code reply
    196. */
    197. @Override
    198. public String set(final byte[] key, final byte[] value) {
    199. checkIsInMultiOrPipeline();
    200. client.set(key, value);
    201. return client.getStatusCodeReply();
    202. }
    203. /**
    204. * Set the string value as value of the key. The string can't be longer than 1073741824 bytes (1
    205. * GB).
    206. * @param key
    207. * @param value
    208. * @param params
    209. * @return Status code reply
    210. */
    211. @Override
    212. public String set(final byte[] key, final byte[] value, final SetParams params) {
    213. checkIsInMultiOrPipeline();
    214. client.set(key, value, params);
    215. return client.getStatusCodeReply();
    216. }
    217. /**
    218. * Get the value of the specified key. If the key does not exist the special value 'nil' is
    219. * returned. If the value stored at key is not a string an error is returned because GET can only
    220. * handle string values.
    221. *

    222. * Time complexity: O(1)
    223. * @param key
    224. * @return Bulk reply
    225. */
    226. @Override
    227. public byte[] get(final byte[] key) {
    228. checkIsInMultiOrPipeline();
    229. client.get(key);
    230. return client.getBinaryBulkReply();
    231. }
    232. /**
    233. * Ask the server to silently close the connection.
    234. */
    235. @Override
    236. public String quit() {
    237. checkIsInMultiOrPipeline();
    238. client.quit();
    239. String quitReturn = client.getStatusCodeReply();
    240. client.disconnect();
    241. return quitReturn;
    242. }
    243. /**
    244. * Test if the specified keys exist. The command returns the number of keys exist.
    245. * Time complexity: O(N)
    246. * @param keys
    247. * @return Integer reply, specifically: an integer greater than 0 if one or more keys exist,
    248. * 0 if none of the specified keys exist.
    249. */
    250. @Override
    251. public Long exists(final byte[]... keys) {
    252. checkIsInMultiOrPipeline();
    253. client.exists(keys);
    254. return client.getIntegerReply();
    255. }
    256. /**
    257. * Test if the specified key exists. The command returns true if the key exists, otherwise false is
    258. * returned. Note that even keys set with an empty string as value will return true. Time
    259. * complexity: O(1)
    260. * @param key
    261. * @return Boolean reply, true if the key exists, otherwise false
    262. */
    263. @Override
    264. public Boolean exists(final byte[] key) {
    265. checkIsInMultiOrPipeline();
    266. client.exists(key);
    267. return client.getIntegerReply() == 1;
    268. }
    269. /**
    270. * Remove the specified keys. If a given key does not exist no operation is performed for this
    271. * key. The command returns the number of keys removed. Time complexity: O(1)
    272. * @param keys
    273. * @return Integer reply, specifically: an integer greater than 0 if one or more keys were removed
    274. * 0 if none of the specified key existed
    275. */
    276. @Override
    277. public Long del(final byte[]... keys) {
    278. checkIsInMultiOrPipeline();
    279. client.del(keys);
    280. return client.getIntegerReply();
    281. }
    282. @Override
    283. public Long del(final byte[] key) {
    284. checkIsInMultiOrPipeline();
    285. client.del(key);
    286. return client.getIntegerReply();
    287. }
    288. /**
    289. * This command is very similar to DEL: it removes the specified keys. Just like DEL a key is
    290. * ignored if it does not exist. However the command performs the actual memory reclaiming in a
    291. * different thread, so it is not blocking, while DEL is. This is where the command name comes
    292. * from: the command just unlinks the keys from the keyspace. The actual removal will happen later
    293. * asynchronously.
    294. *

    295. * Time complexity: O(1) for each key removed regardless of its size. Then the command does O(N)
    296. * work in a different thread in order to reclaim memory, where N is the number of allocations the
    297. * deleted objects where composed of.
    298. * @param keys
    299. * @return Integer reply: The number of keys that were unlinked
    300. */
    301. @Override
    302. public Long unlink(final byte[]... keys) {
    303. checkIsInMultiOrPipeline();
    304. client.unlink(keys);
    305. return client.getIntegerReply();
    306. }
    307. @Override
    308. public Long unlink(final byte[] key) {
    309. checkIsInMultiOrPipeline();
    310. client.unlink(key);
    311. return client.getIntegerReply();
    312. }
    313. /**
    314. * Return the type of the value stored at key in form of a string. The type can be one of "none",
    315. * "string", "list", "set". "none" is returned if the key does not exist. Time complexity: O(1)
    316. * @param key
    317. * @return Status code reply, specifically: "none" if the key does not exist "string" if the key
    318. * contains a String value "list" if the key contains a List value "set" if the key
    319. * contains a Set value "zset" if the key contains a Sorted Set value "hash" if the key
    320. * contains a Hash value
    321. */
    322. @Override
    323. public String type(final byte[] key) {
    324. checkIsInMultiOrPipeline();
    325. client.type(key);
    326. return client.getStatusCodeReply();
    327. }
    328. /**
    329. * Delete all the keys of the currently selected DB. This command never fails.
    330. * @return Status code reply
    331. */
    332. @Override
    333. public String flushDB() {
    334. checkIsInMultiOrPipeline();
    335. client.flushDB();
    336. return client.getStatusCodeReply();
    337. }
    338. /**
    339. * Returns all the keys matching the glob-style pattern as space separated strings. For example if
    340. * you have in the database the keys "foo" and "foobar" the command "KEYS foo*" will return
    341. * "foo foobar".
    342. *

    343. * Note that while the time complexity for this operation is O(n) the constant times are pretty
    344. * low. For example Redis running on an entry level laptop can scan a 1 million keys database in
    345. * 40 milliseconds. Still it's better to consider this one of the slow commands that may ruin
    346. * the DB performance if not used with care.
    347. *

    348. * In other words this command is intended only for debugging and special operations like creating
    349. * a script to change the DB schema. Don't use it in your normal code. Use Redis Sets in order to
    350. * group together a subset of objects.
    351. *

    352. * Glob style patterns examples:
    353. *
      • *
      • h?llo will match hello hallo hhllo
    354. *
    355. h*llo will match hllo heeeello
  • *
  • h[ae]llo will match hello and hallo, but not hillo
  • *
  • *

  • * Use \ to escape special chars if you want to match them verbatim.
  • *

  • * Time complexity: O(n) (with n being the number of keys in the DB, and assuming keys and pattern
  • * of limited length)
  • * @param pattern
  • * @return Multi bulk reply
  • */
  • @Override
  • public Set keys(final byte[] pattern) {
  • checkIsInMultiOrPipeline();
  • client.keys(pattern);
  • return SetFromList.of(client.getBinaryMultiBulkReply());
  • }
  • /**
  • * Return a randomly selected key from the currently selected DB.
  • *

  • * Time complexity: O(1)
  • * @return Single line reply, specifically the randomly selected key or an empty string is the
  • * database is empty
  • */
  • @Override
  • public byte[] randomBinaryKey() {
  • checkIsInMultiOrPipeline();
  • client.randomKey();
  • return client.getBinaryBulkReply();
  • }
  • /**
  • * Atomically renames the key oldkey to newkey. If the source and destination name are the same an
  • * error is returned. If newkey already exists it is overwritten.
  • *

  • * Time complexity: O(1)
  • * @param oldkey
  • * @param newkey
  • * @return Status code repy
  • */
  • @Override
  • public String rename(final byte[] oldkey, final byte[] newkey) {
  • checkIsInMultiOrPipeline();
  • client.rename(oldkey, newkey);
  • return client.getStatusCodeReply();
  • }
  • /**
  • * Rename oldkey into newkey but fails if the destination key newkey already exists.
  • *

  • * Time complexity: O(1)
  • * @param oldkey
  • * @param newkey
  • * @return Integer reply, specifically: 1 if the key was renamed 0 if the target key already exist
  • */
  • @Override
  • public Long renamenx(final byte[] oldkey, final byte[] newkey) {
  • checkIsInMultiOrPipeline();
  • client.renamenx(oldkey, newkey);
  • return client.getIntegerReply();
  • }
  • /**
  • * Return the number of keys in the currently selected database.
  • * @return Integer reply
  • */
  • @Override
  • public Long dbSize() {
  • checkIsInMultiOrPipeline();
  • client.dbSize();
  • return client.getIntegerReply();
  • }
  • /**
  • * Set a timeout on the specified key. After the timeout the key will be automatically deleted by
  • * the server. A key with an associated timeout is said to be volatile in Redis terminology.
  • *

  • * Volatile keys are stored on disk like the other keys, the timeout is persistent too like all the
  • * other aspects of the dataset. Saving a dataset containing expires and stopping the server does
  • * not stop the flow of time as Redis stores on disk the time when the key will no longer be
  • * available as Unix time, and not the remaining seconds.
  • *

  • * Since Redis 2.1.3 you can update the value of the timeout of a key already having an expire
  • * set. It is also possible to undo the expire at all turning the key into a normal key using the
  • * {@link #persist(byte[]) PERSIST} command.
  • *

  • * Time complexity: O(1)
  • * @param key
  • * @param seconds
  • * @return Integer reply, specifically: 1: the timeout was set. 0: the timeout was not set since
  • * the key already has an associated timeout (this may happen only in Redis versions <
  • * 2.1.3, Redis >= 2.1.3 will happily update the timeout), or the key does not exist.
  • */
  • @Override
  • public Long expire(final byte[] key, final int seconds) {
  • checkIsInMultiOrPipeline();
  • client.expire(key, seconds);
  • return client.getIntegerReply();
  • }
  • /**
  • * EXPIREAT works exactly like {@link #expire(byte[], int) EXPIRE} but instead to get the number of
  • * seconds representing the Time To Live of the key as a second argument (that is a relative way
  • * of specifying the TTL), it takes an absolute one in the form of a UNIX timestamp (Number of
  • * seconds elapsed since 1 Gen 1970).
  • *

  • * EXPIREAT was introduced in order to implement the Append Only File persistence mode so that
  • * EXPIRE commands are automatically translated into EXPIREAT commands for the append only file.
  • * Of course EXPIREAT can also used by programmers that need a way to simply specify that a given
  • * key should expire at a given time in the future.
  • *

  • * Since Redis 2.1.3 you can update the value of the timeout of a key already having an expire
  • * set. It is also possible to undo the expire at all turning the key into a normal key using the
  • * {@link #persist(byte[]) PERSIST} command.
  • *

  • * Time complexity: O(1)
  • * @param key
  • * @param unixTime
  • * @return Integer reply, specifically: 1: the timeout was set. 0: the timeout was not set since
  • * the key already has an associated timeout (this may happen only in Redis versions <
  • * 2.1.3, Redis >= 2.1.3 will happily update the timeout), or the key does not exist.
  • */
  • @Override
  • public Long expireAt(final byte[] key, final long unixTime) {
  • checkIsInMultiOrPipeline();
  • client.expireAt(key, unixTime);
  • return client.getIntegerReply();
  • }
  • /**
  • * The TTL command returns the remaining time to live in seconds of a key that has an
  • * {@link #expire(byte[], int) EXPIRE} set. This introspection capability allows a Redis client to
  • * check how many seconds a given key will continue to be part of the dataset.
  • * @param key
  • * @return Integer reply, returns the remaining time to live in seconds of a key that has an
  • * EXPIRE. If the Key does not exists or does not have an associated expire, -1 is
  • * returned.
  • */
  • @Override
  • public Long ttl(final byte[] key) {
  • checkIsInMultiOrPipeline();
  • client.ttl(key);
  • return client.getIntegerReply();
  • }
  • /**
  • * Alters the last access time of a key(s). A key is ignored if it does not exist.
  • * Time complexity: O(N) where N is the number of keys that will be touched.
  • * @param keys
  • * @return Integer reply: The number of keys that were touched.
  • */
  • @Override
  • public Long touch(final byte[]... keys) {
  • checkIsInMultiOrPipeline();
  • client.touch(keys);
  • return client.getIntegerReply();
  • }
  • @Override
  • public Long touch(final byte[] key) {
  • checkIsInMultiOrPipeline();
  • client.touch(key);
  • return client.getIntegerReply();
  • }
  • /**
  • * Select the DB with having the specified zero-based numeric index. For default every new client
  • * connection is automatically selected to DB 0.
  • * @param index
  • * @return Status code reply
  • */
  • @Override
  • public String select(final int index) {
  • checkIsInMultiOrPipeline();
  • client.select(index);
  • String statusCodeReply = client.getStatusCodeReply();
  • client.setDb(index);
  • return statusCodeReply;
  • }
  • @Override
  • public String swapDB(final int index1, final int index2) {
  • checkIsInMultiOrPipeline();
  • client.swapDB(index1, index2);
  • return client.getStatusCodeReply();
  • }
  • /**
  • * Move the specified key from the currently selected DB to the specified destination DB. Note
  • * that this command returns 1 only if the key was successfully moved, and 0 if the target key was
  • * already there or if the source key was not found at all, so it is possible to use MOVE as a
  • * locking primitive.
  • * @param key
  • * @param dbIndex
  • * @return Integer reply, specifically: 1 if the key was moved 0 if the key was not moved because
  • * already present on the target DB or was not found in the current DB.
  • */
  • @Override
  • public Long move(final byte[] key, final int dbIndex) {
  • checkIsInMultiOrPipeline();
  • client.move(key, dbIndex);
  • return client.getIntegerReply();
  • }
  • /**
  • * Delete all the keys of all the existing databases, not just the currently selected one. This
  • * command never fails.
  • * @return Status code reply
  • */
  • @Override
  • public String flushAll() {
  • checkIsInMultiOrPipeline();
  • client.flushAll();
  • return client.getStatusCodeReply();
  • }
  • /**
  • * GETSET is an atomic set this value and return the old value command. Set key to the string
  • * value and return the old value stored at key. The string can't be longer than 1073741824 bytes
  • * (1 GB).
  • *

  • * Time complexity: O(1)
  • * @param key
  • * @param value
  • * @return Bulk reply
  • */
  • @Override
  • public byte[] getSet(final byte[] key, final byte[] value) {
  • checkIsInMultiOrPipeline();
  • client.getSet(key, value);
  • return client.getBinaryBulkReply();
  • }
  • /**
  • * Get the values of all the specified keys. If one or more keys don't exist or is not of type
  • * String, a 'nil' value is returned instead of the value of the specified key, but the operation
  • * never fails.
  • *

  • * Time complexity: O(1) for every key
  • * @param keys
  • * @return Multi bulk reply
  • */
  • @Override
  • public List mget(final byte[]... keys) {
  • checkIsInMultiOrPipeline();
  • client.mget(keys);
  • return client.getBinaryMultiBulkReply();
  • }
  • /**
  • * SETNX works exactly like {@link #set(byte[], byte[]) SET} with the only difference that if the
  • * key already exists no operation is performed. SETNX actually means "SET if Not eXists".
  • *

  • * Time complexity: O(1)
  • * @param key
  • * @param value
  • * @return Integer reply, specifically: 1 if the key was set 0 if the key was not set
  • */
  • @Override
  • public Long setnx(final byte[] key, final byte[] value) {
  • checkIsInMultiOrPipeline();
  • client.setnx(key, value);
  • return client.getIntegerReply();
  • }
  • /**
  • * The command is exactly equivalent to the following group of commands:
  • * {@link #set(byte[], byte[]) SET} + {@link #expire(byte[], int) EXPIRE}. The operation is
  • * atomic.
  • *

  • * Time complexity: O(1)
  • * @param key
  • * @param seconds
  • * @param value
  • * @return Status code reply
  • */
  • @Override
  • public String setex(final byte[] key, final int seconds, final byte[] value) {
  • checkIsInMultiOrPipeline();
  • client.setex(key, seconds, value);
  • return client.getStatusCodeReply();
  • }
  • /**
  • * Set the the respective keys to the respective values. MSET will replace old values with new
  • * values, while {@link #msetnx(byte[]...) MSETNX} will not perform any operation at all even if
  • * just a single key already exists.
  • *

  • * Because of this semantic MSETNX can be used in order to set different keys representing
  • * different fields of an unique logic object in a way that ensures that either all the fields or
  • * none at all are set.
  • *

  • * Both MSET and MSETNX are atomic operations. This means that for instance if the keys A and B
  • * are modified, another client talking to Redis can either see the changes to both A and B at
  • * once, or no modification at all.
  • * @see #msetnx(byte[]...)
  • * @param keysvalues
  • * @return Status code reply Basically +OK as MSET can't fail
  • */
  • @Override
  • public String mset(final byte[]... keysvalues) {
  • checkIsInMultiOrPipeline();
  • client.mset(keysvalues);
  • return client.getStatusCodeReply();
  • }
  • /**
  • * Set the the respective keys to the respective values. {@link #mset(byte[]...) MSET} will
  • * replace old values with new values, while MSETNX will not perform any operation at all even if
  • * just a single key already exists.
  • *

  • * Because of this semantic MSETNX can be used in order to set different keys representing
  • * different fields of an unique logic object in a way that ensures that either all the fields or
  • * none at all are set.
  • *

  • * Both MSET and MSETNX are atomic operations. This means that for instance if the keys A and B
  • * are modified, another client talking to Redis can either see the changes to both A and B at
  • * once, or no modification at all.
  • * @see #mset(byte[]...)
  • * @param keysvalues
  • * @return Integer reply, specifically: 1 if the all the keys were set 0 if no key was set (at
  • * least one key already existed)
  • */
  • @Override
  • public Long msetnx(final byte[]... keysvalues) {
  • checkIsInMultiOrPipeline();
  • client.msetnx(keysvalues);
  • return client.getIntegerReply();
  • }
  • /**
  • * DECRBY work just like {@link #decr(byte[]) INCR} but instead to decrement by 1 the decrement is
  • * integer.
  • *

  • * INCR commands are limited to 64 bit signed integers.
  • *

  • * Note: this is actually a string operation, that is, in Redis there are not "integer" types.
  • * Simply the string stored at the key is parsed as a base 10 64 bit signed integer, incremented,
  • * and then converted back as a string.
  • *

  • * Time complexity: O(1)
  • * @see #incr(byte[])
  • * @see #decr(byte[])
  • * @see #incrBy(byte[], long)
  • * @param key
  • * @param decrement
  • * @return Integer reply, this commands will reply with the new value of key after the increment.
  • */
  • @Override
  • public Long decrBy(final byte[] key, final long decrement) {
  • checkIsInMultiOrPipeline();
  • client.decrBy(key, decrement);
  • return client.getIntegerReply();
  • }
  • /**
  • * Decrement the number stored at key by one. If the key does not exist or contains a value of a
  • * wrong type, set the key to the value of "0" before to perform the decrement operation.
  • *

  • * INCR commands are limited to 64 bit signed integers.
  • *

  • * Note: this is actually a string operation, that is, in Redis there are not "integer" types.
  • * Simply the string stored at the key is parsed as a base 10 64 bit signed integer, incremented,
  • * and then converted back as a string.
  • *

  • * Time complexity: O(1)
  • * @see #incr(byte[])
  • * @see #incrBy(byte[], long)
  • * @see #decrBy(byte[], long)
  • * @param key
  • * @return Integer reply, this commands will reply with the new value of key after the increment.
  • */
  • @Override
  • public Long decr(final byte[] key) {
  • checkIsInMultiOrPipeline();
  • client.decr(key);
  • return client.getIntegerReply();
  • }
  • /**
  • * INCRBY work just like {@link #incr(byte[]) INCR} but instead to increment by 1 the increment is
  • * integer.
  • *

  • * INCR commands are limited to 64 bit signed integers.
  • *

  • * Note: this is actually a string operation, that is, in Redis there are not "integer" types.
  • * Simply the string stored at the key is parsed as a base 10 64 bit signed integer, incremented,
  • * and then converted back as a string.
  • *

  • * Time complexity: O(1)
  • * @see #incr(byte[])
  • * @see #decr(byte[])
  • * @see #decrBy(byte[], long)
  • * @param key
  • * @param increment
  • * @return Integer reply, this commands will reply with the new value of key after the increment.
  • */
  • @Override
  • public Long incrBy(final byte[] key, final long increment) {
  • checkIsInMultiOrPipeline();
  • client.incrBy(key, increment);
  • return client.getIntegerReply();
  • }
  • /**
  • * INCRBYFLOAT work just like {@link #incrBy(byte[], long)} INCRBY} but increments by floats
  • * instead of integers.
  • *

  • * INCRBYFLOAT commands are limited to double precision floating point values.
  • *

  • * Note: this is actually a string operation, that is, in Redis there are not "double" types.
  • * Simply the string stored at the key is parsed as a base double precision floating point value,
  • * incremented, and then converted back as a string. There is no DECRYBYFLOAT but providing a
  • * negative value will work as expected.
  • *

  • * Time complexity: O(1)
  • * @see #incr(byte[])
  • * @see #decr(byte[])
  • * @see #decrBy(byte[], long)
  • * @param key the key to increment
  • * @param increment the value to increment by
  • * @return Integer reply, this commands will reply with the new value of key after the increment.
  • */
  • @Override
  • public Double incrByFloat(final byte[] key, final double increment) {
  • checkIsInMultiOrPipeline();
  • client.incrByFloat(key, increment);
  • String dval = client.getBulkReply();
  • return (dval != null ? new Double(dval) : null);
  • }
  • /**
  • * Increment the number stored at key by one. If the key does not exist or contains a value of a
  • * wrong type, set the key to the value of "0" before to perform the increment operation.
  • *

  • * INCR commands are limited to 64 bit signed integers.
  • *

  • * Note: this is actually a string operation, that is, in Redis there are not "integer" types.
  • * Simply the string stored at the key is parsed as a base 10 64 bit signed integer, incremented,
  • * and then converted back as a string.
  • *

  • * Time complexity: O(1)
  • * @see #incrBy(byte[], long)
  • * @see #decr(byte[])
  • * @see #decrBy(byte[], long)
  • * @param key
  • * @return Integer reply, this commands will reply with the new value of key after the increment.
  • */
  • @Override
  • public Long incr(final byte[] key) {
  • checkIsInMultiOrPipeline();
  • client.incr(key);
  • return client.getIntegerReply();
  • }
  • /**
  • * If the key already exists and is a string, this command appends the provided value at the end
  • * of the string. If the key does not exist it is created and set as an empty string, so APPEND
  • * will be very similar to SET in this special case.
  • *

  • * Time complexity: O(1). The amortized time complexity is O(1) assuming the appended value is
  • * small and the already present value is of any size, since the dynamic string library used by
  • * Redis will double the free space available on every reallocation.
  • * @param key
  • * @param value
  • * @return Integer reply, specifically the total length of the string after the append operation.
  • */
  • @Override
  • public Long append(final byte[] key, final byte[] value) {
  • checkIsInMultiOrPipeline();
  • client.append(key, value);
  • return client.getIntegerReply();
  • }
  • /**
  • * Return a subset of the string from offset start to offset end (both offsets are inclusive).
  • * Negative offsets can be used in order to provide an offset starting from the end of the string.
  • * So -1 means the last char, -2 the penultimate and so forth.
  • *

  • * The function handles out of range requests without raising an error, but just limiting the
  • * resulting range to the actual length of the string.
  • *

  • * Time complexity: O(start+n) (with start being the start index and n the total length of the
  • * requested range). Note that the lookup part of this command is O(1) so for small strings this
  • * is actually an O(1) command.
  • * @param key
  • * @param start
  • * @param end
  • * @return Bulk reply
  • */
  • @Override
  • public byte[] substr(final byte[] key, final int start, final int end) {
  • checkIsInMultiOrPipeline();
  • client.substr(key, start, end);
  • return client.getBinaryBulkReply();
  • }
  • /**
  • * Set the specified hash field to the specified value.
  • *

  • * If key does not exist, a new key holding a hash is created.
  • *

  • * Time complexity: O(1)
  • * @param key
  • * @param field
  • * @param value
  • * @return If the field already exists, and the HSET just produced an update of the value, 0 is
  • * returned, otherwise if a new field is created 1 is returned.
  • */
  • @Override
  • public Long hset(final byte[] key, final byte[] field, final byte[] value) {
  • checkIsInMultiOrPipeline();
  • client.hset(key, field, value);
  • return client.getIntegerReply();
  • }
  • @Override
  • public Long hset(final byte[] key, final Map hash) {
  • checkIsInMultiOrPipeline();
  • client.hset(key, hash);
  • return client.getIntegerReply();
  • }
  • /**
  • * If key holds a hash, retrieve the value associated to the specified field.
  • *

  • * If the field is not found or the key does not exist, a special 'nil' value is returned.
  • *

  • * Time complexity: O(1)
  • * @param key
  • * @param field
  • * @return Bulk reply
  • */
  • @Override
  • public byte[] hget(final byte[] key, final byte[] field) {
  • checkIsInMultiOrPipeline();
  • client.hget(key, field);
  • return client.getBinaryBulkReply();
  • }
  • /**
  • * Set the specified hash field to the specified value if the field not exists. Time
  • * complexity: O(1)
  • * @param key
  • * @param field
  • * @param value
  • * @return If the field already exists, 0 is returned, otherwise if a new field is created 1 is
  • * returned.
  • */
  • @Override
  • public Long hsetnx(final byte[] key, final byte[] field, final byte[] value) {
  • checkIsInMultiOrPipeline();
  • client.hsetnx(key, field, value);
  • return client.getIntegerReply();
  • }
  • /**
  • * Set the respective fields to the respective values. HMSET replaces old values with new values.
  • *

  • * If key does not exist, a new key holding a hash is created.
  • *

  • * Time complexity: O(N) (with N being the number of fields)
  • * @param key
  • * @param hash
  • * @return Always OK because HMSET can't fail
  • */
  • @Override
  • public String hmset(final byte[] key, final Map hash) {
  • checkIsInMultiOrPipeline();
  • client.hmset(key, hash);
  • return client.getStatusCodeReply();
  • }
  • /**
  • * Retrieve the values associated to the specified fields.
  • *

  • * If some of the specified fields do not exist, nil values are returned. Non existing keys are
  • * considered like empty hashes.
  • *

  • * Time complexity: O(N) (with N being the number of fields)
  • * @param key
  • * @param fields
  • * @return Multi Bulk Reply specifically a list of all the values associated with the specified
  • * fields, in the same order of the request.
  • */
  • @Override
  • public List hmget(final byte[] key, final byte[]... fields) {
  • checkIsInMultiOrPipeline();
  • client.hmget(key, fields);
  • return client.getBinaryMultiBulkReply();
  • }
  • /**
  • * Increment the number stored at field in the hash at key by value. If key does not exist, a new
  • * key holding a hash is created. If field does not exist or holds a string, the value is set to 0
  • * before applying the operation. Since the value argument is signed you can use this command to
  • * perform both increments and decrements.
  • *

  • * The range of values supported by HINCRBY is limited to 64 bit signed integers.
  • *

  • * Time complexity: O(1)
  • * @param key
  • * @param field
  • * @param value
  • * @return Integer reply The new value at field after the increment operation.
  • */
  • @Override
  • public Long hincrBy(final byte[] key, final byte[] field, final long value) {
  • checkIsInMultiOrPipeline();
  • client.hincrBy(key, field, value);
  • return client.getIntegerReply();
  • }
  • /**
  • * Increment the number stored at field in the hash at key by a double precision floating point
  • * value. If key does not exist, a new key holding a hash is created. If field does not exist or
  • * holds a string, the value is set to 0 before applying the operation. Since the value argument
  • * is signed you can use this command to perform both increments and decrements.
  • *

  • * The range of values supported by HINCRBYFLOAT is limited to double precision floating point
  • * values.
  • *

  • * Time complexity: O(1)
  • * @param key
  • * @param field
  • * @param value
  • * @return Double precision floating point reply The new value at field after the increment
  • * operation.
  • */
  • @Override
  • public Double hincrByFloat(final byte[] key, final byte[] field, final double value) {
  • checkIsInMultiOrPipeline();
  • client.hincrByFloat(key, field, value);
  • final String dval = client.getBulkReply();
  • return (dval != null ? new Double(dval) : null);
  • }
  • /**
  • * Test for existence of a specified field in a hash. Time complexity: O(1)
  • * @param key
  • * @param field
  • * @return Return true if the hash stored at key contains the specified field. Return false if the key is
  • * not found or the field is not present.
  • */
  • @Override
  • public Boolean hexists(final byte[] key, final byte[] field) {
  • checkIsInMultiOrPipeline();
  • client.hexists(key, field);
  • return client.getIntegerReply() == 1;
  • }
  • /**
  • * Remove the specified field from an hash stored at key.
  • *

  • * Time complexity: O(1)
  • * @param key
  • * @param fields
  • * @return If the field was present in the hash it is deleted and 1 is returned, otherwise 0 is
  • * returned and no operation is performed.
  • */
  • @Override
  • public Long hdel(final byte[] key, final byte[]... fields) {
  • checkIsInMultiOrPipeline();
  • client.hdel(key, fields);
  • return client.getIntegerReply();
  • }
  • /**
  • * Return the number of items in a hash.
  • *

  • * Time complexity: O(1)
  • * @param key
  • * @return The number of entries (fields) contained in the hash stored at key. If the specified
  • * key does not exist, 0 is returned assuming an empty hash.
  • */
  • @Override
  • public Long hlen(final byte[] key) {
  • checkIsInMultiOrPipeline();
  • client.hlen(key);
  • return client.getIntegerReply();
  • }
  • /**
  • * Return all the fields in a hash.
  • *

  • * Time complexity: O(N), where N is the total number of entries
  • * @param key
  • * @return All the fields names contained into a hash.
  • */
  • @Override
  • public Set hkeys(final byte[] key) {
  • checkIsInMultiOrPipeline();
  • client.hkeys(key);
  • return SetFromList.of(client.getBinaryMultiBulkReply());
  • }
  • /**
  • * Return all the values in a hash.
  • *

  • * Time complexity: O(N), where N is the total number of entries
  • * @param key
  • * @return All the fields values contained into a hash.
  • */
  • @Override
  • public List hvals(final byte[] key) {
  • checkIsInMultiOrPipeline();
  • client.hvals(key);
  • return client.getBinaryMultiBulkReply();
  • }
  • /**
  • * Return all the fields and associated values in a hash.
  • *

  • * Time complexity: O(N), where N is the total number of entries
  • * @param key
  • * @return All the fields and values contained into a hash.
  • */
  • @Override
  • public Map hgetAll(final byte[] key) {
  • checkIsInMultiOrPipeline();
  • client.hgetAll(key);
  • final List flatHash = client.getBinaryMultiBulkReply();
  • final Map hash = new JedisByteHashMap();
  • final Iterator iterator = flatHash.iterator();
  • while (iterator.hasNext()) {
  • hash.put(iterator.next(), iterator.next());
  • }
  • return hash;
  • }
  • /**
  • * Add the string value to the head (LPUSH) or tail (RPUSH) of the list stored at key. If the key
  • * does not exist an empty list is created just before the append operation. If the key exists but
  • * is not a List an error is returned.
  • *

  • * Time complexity: O(1)
  • * @see BinaryJedis#rpush(byte[], byte[]...)
  • * @param key
  • * @param strings
  • * @return Integer reply, specifically, the number of elements inside the list after the push
  • * operation.
  • */
  • @Override
  • public Long rpush(final byte[] key, final byte[]... strings) {
  • checkIsInMultiOrPipeline();
  • client.rpush(key, strings);
  • return client.getIntegerReply();
  • }
  • /**
  • * Add the string value to the head (LPUSH) or tail (RPUSH) of the list stored at key. If the key
  • * does not exist an empty list is created just before the append operation. If the key exists but
  • * is not a List an error is returned.
  • *

  • * Time complexity: O(1)
  • * @see BinaryJedis#rpush(byte[], byte[]...)
  • * @param key
  • * @param strings
  • * @return Integer reply, specifically, the number of elements inside the list after the push
  • * operation.
  • */
  • @Override
  • public Long lpush(final byte[] key, final byte[]... strings) {
  • checkIsInMultiOrPipeline();
  • client.lpush(key, strings);
  • return client.getIntegerReply();
  • }
  • /**
  • * Return the length of the list stored at the specified key. If the key does not exist zero is
  • * returned (the same behaviour as for empty lists). If the value stored at key is not a list an
  • * error is returned.
  • *

  • * Time complexity: O(1)
  • * @param key
  • * @return The length of the list.
  • */
  • @Override
  • public Long llen(final byte[] key) {
  • checkIsInMultiOrPipeline();
  • client.llen(key);
  • return client.getIntegerReply();
  • }
  • /**
  • * Return the specified elements of the list stored at the specified key. Start and end are
  • * zero-based indexes. 0 is the first element of the list (the list head), 1 the next element and
  • * so on.
  • *

  • * For example LRANGE foobar 0 2 will return the first three elements of the list.
  • *

  • * start and end can also be negative numbers indicating offsets from the end of the list. For
  • * example -1 is the last element of the list, -2 the penultimate element and so on.
  • *

  • * Consistency with range functions in various programming languages
  • *

  • * Note that if you have a list of numbers from 0 to 100, LRANGE 0 10 will return 11 elements,
  • * that is, rightmost item is included. This may or may not be consistent with behavior of
  • * range-related functions in your programming language of choice (think Ruby's Range.new,
  • * Array#slice or Python's range() function).
  • *

  • * LRANGE behavior is consistent with one of Tcl.
  • *

  • * Out-of-range indexes
  • *

  • * Indexes out of range will not produce an error: if start is over the end of the list, or start
  • * > end, an empty list is returned. If end is over the end of the list Redis will threat it
  • * just like the last element of the list.
  • *

  • * Time complexity: O(start+n) (with n being the length of the range and start being the start
  • * offset)
  • * @param key
  • * @param start
  • * @param stop
  • * @return Multi bulk reply, specifically a list of elements in the specified range.
  • */
  • @Override
  • public List lrange(final byte[] key, final long start, final long stop) {
  • checkIsInMultiOrPipeline();
  • client.lrange(key, start, stop);
  • return client.getBinaryMultiBulkReply();
  • }
  • /**
  • * Trim an existing list so that it will contain only the specified range of elements specified.
  • * Start and end are zero-based indexes. 0 is the first element of the list (the list head), 1 the
  • * next element and so on.
  • *

  • * For example LTRIM foobar 0 2 will modify the list stored at foobar key so that only the first
  • * three elements of the list will remain.
  • *

  • * start and end can also be negative numbers indicating offsets from the end of the list. For
  • * example -1 is the last element of the list, -2 the penultimate element and so on.
  • *

  • * Indexes out of range will not produce an error: if start is over the end of the list, or start
  • * > end, an empty list is left as value. If end over the end of the list Redis will threat it
  • * just like the last element of the list.
  • *

  • * Hint: the obvious use of LTRIM is together with LPUSH/RPUSH. For example:
  • *

  • * {@code lpush("mylist", "someelement"); ltrim("mylist", 0, 99); * }
  • *

  • * The above two commands will push elements in the list taking care that the list will not grow
  • * without limits. This is very useful when using Redis to store logs for example. It is important
  • * to note that when used in this way LTRIM is an O(1) operation because in the average case just
  • * one element is removed from the tail of the list.
  • *

  • * Time complexity: O(n) (with n being len of list - len of range)
  • * @param key
  • * @param start
  • * @param stop
  • * @return Status code reply
  • */
  • @Override
  • public String ltrim(final byte[] key, final long start, final long stop) {
  • checkIsInMultiOrPipeline();
  • client.ltrim(key, start, stop);
  • return client.getStatusCodeReply();
  • }
  • /**
  • * Return the specified element of the list stored at the specified key. 0 is the first element, 1
  • * the second and so on. Negative indexes are supported, for example -1 is the last element, -2
  • * the penultimate and so on.
  • *

  • * If the value stored at key is not of list type an error is returned. If the index is out of
  • * range a 'nil' reply is returned.
  • *

  • * Note that even if the average time complexity is O(n) asking for the first or the last element
  • * of the list is O(1).
  • *

  • * Time complexity: O(n) (with n being the length of the list)
  • * @param key
  • * @param index
  • * @return Bulk reply, specifically the requested element
  • */
  • @Override
  • public byte[] lindex(final byte[] key, final long index) {
  • checkIsInMultiOrPipeline();
  • client.lindex(key, index);
  • return client.getBinaryBulkReply();
  • }
  • /**
  • * Set a new value as the element at index position of the List at key.
  • *

  • * Out of range indexes will generate an error.
  • *

  • * Similarly to other list commands accepting indexes, the index can be negative to access
  • * elements starting from the end of the list. So -1 is the last element, -2 is the penultimate,
  • * and so forth.
  • *

  • * Time complexity:
  • *

  • * O(N) (with N being the length of the list), setting the first or last elements of the list is
  • * O(1).
  • * @see #lindex(byte[], long)
  • * @param key
  • * @param index
  • * @param value
  • * @return Status code reply
  • */
  • @Override
  • public String lset(final byte[] key, final long index, final byte[] value) {
  • checkIsInMultiOrPipeline();
  • client.lset(key, index, value);
  • return client.getStatusCodeReply();
  • }
  • /**
  • * Remove the first count occurrences of the value element from the list. If count is zero all the
  • * elements are removed. If count is negative elements are removed from tail to head, instead to
  • * go from head to tail that is the normal behaviour. So for example LREM with count -2 and hello
  • * as value to remove against the list (a,b,c,hello,x,hello,hello) will leave the list
  • * (a,b,c,hello,x). The number of removed elements is returned as an integer, see below for more
  • * information about the returned value. Note that non existing keys are considered like empty
  • * lists by LREM, so LREM against non existing keys will always return 0.
  • *

  • * Time complexity: O(N) (with N being the length of the list)
  • * @param key
  • * @param count
  • * @param value
  • * @return Integer Reply, specifically: The number of removed elements if the operation succeeded
  • */
  • @Override
  • public Long lrem(final byte[] key, final long count, final byte[] value) {
  • checkIsInMultiOrPipeline();
  • client.lrem(key, count, value);
  • return client.getIntegerReply();
  • }
  • /**
  • * Atomically return and remove the first (LPOP) or last (RPOP) element of the list. For example
  • * if the list contains the elements "a","b","c" LPOP will return "a" and the list will become
  • * "b","c".
  • *

  • * If the key does not exist or the list is already empty the special value 'nil' is returned.
  • * @see #rpop(byte[])
  • * @param key
  • * @return Bulk reply
  • */
  • @Override
  • public byte[] lpop(final byte[] key) {
  • checkIsInMultiOrPipeline();
  • client.lpop(key);
  • return client.getBinaryBulkReply();
  • }
  • /**
  • * Atomically return and remove the first (LPOP) or last (RPOP) element of the list. For example
  • * if the list contains the elements "a","b","c" LPOP will return "a" and the list will become
  • * "b","c".
  • *

  • * If the key does not exist or the list is already empty the special value 'nil' is returned.
  • * @see #lpop(byte[])
  • * @param key
  • * @return Bulk reply
  • */
  • @Override
  • public byte[] rpop(final byte[] key) {
  • checkIsInMultiOrPipeline();
  • client.rpop(key);
  • return client.getBinaryBulkReply();
  • }
  • /**
  • * Atomically return and remove the last (tail) element of the srckey list, and push the element
  • * as the first (head) element of the dstkey list. For example if the source list contains the
  • * elements "a","b","c" and the destination list contains the elements "foo","bar" after an
  • * RPOPLPUSH command the content of the two lists will be "a","b" and "c","foo","bar".
  • *

  • * If the key does not exist or the list is already empty the special value 'nil' is returned. If
  • * the srckey and dstkey are the same the operation is equivalent to removing the last element
  • * from the list and pushing it as first element of the list, so it's a "list rotation" command.
  • *

  • * Time complexity: O(1)
  • * @param srckey
  • * @param dstkey
  • * @return Bulk reply
  • */
  • @Override
  • public byte[] rpoplpush(final byte[] srckey, final byte[] dstkey) {
  • checkIsInMultiOrPipeline();
  • client.rpoplpush(srckey, dstkey);
  • return client.getBinaryBulkReply();
  • }
  • /**
  • * Add the specified member to the set value stored at key. If member is already a member of the
  • * set no operation is performed. If key does not exist a new set with the specified member as
  • * sole member is created. If the key exists but does not hold a set value an error is returned.
  • *

  • * Time complexity O(1)
  • * @param key
  • * @param members
  • * @return Integer reply, specifically: 1 if the new element was added 0 if the element was
  • * already a member of the set
  • */
  • @Override
  • public Long sadd(final byte[] key, final byte[]... members) {
  • checkIsInMultiOrPipeline();
  • client.sadd(key, members);
  • return client.getIntegerReply();
  • }
  • /**
  • * Return all the members (elements) of the set value stored at key. This is just syntax glue for
  • * {@link #sinter(byte[]...)} SINTER}.
  • *

  • * Time complexity O(N)
  • * @param key the key of the set
  • * @return Multi bulk reply
  • */
  • @Override
  • public Set smembers(final byte[] key) {
  • checkIsInMultiOrPipeline();
  • client.smembers(key);
  • return SetFromList.of(client.getBinaryMultiBulkReply());
  • }
  • /**
  • * Remove the specified member from the set value stored at key. If member was not a member of the
  • * set no operation is performed. If key does not hold a set value an error is returned.
  • *

  • * Time complexity O(1)
  • * @param key the key of the set
  • * @param member the set member to remove
  • * @return Integer reply, specifically: 1 if the new element was removed 0 if the new element was
  • * not a member of the set
  • */
  • @Override
  • public Long srem(final byte[] key, final byte[]... member) {
  • checkIsInMultiOrPipeline();
  • client.srem(key, member);
  • return client.getIntegerReply();
  • }
  • /**
  • * Remove a random element from a Set returning it as return value. If the Set is empty or the key
  • * does not exist, a nil object is returned.
  • *

  • * The {@link #srandmember(byte[])} command does a similar work but the returned element is not
  • * removed from the Set.
  • *

  • * Time complexity O(1)
  • * @param key
  • * @return Bulk reply
  • */
  • @Override
  • public byte[] spop(final byte[] key) {
  • checkIsInMultiOrPipeline();
  • client.spop(key);
  • return client.getBinaryBulkReply();
  • }
  • @Override
  • public Set spop(final byte[] key, final long count) {
  • checkIsInMultiOrPipeline();
  • client.spop(key, count);
  • List members = client.getBinaryMultiBulkReply();
  • if (members == null) return null;
  • return SetFromList.of(members);
  • }
  • /**
  • * Move the specified member from the set at srckey to the set at dstkey. This operation is
  • * atomic, in every given moment the element will appear to be in the source or destination set
  • * for accessing clients.
  • *

  • * If the source set does not exist or does not contain the specified element no operation is
  • * performed and zero is returned, otherwise the element is removed from the source set and added
  • * to the destination set. On success one is returned, even if the element was already present in
  • * the destination set.
  • *

  • * An error is raised if the source or destination keys contain a non Set value.
  • *

  • * Time complexity O(1)
  • * @param srckey
  • * @param dstkey
  • * @param member
  • * @return Integer reply, specifically: 1 if the element was moved 0 if the element was not found
  • * on the first set and no operation was performed
  • */
  • @Override
  • public Long smove(final byte[] srckey, final byte[] dstkey, final byte[] member) {
  • checkIsInMultiOrPipeline();
  • client.smove(srckey, dstkey, member);
  • return client.getIntegerReply();
  • }
  • /**
  • * Return the set cardinality (number of elements). If the key does not exist 0 is returned, like
  • * for empty sets.
  • * @param key
  • * @return Integer reply, specifically: the cardinality (number of elements) of the set as an
  • * integer.
  • */
  • @Override
  • public Long scard(final byte[] key) {
  • checkIsInMultiOrPipeline();
  • client.scard(key);
  • return client.getIntegerReply();
  • }
  • /**
  • * Return true if member is a member of the set stored at key, otherwise false is returned.
  • *

  • * Time complexity O(1)
  • * @param key
  • * @param member
  • * @return Boolean reply, specifically: true if the element is a member of the set false if the element
  • * is not a member of the set OR if the key does not exist
  • */
  • @Override
  • public Boolean sismember(final byte[] key, final byte[] member) {
  • checkIsInMultiOrPipeline();
  • client.sismember(key, member);
  • return client.getIntegerReply() == 1;
  • }
  • /**
  • * Return the members of a set resulting from the intersection of all the sets hold at the
  • * specified keys. Like in {@link #lrange(byte[], long, long)} LRANGE} the result is sent to the
  • * client as a multi-bulk reply (see the protocol specification for more information). If just a
  • * single key is specified, then this command produces the same result as
  • * {@link #smembers(byte[]) SMEMBERS}. Actually SMEMBERS is just syntax sugar for SINTER.
  • *

  • * Non existing keys are considered like empty sets, so if one of the keys is missing an empty set
  • * is returned (since the intersection with an empty set always is an empty set).
  • *

  • * Time complexity O(N*M) worst case where N is the cardinality of the smallest set and M the
  • * number of sets
  • * @param keys
  • * @return Multi bulk reply, specifically the list of common elements.
  • */
  • @Override
  • public Set sinter(final byte[]... keys) {
  • checkIsInMultiOrPipeline();
  • client.sinter(keys);
  • return SetFromList.of(client.getBinaryMultiBulkReply());
  • }
  • /**
  • * This commanad works exactly like {@link #sinter(byte[]...) SINTER} but instead of being returned
  • * the resulting set is stored as dstkey.
  • *

  • * Time complexity O(N*M) worst case where N is the cardinality of the smallest set and M the
  • * number of sets
  • * @param dstkey
  • * @param keys
  • * @return Status code reply
  • */
  • @Override
  • public Long sinterstore(final byte[] dstkey, final byte[]... keys) {
  • checkIsInMultiOrPipeline();
  • client.sinterstore(dstkey, keys);
  • return client.getIntegerReply();
  • }
  • /**
  • * Return the members of a set resulting from the union of all the sets hold at the specified
  • * keys. Like in {@link #lrange(byte[], long, long)} LRANGE} the result is sent to the client as a
  • * multi-bulk reply (see the protocol specification for more information). If just a single key is
  • * specified, then this command produces the same result as {@link #smembers(byte[]) SMEMBERS}.
  • *

  • * Non existing keys are considered like empty sets.
  • *

  • * Time complexity O(N) where N is the total number of elements in all the provided sets
  • * @param keys
  • * @return Multi bulk reply, specifically the list of common elements.
  • */
  • @Override
  • public Set sunion(final byte[]... keys) {
  • checkIsInMultiOrPipeline();
  • client.sunion(keys);
  • return SetFromList.of(client.getBinaryMultiBulkReply());
  • }
  • /**
  • * This command works exactly like {@link #sunion(byte[]...) SUNION} but instead of being returned
  • * the resulting set is stored as dstkey. Any existing value in dstkey will be over-written.
  • *

  • * Time complexity O(N) where N is the total number of elements in all the provided sets
  • * @param dstkey
  • * @param keys
  • * @return Status code reply
  • */
  • @Override
  • public Long sunionstore(final byte[] dstkey, final byte[]... keys) {
  • checkIsInMultiOrPipeline();
  • client.sunionstore(dstkey, keys);
  • return client.getIntegerReply();
  • }
  • /**
  • * Return the difference between the Set stored at key1 and all the Sets key2, ..., keyN
  • *

  • * Example:
  • *
  • *
  • * key1 = [x, a, b, c]
  • * key2 = [c]
  • * key3 = [a, d]
  • * SDIFF key1,key2,key3 => [x, b]
  • *
  • *
  • * Non existing keys are considered like empty sets.
  • *

  • * Time complexity:
  • *

  • * O(N) with N being the total number of elements of all the sets
  • * @param keys
  • * @return Return the members of a set resulting from the difference between the first set
  • * provided and all the successive sets.
  • */
  • @Override
  • public Set sdiff(final byte[]... keys) {
  • checkIsInMultiOrPipeline();
  • client.sdiff(keys);
  • return SetFromList.of(client.getBinaryMultiBulkReply());
  • }
  • /**
  • * This command works exactly like {@link #sdiff(byte[]...) SDIFF} but instead of being returned
  • * the resulting set is stored in dstkey.
  • * @param dstkey
  • * @param keys
  • * @return Status code reply
  • */
  • @Override
  • public Long sdiffstore(final byte[] dstkey, final byte[]... keys) {
  • checkIsInMultiOrPipeline();
  • client.sdiffstore(dstkey, keys);
  • return client.getIntegerReply();
  • }
  • /**
  • * Return a random element from a Set, without removing the element. If the Set is empty or the
  • * key does not exist, a nil object is returned.
  • *

  • * The SPOP command does a similar work but the returned element is popped (removed) from the Set.
  • *

  • * Time complexity O(1)
  • * @param key
  • * @return Bulk reply
  • */
  • @Override
  • public byte[] srandmember(final byte[] key) {
  • checkIsInMultiOrPipeline();
  • client.srandmember(key);
  • return client.getBinaryBulkReply();
  • }
  • @Override
  • public List srandmember(final byte[] key, final int count) {
  • checkIsInMultiOrPipeline();
  • client.srandmember(key, count);
  • return client.getBinaryMultiBulkReply();
  • }
  • /**
  • * Add the specified member having the specified score to the sorted set stored at key. If member
  • * is already a member of the sorted set the score is updated, and the element reinserted in the
  • * right position to ensure sorting. If key does not exist a new sorted set with the specified
  • * member as sole member is created. If the key exists but does not hold a sorted set value an
  • * error is returned.
  • *

  • * The score value can be the string representation of a double precision floating point number.
  • *

  • * Time complexity O(log(N)) with N being the number of elements in the sorted set
  • * @param key
  • * @param score
  • * @param member
  • * @return Integer reply, specifically: 1 if the new element was added 0 if the element was
  • * already a member of the sorted set and the score was updated
  • */
  • @Override
  • public Long zadd(final byte[] key, final double score, final byte[] member) {
  • checkIsInMultiOrPipeline();
  • client.zadd(key, score, member);
  • return client.getIntegerReply();
  • }
  • @Override
  • public Long zadd(final byte[] key, final double score, final byte[] member, final ZAddParams params) {
  • checkIsInMultiOrPipeline();
  • client.zadd(key, score, member, params);
  • return client.getIntegerReply();
  • }
  • @Override
  • public Long zadd(final byte[] key, final Map scoreMembers) {
  • checkIsInMultiOrPipeline();
  • client.zadd(key, scoreMembers);
  • return client.getIntegerReply();
  • }
  • @Override
  • public Long zadd(final byte[] key, final Map scoreMembers, final ZAddParams params) {
  • checkIsInMultiOrPipeline();
  • client.zadd(key, scoreMembers, params);
  • return client.getIntegerReply();
  • }
  • @Override
  • public Set zrange(final byte[] key, final long start, final long stop) {
  • checkIsInMultiOrPipeline();
  • client.zrange(key, start, stop);
  • return SetFromList.of(client.getBinaryMultiBulkReply());
  • }
  • /**
  • * Remove the specified member from the sorted set value stored at key. If member was not a member
  • * of the set no operation is performed. If key does not not hold a set value an error is
  • * returned.
  • *

  • * Time complexity O(log(N)) with N being the number of elements in the sorted set
  • * @param key
  • * @param members
  • * @return Integer reply, specifically: 1 if the new element was removed 0 if the new element was
  • * not a member of the set
  • */
  • @Override
  • public Long zrem(final byte[] key, final byte[]... members) {
  • checkIsInMultiOrPipeline();
  • client.zrem(key, members);
  • return client.getIntegerReply();
  • }
  • /**
  • * If member already exists in the sorted set adds the increment to its score and updates the
  • * position of the element in the sorted set accordingly. If member does not already exist in the
  • * sorted set it is added with increment as score (that is, like if the previous score was
  • * virtually zero). If key does not exist a new sorted set with the specified member as sole
  • * member is created. If the key exists but does not hold a sorted set value an error is returned.
  • *

  • * The score value can be the string representation of a double precision floating point number.
  • * It's possible to provide a negative value to perform a decrement.
  • *

  • * For an introduction to sorted sets check the Introduction to Redis data types page.
  • *

  • * Time complexity O(log(N)) with N being the number of elements in the sorted set
  • * @param key
  • * @param increment
  • * @param member
  • * @return The new score
  • */
  • @Override
  • public Double zincrby(final byte[] key, final double increment, final byte[] member) {
  • checkIsInMultiOrPipeline();
  • client.zincrby(key, increment, member);
  • return BuilderFactory.DOUBLE.build(client.getOne());
  • }
  • @Override
  • public Double zincrby(final byte[] key, final double increment, final byte[] member, final ZIncrByParams params) {
  • checkIsInMultiOrPipeline();
  • client.zincrby(key, increment, member, params);
  • return BuilderFactory.DOUBLE.build(client.getOne());
  • }
  • /**
  • * Return the rank (or index) or member in the sorted set at key, with scores being ordered from
  • * low to high.
  • *

  • * When the given member does not exist in the sorted set, the special value 'nil' is returned.
  • * The returned rank (or index) of the member is 0-based for both commands.
  • *

  • * Time complexity:
  • *

  • * O(log(N))
  • * @see #zrevrank(byte[], byte[])
  • * @param key
  • * @param member
  • * @return Integer reply or a nil bulk reply, specifically: the rank of the element as an integer
  • * reply if the element exists. A nil bulk reply if there is no such element.
  • */
  • @Override
  • public Long zrank(final byte[] key, final byte[] member) {
  • checkIsInMultiOrPipeline();
  • client.zrank(key, member);
  • return client.getIntegerReply();
  • }
  • /**
  • * Return the rank (or index) or member in the sorted set at key, with scores being ordered from
  • * high to low.
  • *

  • * When the given member does not exist in the sorted set, the special value 'nil' is returned.
  • * The returned rank (or index) of the member is 0-based for both commands.
  • *

  • * Time complexity:
  • *

  • * O(log(N))
  • * @see #zrank(byte[], byte[])
  • * @param key
  • * @param member
  • * @return Integer reply or a nil bulk reply, specifically: the rank of the element as an integer
  • * reply if the element exists. A nil bulk reply if there is no such element.
  • */
  • @Override
  • public Long zrevrank(final byte[] key, final byte[] member) {
  • checkIsInMultiOrPipeline();
  • client.zrevrank(key, member);
  • return client.getIntegerReply();
  • }
  • @Override
  • public Set zrevrange(final byte[] key, final long start, final long stop) {
  • checkIsInMultiOrPipeline();
  • client.zrevrange(key, start, stop);
  • return SetFromList.of(client.getBinaryMultiBulkReply());
  • }
  • @Override
  • public Set<Tuple> zrangeWithScores(final byte[] key, final long start, final long stop) {
  • checkIsInMultiOrPipeline();
  • client.zrangeWithScores(key, start, stop);
  • return getTupledSet();
  • }
  • @Override
  • public Set<Tuple> zrevrangeWithScores(final byte[] key, final long start, final long stop) {
  • checkIsInMultiOrPipeline();
  • client.zrevrangeWithScores(key, start, stop);
  • return getTupledSet();
  • }
  • /**
  • * Return the sorted set cardinality (number of elements). If the key does not exist 0 is
  • * returned, like for empty sorted sets.
  • *

  • * Time complexity O(1)
  • * @param key
  • * @return the cardinality (number of elements) of the set as an integer.
  • */
  • @Override
  • public Long zcard(final byte[] key) {
  • checkIsInMultiOrPipeline();
  • client.zcard(key);
  • return client.getIntegerReply();
  • }
  • /**
  • * Return the score of the specified element of the sorted set at key. If the specified element
  • * does not exist in the sorted set, or the key does not exist at all, a special 'nil' value is
  • * returned.
  • *

  • * Time complexity: O(1)
  • * @param key
  • * @param member
  • * @return the score
  • */
  • @Override
  • public Double zscore(final byte[] key, final byte[] member) {
  • checkIsInMultiOrPipeline();
  • client.zscore(key, member);
  • final String score = client.getBulkReply();
  • return (score != null ? new Double(score) : null);
  • }
  • @Override
  • public Tuple zpopmax(final byte[] key) {
  • checkIsInMultiOrPipeline();
  • client.zpopmax(key);
  • return BuilderFactory.TUPLE.build(client.getBinaryMultiBulkReply());
  • }
  • @Override
  • public Set<Tuple> zpopmax(final byte[] key, final int count) {
  • checkIsInMultiOrPipeline();
  • client.zpopmax(key, count);
  • return getTupledSet();
  • }
  • @Override
  • public Tuple zpopmin(final byte[] key) {
  • checkIsInMultiOrPipeline();
  • client.zpopmin(key);
  • return BuilderFactory.TUPLE.build(client.getBinaryMultiBulkReply());
  • }
  • @Override
  • public Set<Tuple> zpopmin(final byte[] key, final int count) {
  • checkIsInMultiOrPipeline();
  • client.zpopmin(key, count);
  • return getTupledSet();
  • }
  • public Transaction multi() {
  • client.multi();
  • client.getOne(); // expected OK
  • transaction = new Transaction(client);
  • return transaction;
  • }
  • protected void checkIsInMultiOrPipeline() {
  • if (client.isInMulti()) {
  • throw new JedisDataException(
  • "Cannot use Jedis when in Multi. Please use Transaction or reset jedis state.");
  • } else if (pipeline != null && pipeline.hasPipelinedResponse()) {
  • throw new JedisDataException(
  • "Cannot use Jedis when in Pipeline. Please use Pipeline or reset jedis state .");
  • }
  • }
  • public void connect() {
  • client.connect();
  • }
  • public void disconnect() {
  • client.disconnect();
  • }
  • public void resetState() {
  • if (client.isConnected()) {
  • if (transaction != null) {
  • transaction.close();
  • }
  • if (pipeline != null) {
  • pipeline.close();
  • }
  • client.resetState();
  • }
  • transaction = null;
  • pipeline = null;
  • }
  • @Override
  • public String watch(final byte[]... keys) {
  • checkIsInMultiOrPipeline();
  • client.watch(keys);
  • return client.getStatusCodeReply();
  • }
  • @Override
  • public String unwatch() {
  • checkIsInMultiOrPipeline();
  • client.unwatch();
  • return client.getStatusCodeReply();
  • }
  • @Override
  • public void close() {
  • client.close();
  • }
  • /**
  • * Sort a Set or a List.
  • *

  • * Sort the elements contained in the List, Set, or Sorted Set value at key. By default sorting is
  • * numeric with elements being compared as double precision floating point numbers. This is the
  • * simplest form of SORT.
  • * @see #sort(byte[], byte[])
  • * @see #sort(byte[], SortingParams)
  • * @see #sort(byte[], SortingParams, byte[])
  • * @param key
  • * @return Assuming the Set/List at key contains a list of numbers, the return value will be the
  • * list of numbers ordered from the smallest to the biggest number.
  • */
  • @Override
  • public List sort(final byte[] key) {
  • checkIsInMultiOrPipeline();
  • client.sort(key);
  • return client.getBinaryMultiBulkReply();
  • }
  • /**
  • * Sort a Set or a List accordingly to the specified parameters.
  • *

  • * examples:
  • *

  • * Given are the following sets and key/values:
  • *
  • *
  • * x = [1, 2, 3]
  • * y = [a, b, c]
  • *
  • * k1 = z
  • * k2 = y
  • * k3 = x
  • *
  • * w1 = 9
  • * w2 = 8
  • * w3 = 7
  • *
  • *
  • * Sort Order:
  • *
  • *
  • * sort(x) or sort(x, sp.asc())
  • * -> [1, 2, 3]
  • *
  • * sort(x, sp.desc())
  • * -> [3, 2, 1]
  • *
  • * sort(y)
  • * -> [c, a, b]
  • *
  • * sort(y, sp.alpha())
  • * -> [a, b, c]
  • *
  • * sort(y, sp.alpha().desc())
  • * -> [c, a, b]
  • *
  • *
  • * Limit (e.g. for Pagination):
  • *
  • *
  • * sort(x, sp.limit(0, 2))
  • * -> [1, 2]
  • *
  • * sort(y, sp.alpha().desc().limit(1, 2))
  • * -> [b, a]
  • *
  • *
  • * Sorting by external keys:
  • *
  • *
  • * sort(x, sb.by(w*))
  • * -> [3, 2, 1]
  • *
  • * sort(x, sb.by(w*).desc())
  • * -> [1, 2, 3]
  • *
  • *
  • * Getting external keys:
  • *
  • *
  • * sort(x, sp.by(w*).get(k*))
  • * -> [x, y, z]
  • *
  • * sort(x, sp.by(w*).get(#).get(k*))
  • * -> [3, x, 2, y, 1, z]
  • *
  • * @see #sort(byte[])
  • * @see #sort(byte[], SortingParams, byte[])
  • * @param key
  • * @param sortingParameters
  • * @return a list of sorted elements.
  • */
  • @Override
  • public List sort(final byte[] key, final SortingParams sortingParameters) {
  • checkIsInMultiOrPipeline();
  • client.sort(key, sortingParameters);
  • return client.getBinaryMultiBulkReply();
  • }
  • /**
  • * BLPOP (and BRPOP) is a blocking list pop primitive. You can see this commands as blocking
  • * versions of LPOP and RPOP able to block if the specified keys don't exist or contain empty
  • * lists.
  • *

  • * The following is a description of the exact semantic. We describe BLPOP but the two commands
  • * are identical, the only difference is that BLPOP pops the element from the left (head) of the
  • * list, and BRPOP pops from the right (tail).
  • *

  • * Non blocking behavior
  • *

  • * When BLPOP is called, if at least one of the specified keys contain a non empty list, an
  • * element is popped from the head of the list and returned to the caller together with the name
  • * of the key (BLPOP returns a two elements array, the first element is the key, the second the
  • * popped value).
  • *

  • * Keys are scanned from left to right, so for instance if you issue BLPOP list1 list2 list3 0
  • * against a dataset where list1 does not exist but list2 and list3 contain non empty lists, BLPOP
  • * guarantees to return an element from the list stored at list2 (since it is the first non empty
  • * list starting from the left).
  • *

  • * Blocking behavior
  • *

  • * If none of the specified keys exist or contain non empty lists, BLPOP blocks until some other
  • * client performs a LPUSH or an RPUSH operation against one of the lists.
  • *

  • * Once new data is present on one of the lists, the client finally returns with the name of the
  • * key unblocking it and the popped value.
  • *

  • * When blocking, if a non-zero timeout is specified, the client will unblock returning a nil
  • * special value if the specified amount of seconds passed without a push operation against at
  • * least one of the specified keys.
  • *

  • * The timeout argument is interpreted as an integer value. A timeout of zero means instead to
  • * block forever.
  • *

  • * Multiple clients blocking for the same keys
  • *

  • * Multiple clients can block for the same key. They are put into a queue, so the first to be
  • * served will be the one that started to wait earlier, in a first-blpopping first-served fashion.
  • *

  • * blocking POP inside a MULTI/EXEC transaction
  • *

  • * BLPOP and BRPOP can be used with pipelining (sending multiple commands and reading the replies
  • * in batch), but it does not make sense to use BLPOP or BRPOP inside a MULTI/EXEC block (a Redis
  • * transaction).
  • *

  • * The behavior of BLPOP inside MULTI/EXEC when the list is empty is to return a multi-bulk nil
  • * reply, exactly what happens when the timeout is reached. If you like science fiction, think at
  • * it like if inside MULTI/EXEC the time will flow at infinite speed :)
  • *

  • * Time complexity: O(1)
  • * @see #brpop(int, byte[]...)
  • * @param timeout
  • * @param keys
  • * @return BLPOP returns a two-elements array via a multi bulk reply in order to return both the
  • * unblocking key and the popped value.
  • *

  • * When a non-zero timeout is specified, and the BLPOP operation timed out, the return
  • * value is a nil multi bulk reply. Most client values will return false or nil
  • * accordingly to the programming language used.
  • */
  • @Override
  • public List blpop(final int timeout, final byte[]... keys) {
  • return blpop(getArgsAddTimeout(timeout, keys));
  • }
  • private byte[][] getArgsAddTimeout(int timeout, byte[][] keys) {
  • int size = keys.length;
  • final byte[][] args = new byte[size + 1][];
  • for (int at = 0; at != size; ++at) {
  • args[at] = keys[at];
  • }
  • args[size] = Protocol.toByteArray(timeout);
  • return args;
  • }
  • /**
  • * Sort a Set or a List accordingly to the specified parameters and store the result at dstkey.
  • * @see #sort(byte[], SortingParams)
  • * @see #sort(byte[])
  • * @see #sort(byte[], byte[])
  • * @param key
  • * @param sortingParameters
  • * @param dstkey
  • * @return The number of elements of the list at dstkey.
  • */
  • @Override
  • public Long sort(final byte[] key, final SortingParams sortingParameters, final byte[] dstkey) {
  • checkIsInMultiOrPipeline();
  • client.sort(key, sortingParameters, dstkey);
  • return client.getIntegerReply();
  • }
  • /**
  • * Sort a Set or a List and Store the Result at dstkey.
  • *

  • * Sort the elements contained in the List, Set, or Sorted Set value at key and store the result
  • * at dstkey. By default sorting is numeric with elements being compared as double precision
  • * floating point numbers. This is the simplest form of SORT.
  • * @see #sort(byte[])
  • * @see #sort(byte[], SortingParams)
  • * @see #sort(byte[], SortingParams, byte[])
  • * @param key
  • * @param dstkey
  • * @return The number of elements of the list at dstkey.
  • */
  • @Override
  • public Long sort(final byte[] key, final byte[] dstkey) {
  • checkIsInMultiOrPipeline();
  • client.sort(key, dstkey);
  • return client.getIntegerReply();
  • }
  • /**
  • * BLPOP (and BRPOP) is a blocking list pop primitive. You can see this commands as blocking
  • * versions of LPOP and RPOP able to block if the specified keys don't exist or contain empty
  • * lists.
  • *

  • * The following is a description of the exact semantic. We describe BLPOP but the two commands
  • * are identical, the only difference is that BLPOP pops the element from the left (head) of the
  • * list, and BRPOP pops from the right (tail).
  • *

  • * Non blocking behavior
  • *

  • * When BLPOP is called, if at least one of the specified keys contain a non empty list, an
  • * element is popped from the head of the list and returned to the caller together with the name
  • * of the key (BLPOP returns a two elements array, the first element is the key, the second the
  • * popped value).
  • *

  • * Keys are scanned from left to right, so for instance if you issue BLPOP list1 list2 list3 0
  • * against a dataset where list1 does not exist but list2 and list3 contain non empty lists, BLPOP
  • * guarantees to return an element from the list stored at list2 (since it is the first non empty
  • * list starting from the left).
  • *

  • * Blocking behavior
  • *

  • * If none of the specified keys exist or contain non empty lists, BLPOP blocks until some other
  • * client performs a LPUSH or an RPUSH operation against one of the lists.
  • *

  • * Once new data is present on one of the lists, the client finally returns with the name of the
  • * key unblocking it and the popped value.
  • *

  • * When blocking, if a non-zero timeout is specified, the client will unblock returning a nil
  • * special value if the specified amount of seconds passed without a push operation against at
  • * least one of the specified keys.
  • *

  • * The timeout argument is interpreted as an integer value. A timeout of zero means instead to
  • * block forever.
  • *

  • * Multiple clients blocking for the same keys
  • *

  • * Multiple clients can block for the same key. They are put into a queue, so the first to be
  • * served will be the one that started to wait earlier, in a first-blpopping first-served fashion.
  • *

  • * blocking POP inside a MULTI/EXEC transaction
  • *

  • * BLPOP and BRPOP can be used with pipelining (sending multiple commands and reading the replies
  • * in batch), but it does not make sense to use BLPOP or BRPOP inside a MULTI/EXEC block (a Redis
  • * transaction).
  • *

  • * The behavior of BLPOP inside MULTI/EXEC when the list is empty is to return a multi-bulk nil
  • * reply, exactly what happens when the timeout is reached. If you like science fiction, think at
  • * it like if inside MULTI/EXEC the time will flow at infinite speed :)
  • *

  • * Time complexity: O(1)
  • * @see #blpop(int, byte[]...)
  • * @param timeout
  • * @param keys
  • * @return BLPOP returns a two-elements array via a multi bulk reply in order to return both the
  • * unblocking key and the popped value.
  • *

  • * When a non-zero timeout is specified, and the BLPOP operation timed out, the return
  • * value is a nil multi bulk reply. Most client values will return false or nil
  • * accordingly to the programming language used.
  • */
  • @Override
  • public List brpop(final int timeout, final byte[]... keys) {
  • return brpop(getArgsAddTimeout(timeout, keys));
  • }
  • @Override
  • public List blpop(final byte[]... args) {
  • checkIsInMultiOrPipeline();
  • client.blpop(args);
  • client.setTimeoutInfinite();
  • try {
  • return client.getBinaryMultiBulkReply();
  • } finally {
  • client.rollbackTimeout();
  • }
  • }
  • @Override
  • public List brpop(final byte[]... args) {
  • checkIsInMultiOrPipeline();
  • client.brpop(args);
  • client.setTimeoutInfinite();
  • try {
  • return client.getBinaryMultiBulkReply();
  • } finally {
  • client.rollbackTimeout();
  • }
  • }
  • /**
  • * Request for authentication in a password protected Redis server. A Redis server can be
  • * instructed to require a password before to allow clients to issue commands. This is done using
  • * the requirepass directive in the Redis configuration file. If the password given by the client
  • * is correct the server replies with an OK status code reply and starts accepting commands from
  • * the client. Otherwise an error is returned and the clients needs to try a new password. Note
  • * that for the high performance nature of Redis it is possible to try a lot of passwords in
  • * parallel in very short time, so make sure to generate a strong and very long password so that
  • * this attack is infeasible.
  • * @param password
  • * @return Status code reply
  • */
  • @Override
  • public String auth(final String password) {
  • checkIsInMultiOrPipeline();
  • if(StringUtils.isBlank(this.user)){
  • client.auth(password);
  • }else{
  • client.auth(user,password);
  • }
  • return client.getStatusCodeReply();
  • }
  • /**
  • * Request for authentication with a Redis Server that is using ACL where user are authenticated with
  • * username and password.
  • * See https://redis.io/topics/acl
  • * @param user
  • * @param password
  • * @return
  • */
  • @Override
  • public String auth(final String user, final String password) {
  • checkIsInMultiOrPipeline();
  • client.auth(user, password);
  • return client.getStatusCodeReply();
  • }
  • public Pipeline pipelined() {
  • pipeline = new Pipeline();
  • pipeline.setClient(client);
  • return pipeline;
  • }
  • @Override
  • public Long zcount(final byte[] key, final double min, final double max) {
  • checkIsInMultiOrPipeline();
  • client.zcount(key, min, max);
  • return client.getIntegerReply();
  • }
  • @Override
  • public Long zcount(final byte[] key, final byte[] min, final byte[] max) {
  • checkIsInMultiOrPipeline();
  • client.zcount(key, min, max);
  • return client.getIntegerReply();
  • }
  • /**
  • * Return the all the elements in the sorted set at key with a score between min and max
  • * (including elements with score equal to min or max).
  • *

  • * The elements having the same score are returned sorted lexicographically as ASCII strings (this
  • * follows from a property of Redis sorted sets and does not involve further computation).
  • *

  • * Using the optional {@link #zrangeByScore(byte[], double, double, int, int) LIMIT} it's possible
  • * to get only a range of the matching elements in an SQL-alike way. Note that if offset is large
  • * the commands needs to traverse the list for offset elements and this adds up to the O(M)
  • * figure.
  • *

  • * The {@link #zcount(byte[], double, double) ZCOUNT} command is similar to
  • * {@link #zrangeByScore(byte[], double, double) ZRANGEBYSCORE} but instead of returning the
  • * actual elements in the specified interval, it just returns the number of matching elements.
  • *

  • * Exclusive intervals and infinity
  • *

  • * min and max can be -inf and +inf, so that you are not required to know what's the greatest or
  • * smallest element in order to take, for instance, elements "up to a given value".
  • *

  • * Also while the interval is for default closed (inclusive) it's possible to specify open
  • * intervals prefixing the score with a "(" character, so for instance:
  • *

  • * {@code ZRANGEBYSCORE zset (1.3 5}
  • *

  • * Will return all the values with score > 1.3 and <= 5, while for instance:
  • *

  • * {@code ZRANGEBYSCORE zset (5 (10}
  • *

  • * Will return all the values with score > 5 and < 10 (5 and 10 excluded).
  • *

  • * Time complexity:
  • *

  • * O(log(N))+O(M) with N being the number of elements in the sorted set and M the number of
  • * elements returned by the command, so if M is constant (for instance you always ask for the
  • * first ten elements with LIMIT) you can consider it O(log(N))
  • * @see #zrangeByScore(byte[], double, double)
  • * @see #zrangeByScore(byte[], double, double, int, int)
  • * @see #zrangeByScoreWithScores(byte[], double, double)
  • * @see #zrangeByScoreWithScores(byte[], double, double, int, int)
  • * @see #zcount(byte[], double, double)
  • * @param key
  • * @param min
  • * @param max
  • * @return Multi bulk reply specifically a list of elements in the specified score range.
  • */
  • @Override
  • public Set zrangeByScore(final byte[] key, final double min, final double max) {
  • checkIsInMultiOrPipeline();
  • client.zrangeByScore(key, min, max);
  • return SetFromList.of(client.getBinaryMultiBulkReply());
  • }
  • @Override
  • public Set zrangeByScore(final byte[] key, final byte[] min, final byte[] max) {
  • checkIsInMultiOrPipeline();
  • client.zrangeByScore(key, min, max);
  • return SetFromList.of(client.getBinaryMultiBulkReply());
  • }
  • /**
  • * Return the all the elements in the sorted set at key with a score between min and max
  • * (including elements with score equal to min or max).
  • *

  • * The elements having the same score are returned sorted lexicographically as ASCII strings (this
  • * follows from a property of Redis sorted sets and does not involve further computation).
  • *

  • * Using the optional {@link #zrangeByScore(byte[], double, double, int, int) LIMIT} it's possible
  • * to get only a range of the matching elements in an SQL-alike way. Note that if offset is large
  • * the commands needs to traverse the list for offset elements and this adds up to the O(M)
  • * figure.
  • *

  • * The {@link #zcount(byte[], double, double) ZCOUNT} command is similar to
  • * {@link #zrangeByScore(byte[], double, double) ZRANGEBYSCORE} but instead of returning the
  • * actual elements in the specified interval, it just returns the number of matching elements.
  • *

  • * Exclusive intervals and infinity
  • *

  • * min and max can be -inf and +inf, so that you are not required to know what's the greatest or
  • * smallest element in order to take, for instance, elements "up to a given value".
  • *

  • * Also while the interval is for default closed (inclusive) it's possible to specify open
  • * intervals prefixing the score with a "(" character, so for instance:
  • *

  • * {@code ZRANGEBYSCORE zset (1.3 5}
  • *

  • * Will return all the values with score > 1.3 and <= 5, while for instance:
  • *

  • * {@code ZRANGEBYSCORE zset (5 (10}
  • *

  • * Will return all the values with score > 5 and < 10 (5 and 10 excluded).
  • *

  • * Time complexity:
  • *

  • * O(log(N))+O(M) with N being the number of elements in the sorted set and M the number of
  • * elements returned by the command, so if M is constant (for instance you always ask for the
  • * first ten elements with LIMIT) you can consider it O(log(N))
  • * @see #zrangeByScore(byte[], double, double)
  • * @see #zrangeByScore(byte[], double, double, int, int)
  • * @see #zrangeByScoreWithScores(byte[], double, double)
  • * @see #zrangeByScoreWithScores(byte[], double, double, int, int)
  • * @see #zcount(byte[], double, double)
  • * @param key
  • * @param min
  • * @param max
  • * @param offset
  • * @param count
  • * @return Multi bulk reply specifically a list of elements in the specified score range.
  • */
  • @Override
  • public Set zrangeByScore(final byte[] key, final double min, final double max,
  • final int offset, final int count) {
  • checkIsInMultiOrPipeline();
  • client.zrangeByScore(key, min, max, offset, count);
  • return SetFromList.of(client.getBinaryMultiBulkReply());
  • }
  • @Override
  • public Set zrangeByScore(final byte[] key, final byte[] min, final byte[] max,
  • final int offset, final int count) {
  • checkIsInMultiOrPipeline();
  • client.zrangeByScore(key, min, max, offset, count);
  • return SetFromList.of(client.getBinaryMultiBulkReply());
  • }
  • /**
  • * Return the all the elements in the sorted set at key with a score between min and max
  • * (including elements with score equal to min or max).
  • *

  • * The elements having the same score are returned sorted lexicographically as ASCII strings (this
  • * follows from a property of Redis sorted sets and does not involve further computation).
  • *

  • * Using the optional {@link #zrangeByScore(byte[], double, double, int, int) LIMIT} it's possible
  • * to get only a range of the matching elements in an SQL-alike way. Note that if offset is large
  • * the commands needs to traverse the list for offset elements and this adds up to the O(M)
  • * figure.
  • *

  • * The {@link #zcount(byte[], double, double) ZCOUNT} command is similar to
  • * {@link #zrangeByScore(byte[], double, double) ZRANGEBYSCORE} but instead of returning the
  • * actual elements in the specified interval, it just returns the number of matching elements.
  • *

  • * Exclusive intervals and infinity
  • *

  • * min and max can be -inf and +inf, so that you are not required to know what's the greatest or
  • * smallest element in order to take, for instance, elements "up to a given value".
  • *

  • * Also while the interval is for default closed (inclusive) it's possible to specify open
  • * intervals prefixing the score with a "(" character, so for instance:
  • *

  • * {@code ZRANGEBYSCORE zset (1.3 5}
  • *

  • * Will return all the values with score > 1.3 and <= 5, while for instance:
  • *

  • * {@code ZRANGEBYSCORE zset (5 (10}
  • *

  • * Will return all the values with score > 5 and < 10 (5 and 10 excluded).
  • *

  • * Time complexity:
  • *

  • * O(log(N))+O(M) with N being the number of elements in the sorted set and M the number of
  • * elements returned by the command, so if M is constant (for instance you always ask for the
  • * first ten elements with LIMIT) you can consider it O(log(N))
  • * @see #zrangeByScore(byte[], double, double)
  • * @see #zrangeByScore(byte[], double, double, int, int)
  • * @see #zrangeByScoreWithScores(byte[], double, double)
  • * @see #zrangeByScoreWithScores(byte[], double, double, int, int)
  • * @see #zcount(byte[], double, double)
  • * @param key
  • * @param min
  • * @param max
  • * @return Multi bulk reply specifically a list of elements in the specified score range.
  • */
  • @Override
  • public Set<Tuple> zrangeByScoreWithScores(final byte[] key, final double min, final double max) {
  • checkIsInMultiOrPipeline();
  • client.zrangeByScoreWithScores(key, min, max);
  • return getTupledSet();
  • }
  • @Override
  • public Set<Tuple> zrangeByScoreWithScores(final byte[] key, final byte[] min, final byte[] max) {
  • checkIsInMultiOrPipeline();
  • client.zrangeByScoreWithScores(key, min, max);
  • return getTupledSet();
  • }
  • /**
  • * Return the all the elements in the sorted set at key with a score between min and max
  • * (including elements with score equal to min or max).
  • *

  • * The elements having the same score are returned sorted lexicographically as ASCII strings (this
  • * follows from a property of Redis sorted sets and does not involve further computation).
  • *

  • * Using the optional {@link #zrangeByScore(byte[], double, double, int, int) LIMIT} it's possible
  • * to get only a range of the matching elements in an SQL-alike way. Note that if offset is large
  • * the commands needs to traverse the list for offset elements and this adds up to the O(M)
  • * figure.
  • *

  • * The {@link #zcount(byte[], double, double) ZCOUNT} command is similar to
  • * {@link #zrangeByScore(byte[], double, double) ZRANGEBYSCORE} but instead of returning the
  • * actual elements in the specified interval, it just returns the number of matching elements.
  • *

  • * Exclusive intervals and infinity
  • *

  • * min and max can be -inf and +inf, so that you are not required to know what's the greatest or
  • * smallest element in order to take, for instance, elements "up to a given value".
  • *

  • * Also while the interval is for default closed (inclusive) it's possible to specify open
  • * intervals prefixing the score with a "(" character, so for instance:
  • *

  • * {@code ZRANGEBYSCORE zset (1.3 5}
  • *

  • * Will return all the values with score > 1.3 and <= 5, while for instance:
  • *

  • * {@code ZRANGEBYSCORE zset (5 (10}
  • *

  • * Will return all the values with score > 5 and < 10 (5 and 10 excluded).
  • *

  • * Time complexity:
  • *

  • * O(log(N))+O(M) with N being the number of elements in the sorted set and M the number of
  • * elements returned by the command, so if M is constant (for instance you always ask for the
  • * first ten elements with LIMIT) you can consider it O(log(N))
  • * @see #zrangeByScore(byte[], double, double)
  • * @see #zrangeByScore(byte[], double, double, int, int)
  • * @see #zrangeByScoreWithScores(byte[], double, double)
  • * @see #zrangeByScoreWithScores(byte[], double, double, int, int)
  • * @see #zcount(byte[], double, double)
  • * @param key
  • * @param min
  • * @param max
  • * @param offset
  • * @param count
  • * @return Multi bulk reply specifically a list of elements in the specified score range.
  • */
  • @Override
  • public Set<Tuple> zrangeByScoreWithScores(final byte[] key, final double min, final double max,
  • final int offset, final int count) {
  • checkIsInMultiOrPipeline();
  • client.zrangeByScoreWithScores(key, min, max, offset, count);
  • return getTupledSet();
  • }
  • @Override
  • public Set<Tuple> zrangeByScoreWithScores(final byte[] key, final byte[] min, final byte[] max,
  • final int offset, final int count) {
  • checkIsInMultiOrPipeline();
  • client.zrangeByScoreWithScores(key, min, max, offset, count);
  • return getTupledSet();
  • }
  • protected Set<Tuple> getTupledSet() {
  • List membersWithScores = client.getBinaryMultiBulkReply();
  • if (membersWithScores.isEmpty()) {
  • return Collections.emptySet();
  • }
  • Set<Tuple> set = new LinkedHashSet<>(membersWithScores.size() / 2, 1.0f);
  • Iterator iterator = membersWithScores.iterator();
  • while (iterator.hasNext()) {
  • set.add(new Tuple(iterator.next(), BuilderFactory.DOUBLE.build(iterator.next())));
  • }
  • return set;
  • }
  • @Override
  • public Set zrevrangeByScore(final byte[] key, final double max, final double min) {
  • checkIsInMultiOrPipeline();
  • client.zrevrangeByScore(key, max, min);
  • return SetFromList.of(client.getBinaryMultiBulkReply());
  • }
  • @Override
  • public Set zrevrangeByScore(final byte[] key, final byte[] max, final byte[] min) {
  • checkIsInMultiOrPipeline();
  • client.zrevrangeByScore(key, max, min);
  • return SetFromList.of(client.getBinaryMultiBulkReply());
  • }
  • @Override
  • public Set zrevrangeByScore(final byte[] key, final double max, final double min,
  • final int offset, final int count) {
  • checkIsInMultiOrPipeline();
  • client.zrevrangeByScore(key, max, min, offset, count);
  • return SetFromList.of(client.getBinaryMultiBulkReply());
  • }
  • @Override
  • public Set zrevrangeByScore(final byte[] key, final byte[] max, final byte[] min,
  • final int offset, final int count) {
  • checkIsInMultiOrPipeline();
  • client.zrevrangeByScore(key, max, min, offset, count);
  • return SetFromList.of(client.getBinaryMultiBulkReply());
  • }
  • @Override
  • public Set<Tuple> zrevrangeByScoreWithScores(final byte[] key, final double max, final double min) {
  • checkIsInMultiOrPipeline();
  • client.zrevrangeByScoreWithScores(key, max, min);
  • return getTupledSet();
  • }
  • @Override
  • public Set<Tuple> zrevrangeByScoreWithScores(final byte[] key, final double max,
  • final double min, final int offset, final int count) {
  • checkIsInMultiOrPipeline();
  • client.zrevrangeByScoreWithScores(key, max, min, offset, count);
  • return getTupledSet();
  • }
  • @Override
  • public Set<Tuple> zrevrangeByScoreWithScores(final byte[] key, final byte[] max, final byte[] min) {
  • checkIsInMultiOrPipeline();
  • client.zrevrangeByScoreWithScores(key, max, min);
  • return getTupledSet();
  • }
  • @Override
  • public Set<Tuple> zrevrangeByScoreWithScores(final byte[] key, final byte[] max,
  • final byte[] min, final int offset, final int count) {
  • checkIsInMultiOrPipeline();
  • client.zrevrangeByScoreWithScores(key, max, min, offset, count);
  • return getTupledSet();
  • }
  • /**
  • * Remove all elements in the sorted set at key with rank between start and end. Start and end are
  • * 0-based with rank 0 being the element with the lowest score. Both start and end can be negative
  • * numbers, where they indicate offsets starting at the element with the highest rank. For
  • * example: -1 is the element with the highest score, -2 the element with the second highest score
  • * and so forth.
  • *

  • * Time complexity: O(log(N))+O(M) with N being the number of elements in the sorted set
  • * and M the number of elements removed by the operation
  • * @param key
  • * @param start
  • * @param stop
  • * @return
  • */
  • @Override
  • public Long zremrangeByRank(final byte[] key, final long start, final long stop) {
  • checkIsInMultiOrPipeline();
  • client.zremrangeByRank(key, start, stop);
  • return client.getIntegerReply();
  • }
  • /**
  • * Remove all the elements in the sorted set at key with a score between min and max (including
  • * elements with score equal to min or max).
  • *

  • * Time complexity:
  • *

  • * O(log(N))+O(M) with N being the number of elements in the sorted set and M the number of
  • * elements removed by the operation
  • * @param key
  • * @param min
  • * @param max
  • * @return Integer reply, specifically the number of elements removed.
  • */
  • @Override
  • public Long zremrangeByScore(final byte[] key, final double min, final double max) {
  • checkIsInMultiOrPipeline();
  • client.zremrangeByScore(key, min, max);
  • return client.getIntegerReply();
  • }
  • @Override
  • public Long zremrangeByScore(final byte[] key, final byte[] min, final byte[] max) {
  • checkIsInMultiOrPipeline();
  • client.zremrangeByScore(key, min, max);
  • return client.getIntegerReply();
  • }
  • /**
  • * Creates a union or intersection of N sorted sets given by keys k1 through kN, and stores it at
  • * dstkey. It is mandatory to provide the number of input keys N, before passing the input keys
  • * and the other (optional) arguments.
  • *

  • * As the terms imply, the {@link #zinterstore(byte[], byte[]...)} ZINTERSTORE} command requires
  • * an element to be present in each of the given inputs to be inserted in the result. The {@link
  • * #zunionstore(byte[], byte[]...)} command inserts all elements across all inputs.
  • *

  • * Using the WEIGHTS option, it is possible to add weight to each input sorted set. This means
  • * that the score of each element in the sorted set is first multiplied by this weight before
  • * being passed to the aggregation. When this option is not given, all weights default to 1.
  • *

  • * With the AGGREGATE option, it's possible to specify how the results of the union or
  • * intersection are aggregated. This option defaults to SUM, where the score of an element is
  • * summed across the inputs where it exists. When this option is set to be either MIN or MAX, the
  • * resulting set will contain the minimum or maximum score of an element across the inputs where
  • * it exists.
  • *

  • * Time complexity: O(N) + O(M log(M)) with N being the sum of the sizes of the input
  • * sorted sets, and M being the number of elements in the resulting sorted set
  • * @see #zunionstore(byte[], byte[]...)
  • * @see #zunionstore(byte[], ZParams, byte[]...)
  • * @see #zinterstore(byte[], byte[]...)
  • * @see #zinterstore(byte[], ZParams, byte[]...)
  • * @param dstkey
  • * @param sets
  • * @return Integer reply, specifically the number of elements in the sorted set at dstkey
  • */
  • @Override
  • public Long zunionstore(final byte[] dstkey, final byte[]... sets) {
  • checkIsInMultiOrPipeline();
  • client.zunionstore(dstkey, sets);
  • return client.getIntegerReply();
  • }
  • /**
  • * Creates a union or intersection of N sorted sets given by keys k1 through kN, and stores it at
  • * dstkey. It is mandatory to provide the number of input keys N, before passing the input keys
  • * and the other (optional) arguments.
  • *

  • * As the terms imply, the {@link #zinterstore(byte[], byte[]...) ZINTERSTORE} command requires an
  • * element to be present in each of the given inputs to be inserted in the result. The {@link
  • * #zunionstore(byte[], byte[]...) ZUNIONSTORE} command inserts all elements across all inputs.
  • *

  • * Using the WEIGHTS option, it is possible to add weight to each input sorted set. This means
  • * that the score of each element in the sorted set is first multiplied by this weight before
  • * being passed to the aggregation. When this option is not given, all weights default to 1.
  • *

  • * With the AGGREGATE option, it's possible to specify how the results of the union or
  • * intersection are aggregated. This option defaults to SUM, where the score of an element is
  • * summed across the inputs where it exists. When this option is set to be either MIN or MAX, the
  • * resulting set will contain the minimum or maximum score of an element across the inputs where
  • * it exists.
  • *

  • * Time complexity: O(N) + O(M log(M)) with N being the sum of the sizes of the input
  • * sorted sets, and M being the number of elements in the resulting sorted set
  • * @see #zunionstore(byte[], byte[]...)
  • * @see #zunionstore(byte[], ZParams, byte[]...)
  • * @see #zinterstore(byte[], byte[]...)
  • * @see #zinterstore(byte[], ZParams, byte[]...)
  • * @param dstkey
  • * @param sets
  • * @param params
  • * @return Integer reply, specifically the number of elements in the sorted set at dstkey
  • */
  • @Override
  • public Long zunionstore(final byte[] dstkey, final ZParams params, final byte[]... sets) {
  • checkIsInMultiOrPipeline();
  • client.zunionstore(dstkey, params, sets);
  • return client.getIntegerReply();
  • }
  • /**
  • * Creates a union or intersection of N sorted sets given by keys k1 through kN, and stores it at
  • * dstkey. It is mandatory to provide the number of input keys N, before passing the input keys
  • * and the other (optional) arguments.
  • *

  • * As the terms imply, the {@link #zinterstore(byte[], byte[]...) ZINTERSTORE} command requires an
  • * element to be present in each of the given inputs to be inserted in the result. The {@link
  • * #zunionstore(byte[], byte[]...) ZUNIONSTORE} command inserts all elements across all inputs.
  • *

  • * Using the WEIGHTS option, it is possible to add weight to each input sorted set. This means
  • * that the score of each element in the sorted set is first multiplied by this weight before
  • * being passed to the aggregation. When this option is not given, all weights default to 1.
  • *

  • * With the AGGREGATE option, it's possible to specify how the results of the union or
  • * intersection are aggregated. This option defaults to SUM, where the score of an element is
  • * summed across the inputs where it exists. When this option is set to be either MIN or MAX, the
  • * resulting set will contain the minimum or maximum score of an element across the inputs where
  • * it exists.
  • *

  • * Time complexity: O(N) + O(M log(M)) with N being the sum of the sizes of the input
  • * sorted sets, and M being the number of elements in the resulting sorted set
  • * @see #zunionstore(byte[], byte[]...)
  • * @see #zunionstore(byte[], ZParams, byte[]...)
  • * @see #zinterstore(byte[], byte[]...)
  • * @see #zinterstore(byte[], ZParams, byte[]...)
  • * @param dstkey
  • * @param sets
  • * @return Integer reply, specifically the number of elements in the sorted set at dstkey
  • */
  • @Override
  • public Long zinterstore(final byte[] dstkey, final byte[]... sets) {
  • checkIsInMultiOrPipeline();
  • client.zinterstore(dstkey, sets);
  • return client.getIntegerReply();
  • }
  • /**
  • * Creates a union or intersection of N sorted sets given by keys k1 through kN, and stores it at
  • * dstkey. It is mandatory to provide the number of input keys N, before passing the input keys
  • * and the other (optional) arguments.
  • *

  • * As the terms imply, the {@link #zinterstore(byte[], byte[]...) ZINTERSTORE} command requires an
  • * element to be present in each of the given inputs to be inserted in the result. The {@link
  • * #zunionstore(byte[], byte[]...) ZUNIONSTORE} command inserts all elements across all inputs.
  • *

  • * Using the WEIGHTS option, it is possible to add weight to each input sorted set. This means
  • * that the score of each element in the sorted set is first multiplied by this weight before
  • * being passed to the aggregation. When this option is not given, all weights default to 1.
  • *

  • * With the AGGREGATE option, it's possible to specify how the results of the union or
  • * intersection are aggregated. This option defaults to SUM, where the score of an element is
  • * summed across the inputs where it exists. When this option is set to be either MIN or MAX, the
  • * resulting set will contain the minimum or maximum score of an element across the inputs where
  • * it exists.
  • *

  • * Time complexity: O(N) + O(M log(M)) with N being the sum of the sizes of the input
  • * sorted sets, and M being the number of elements in the resulting sorted set
  • * @see #zunionstore(byte[], byte[]...)
  • * @see #zunionstore(byte[], ZParams, byte[]...)
  • * @see #zinterstore(byte[], byte[]...)
  • * @see #zinterstore(byte[], ZParams, byte[]...)
  • * @param dstkey
  • * @param sets
  • * @param params
  • * @return Integer reply, specifically the number of elements in the sorted set at dstkey
  • */
  • @Override
  • public Long zinterstore(final byte[] dstkey, final ZParams params, final byte[]... sets) {
  • checkIsInMultiOrPipeline();
  • client.zinterstore(dstkey, params, sets);
  • return client.getIntegerReply();
  • }
  • @Override
  • public Long zlexcount(final byte[] key, final byte[] min, final byte[] max) {
  • checkIsInMultiOrPipeline();
  • client.zlexcount(key, min, max);
  • return client.getIntegerReply();
  • }
  • @Override
  • public Set zrangeByLex(final byte[] key, final byte[] min, final byte[] max) {
  • checkIsInMultiOrPipeline();
  • client.zrangeByLex(key, min, max);
  • return SetFromList.of(client.getBinaryMultiBulkReply());
  • }
  • @Override
  • public Set zrangeByLex(final byte[] key, final byte[] min, final byte[] max,
  • final int offset, final int count) {
  • checkIsInMultiOrPipeline();
  • client.zrangeByLex(key, min, max, offset, count);
  • return SetFromList.of(client.getBinaryMultiBulkReply());
  • }
  • @Override
  • public Set zrevrangeByLex(final byte[] key, final byte[] max, final byte[] min) {
  • checkIsInMultiOrPipeline();
  • client.zrevrangeByLex(key, max, min);
  • return SetFromList.of(client.getBinaryMultiBulkReply());
  • }
  • @Override
  • public Set zrevrangeByLex(final byte[] key, final byte[] max, final byte[] min, final int offset, final int count) {
  • checkIsInMultiOrPipeline();
  • client.zrevrangeByLex(key, max, min, offset, count);
  • return SetFromList.of(client.getBinaryMultiBulkReply());
  • }
  • @Override
  • public Long zremrangeByLex(final byte[] key, final byte[] min, final byte[] max) {
  • checkIsInMultiOrPipeline();
  • client.zremrangeByLex(key, min, max);
  • return client.getIntegerReply();
  • }
  • /**
  • * Synchronously save the DB on disk.
  • *

  • * Save the whole dataset on disk (this means that all the databases are saved, as well as keys
  • * with an EXPIRE set (the expire is preserved). The server hangs while the saving is not
  • * completed, no connection is served in the meanwhile. An OK code is returned when the DB was
  • * fully stored in disk.
  • *

  • * The background variant of this command is {@link #bgsave() BGSAVE} that is able to perform the
  • * saving in the background while the server continues serving other clients.
  • *

  • * @return Status code reply
  • */
  • @Override
  • public String save() {
  • client.save();
  • return client.getStatusCodeReply();
  • }
  • /**
  • * Asynchronously save the DB on disk.
  • *

  • * Save the DB in background. The OK code is immediately returned. Redis forks, the parent
  • * continues to server the clients, the child saves the DB on disk then exit. A client my be able
  • * to check if the operation succeeded using the LASTSAVE command.
  • * @return Status code reply
  • */
  • @Override
  • public String bgsave() {
  • client.bgsave();
  • return client.getStatusCodeReply();
  • }
  • /**
  • * Rewrite the append only file in background when it gets too big. Please for detailed
  • * information about the Redis Append Only File check the
  • * href="http://redis.io/topics/persistence#append-only-file">Append Only File Howto.
  • *

  • * BGREWRITEAOF rewrites the Append Only File in background when it gets too big. The Redis Append
  • * Only File is a Journal, so every operation modifying the dataset is logged in the Append Only
  • * File (and replayed at startup). This means that the Append Only File always grows. In order to
  • * rebuild its content the BGREWRITEAOF creates a new version of the append only file starting
  • * directly form the dataset in memory in order to guarantee the generation of the minimal number
  • * of commands needed to rebuild the database.
  • *

  • * @return Status code reply
  • */
  • @Override
  • public String bgrewriteaof() {
  • client.bgrewriteaof();
  • return client.getStatusCodeReply();
  • }
  • /**
  • * Return the UNIX time stamp of the last successfully saving of the dataset on disk.
  • *

  • * Return the UNIX TIME of the last DB save executed with success. A client may check if a
  • * {@link #bgsave() BGSAVE} command succeeded reading the LASTSAVE value, then issuing a BGSAVE
  • * command and checking at regular intervals every N seconds if LASTSAVE changed.
  • * @return Integer reply, specifically an UNIX time stamp.
  • */
  • @Override
  • public Long lastsave() {
  • client.lastsave();
  • return client.getIntegerReply();
  • }
  • /**
  • * Synchronously save the DB on disk, then shutdown the server.
  • *

  • * Stop all the clients, save the DB, then quit the server. This commands makes sure that the DB
  • * is switched off without the lost of any data. This is not guaranteed if the client uses simply
  • * {@link #save() SAVE} and then {@link #quit() QUIT} because other clients may alter the DB data
  • * between the two commands.
  • * @return Status code reply on error. On success nothing is returned since the server quits and
  • * the connection is closed.
  • */
  • @Override
  • public String shutdown() {
  • client.shutdown();
  • String status;
  • try {
  • status = client.getStatusCodeReply();
  • } catch (JedisException ex) {
  • status = null;
  • }
  • return status;
  • }
  • /**
  • * Provide information and statistics about the server.
  • *

  • * The info command returns different information and statistics about the server in an format
  • * that's simple to parse by computers and easy to read by humans.
  • *

  • * Format of the returned String:
  • *

  • * All the fields are in the form field:value
  • *
  • *
  • * edis_version:0.07
  • * connected_clients:1
  • * connected_slaves:0
  • * used_memory:3187
  • * changes_since_last_save:0
  • * last_save_time:1237655729
  • * total_connections_received:1
  • * total_commands_processed:1
  • * uptime_in_seconds:25
  • * uptime_in_days:0
  • *
  • *
  • * Notes
  • *

  • * used_memory is returned in bytes, and is the total number of bytes allocated by the program
  • * using malloc.
  • *

  • * uptime_in_days is redundant since the uptime in seconds contains already the full uptime
  • * information, this field is only mainly present for humans.
  • *

  • * changes_since_last_save does not refer to the number of key changes, but to the number of
  • * operations that produced some kind of change in the dataset.
  • *

  • * @return Bulk reply
  • */
  • @Override
  • public String info() {
  • client.info();
  • return client.getBulkReply();
  • }
  • @Override
  • public String info(final String section) {
  • client.info(section);
  • return client.getBulkReply();
  • }
  • /**
  • * Dump all the received requests in real time.
  • *

  • * MONITOR is a debugging command that outputs the whole sequence of commands received by the
  • * Redis server. is very handy in order to understand what is happening into the database. This
  • * command is used directly via telnet.
  • * @param jedisMonitor
  • */
  • public void monitor(final JedisMonitor jedisMonitor) {
  • client.monitor();
  • client.getStatusCodeReply();
  • jedisMonitor.proceed(client);
  • }
  • /**
  • * Change the replication settings.
  • *

  • * The SLAVEOF command can change the replication settings of a slave on the fly. If a Redis
  • * server is already acting as slave, the command SLAVEOF NO ONE will turn off the replication
  • * turning the Redis server into a MASTER. In the proper form SLAVEOF hostname port will make the
  • * server a slave of the specific server listening at the specified hostname and port.
  • *

  • * If a server is already a slave of some master, SLAVEOF hostname port will stop the replication
  • * against the old server and start the synchronization against the new one discarding the old
  • * dataset.
  • *

  • * The form SLAVEOF no one will stop replication turning the server into a MASTER but will not
  • * discard the replication. So if the old master stop working it is possible to turn the slave
  • * into a master and set the application to use the new master in read/write. Later when the other
  • * Redis server will be fixed it can be configured in order to work as slave.
  • *

  • * @param host
  • * @param port
  • * @return Status code reply
  • */
  • @Override
  • public String slaveof(final String host, final int port) {
  • client.slaveof(host, port);
  • return client.getStatusCodeReply();
  • }
  • @Override
  • public String slaveofNoOne() {
  • client.slaveofNoOne();
  • return client.getStatusCodeReply();
  • }
  • /**
  • * Retrieve the configuration of a running Redis server. Not all the configuration parameters are
  • * supported.
  • *

  • * CONFIG GET returns the current configuration parameters. This sub command only accepts a single
  • * argument, that is glob style pattern. All the configuration parameters matching this parameter
  • * are reported as a list of key-value pairs.
  • *

  • * Example:
  • *
  • *
  • * $ redis-cli config get '*'
  • * 1. "dbfilename"
  • * 2. "dump.rdb"
  • * 3. "requirepass"
  • * 4. (nil)
  • * 5. "masterauth"
  • * 6. (nil)
  • * 7. "maxmemory"
  • * 8. "0\n"
  • * 9. "appendfsync"
  • * 10. "everysec"
  • * 11. "save"
  • * 12. "3600 1 300 100 60 10000"
  • *
  • * $ redis-cli config get 'm*'
  • * 1. "masterauth"
  • * 2. (nil)
  • * 3. "maxmemory"
  • * 4. "0\n"
  • *
  • * @param pattern
  • * @return Bulk reply.
  • */
  • @Override
  • public List configGet(final byte[] pattern) {
  • checkIsInMultiOrPipeline();
  • client.configGet(pattern);
  • return client.getBinaryMultiBulkReply();
  • }
  • /**
  • * Reset the stats returned by INFO
  • * @return
  • */
  • @Override
  • public String configResetStat() {
  • checkIsInMultiOrPipeline();
  • client.configResetStat();
  • return client.getStatusCodeReply();
  • }
  • /**
  • * The CONFIG REWRITE command rewrites the redis.conf file the server was started with, applying
  • * the minimal changes needed to make it reflect the configuration currently used by the server,
  • * which may be different compared to the original one because of the use of the CONFIG SET command.
  • *
  • * The rewrite is performed in a very conservative way:
  • *
    • *
    • Comments and the overall structure of the original redis.conf are preserved as much as possible.
    • *
    • If an option already exists in the old redis.conf file, it will be rewritten at the same position (line number).
    • *
    • If an option was not already present, but it is set to its default value, it is not added by the rewrite process.
    • *
    • If an option was not already present, but it is set to a non-default value, it is appended at the end of the file.
    • *
    • Non used lines are blanked. For instance if you used to have multiple save directives, but
    • * the current configuration has fewer or none as you disabled RDB persistence, all the lines will be blanked.
    • *
    • *
    • * CONFIG REWRITE is also able to rewrite the configuration file from scratch if the original one
    • * no longer exists for some reason. However if the server was started without a configuration
    • * file at all, the CONFIG REWRITE will just return an error.
    • * @return OK when the configuration was rewritten properly. Otherwise an error is returned.
    • */
    • @Override
    • public String configRewrite() {
    • checkIsInMultiOrPipeline();
    • client.configRewrite();
    • return client.getStatusCodeReply();
    • }
    • /**
    • * Alter the configuration of a running Redis server. Not all the configuration parameters are
    • * supported.
    • *

    • * The list of configuration parameters supported by CONFIG SET can be obtained issuing a
    • * {@link #configGet(byte[]) CONFIG GET *} command.
    • *

    • * The configuration set using CONFIG SET is immediately loaded by the Redis server that will
    • * start acting as specified starting from the next command.
    • *

    • * Parameters value format
    • *

    • * The value of the configuration parameter is the same as the one of the same parameter in the
    • * Redis configuration file, with the following exceptions:
    • *

    • *
      • *
      • The save parameter is a list of space-separated integers. Every pair of integers specify the
      • * time and number of changes limit to trigger a save. For instance the command CONFIG SET save
      • * "3600 10 60 10000" will configure the server to issue a background saving of the RDB file every
      • * 3600 seconds if there are at least 10 changes in the dataset, and every 60 seconds if there are
      • * at least 10000 changes. To completely disable automatic snapshots just set the parameter as an
      • * empty string.
      • *
      • All the integer parameters representing memory are returned and accepted only using bytes
      • * as unit.
      • *
      • * @param parameter
      • * @param value
      • * @return Status code reply
      • */
      • @Override
      • public byte[] configSet(final byte[] parameter, final byte[] value) {
      • checkIsInMultiOrPipeline();
      • client.configSet(parameter, value);
      • return client.getBinaryBulkReply();
      • }
      • public boolean isConnected() {
      • return client.isConnected();
      • }
      • @Override
      • public Long strlen(final byte[] key) {
      • checkIsInMultiOrPipeline();
      • client.strlen(key);
      • return client.getIntegerReply();
      • }
      • public void sync() {
      • client.sync();
      • }
      • @Override
      • public Long lpushx(final byte[] key, final byte[]... string) {
      • checkIsInMultiOrPipeline();
      • client.lpushx(key, string);
      • return client.getIntegerReply();
      • }
      • /**
      • * Undo a {@link #expire(byte[], int) expire} at turning the expire key into a normal key.
      • *

      • * Time complexity: O(1)
      • * @param key
      • * @return Integer reply, specifically: 1: the key is now persist. 0: the key is not persist (only
      • * happens when key not set).
      • */
      • @Override
      • public Long persist(final byte[] key) {
      • checkIsInMultiOrPipeline();
      • client.persist(key);
      • return client.getIntegerReply();
      • }
      • @Override
      • public Long rpushx(final byte[] key, final byte[]... string) {
      • checkIsInMultiOrPipeline();
      • client.rpushx(key, string);
      • return client.getIntegerReply();
      • }
      • @Override
      • public byte[] echo(final byte[] string) {
      • checkIsInMultiOrPipeline();
      • client.echo(string);
      • return client.getBinaryBulkReply();
      • }
      • @Override
      • public Long linsert(final byte[] key, final ListPosition where, final byte[] pivot,
      • final byte[] value) {
      • checkIsInMultiOrPipeline();
      • client.linsert(key, where, pivot, value);
      • return client.getIntegerReply();
      • }
      • @Override
      • public String debug(final DebugParams params) {
      • client.debug(params);
      • return client.getStatusCodeReply();
      • }
      • public Client getClient() {
      • return client;
      • }
      • /**
      • * Pop a value from a list, push it to another list and return it; or block until one is available
      • * @param source
      • * @param destination
      • * @param timeout
      • * @return the element
      • */
      • @Override
      • public byte[] brpoplpush(final byte[] source, final byte[] destination, final int timeout) {
      • checkIsInMultiOrPipeline();
      • client.brpoplpush(source, destination, timeout);
      • client.setTimeoutInfinite();
      • try {
      • return client.getBinaryBulkReply();
      • } finally {
      • client.rollbackTimeout();
      • }
      • }
      • /**
      • * Sets or clears the bit at offset in the string value stored at key
      • * @param key
      • * @param offset
      • * @param value
      • * @return
      • */
      • @Override
      • public Boolean setbit(final byte[] key, final long offset, final boolean value) {
      • checkIsInMultiOrPipeline();
      • client.setbit(key, offset, value);
      • return client.getIntegerReply() == 1;
      • }
      • @Override
      • public Boolean setbit(final byte[] key, final long offset, final byte[] value) {
      • checkIsInMultiOrPipeline();
      • client.setbit(key, offset, value);
      • return client.getIntegerReply() == 1;
      • }
      • /**
      • * Returns the bit value at offset in the string value stored at key
      • * @param key
      • * @param offset
      • * @return
      • */
      • @Override
      • public Boolean getbit(final byte[] key, final long offset) {
      • checkIsInMultiOrPipeline();
      • client.getbit(key, offset);
      • return client.getIntegerReply() == 1;
      • }
      • public Long bitpos(final byte[] key, final boolean value) {
      • return bitpos(key, value, new BitPosParams());
      • }
      • public Long bitpos(final byte[] key, final boolean value, final BitPosParams params) {
      • checkIsInMultiOrPipeline();
      • client.bitpos(key, value, params);
      • return client.getIntegerReply();
      • }
      • @Override
      • public Long setrange(final byte[] key, final long offset, final byte[] value) {
      • checkIsInMultiOrPipeline();
      • client.setrange(key, offset, value);
      • return client.getIntegerReply();
      • }
      • @Override
      • public byte[] getrange(final byte[] key, final long startOffset, final long endOffset) {
      • checkIsInMultiOrPipeline();
      • client.getrange(key, startOffset, endOffset);
      • return client.getBinaryBulkReply();
      • }
      • @Override
      • public Long publish(final byte[] channel, final byte[] message) {
      • checkIsInMultiOrPipeline();
      • client.publish(channel, message);
      • return client.getIntegerReply();
      • }
      • @Override
      • public void subscribe(BinaryJedisPubSub jedisPubSub, final byte[]... channels) {
      • client.setTimeoutInfinite();
      • try {
      • jedisPubSub.proceed(client, channels);
      • } finally {
      • client.rollbackTimeout();
      • }
      • }
      • @Override
      • public void psubscribe(BinaryJedisPubSub jedisPubSub, final byte[]... patterns) {
      • client.setTimeoutInfinite();
      • try {
      • jedisPubSub.proceedWithPatterns(client, patterns);
      • } finally {
      • client.rollbackTimeout();
      • }
      • }
      • @Override
      • public int getDB() {
      • return client.getDB();
      • }
      • /**
      • * Evaluates scripts using the Lua interpreter built into Redis starting from version 2.6.0.
      • *

      • * @param script
      • * @param keys
      • * @param args
      • * @return Script result
      • */
      • @Override
      • public Object eval(final byte[] script, final List keys, final List args) {
      • return eval(script, toByteArray(keys.size()), getParamsWithBinary(keys, args));
      • }
      • protected static byte[][] getParamsWithBinary(List keys, List args) {
      • final int keyCount = keys.size();
      • final int argCount = args.size();
      • byte[][] params = new byte[keyCount + argCount][];
      • for (int i = 0; i < keyCount; i++)
      • params[i] = keys.get(i);
      • for (int i = 0; i < argCount; i++)
      • params[keyCount + i] = args.get(i);
      • return params;
      • }
      • @Override
      • public Object eval(final byte[] script, final byte[] keyCount, final byte[]... params) {
      • checkIsInMultiOrPipeline();
      • client.eval(script, keyCount, params);
      • client.setTimeoutInfinite();
      • try {
      • return client.getOne();
      • } finally {
      • client.rollbackTimeout();
      • }
      • }
      • @Override
      • public Object eval(final byte[] script, final int keyCount, final byte[]... params) {
      • return eval(script, toByteArray(keyCount), params);
      • }
      • @Override
      • public Object eval(final byte[] script) {
      • return eval(script, 0);
      • }
      • @Override
      • public Object evalsha(final byte[] sha1) {
      • return evalsha(sha1, 0);
      • }
      • @Override
      • public Object evalsha(final byte[] sha1, final List keys, final List args) {
      • return evalsha(sha1, keys.size(), getParamsWithBinary(keys, args));
      • }
      • @Override
      • public Object evalsha(final byte[] sha1, final int keyCount, final byte[]... params) {
      • checkIsInMultiOrPipeline();
      • client.evalsha(sha1, keyCount, params);
      • client.setTimeoutInfinite();
      • try {
      • return client.getOne();
      • } finally {
      • client.rollbackTimeout();
      • }
      • }
      • @Override
      • public String scriptFlush() {
      • client.scriptFlush();
      • return client.getStatusCodeReply();
      • }
      • public Long scriptExists(final byte[] sha1) {
      • byte[][] a = new byte[1][];
      • a[0] = sha1;
      • return scriptExists(a).get(0);
      • }
      • @Override
      • public List<Long> scriptExists(final byte[]... sha1) {
      • client.scriptExists(sha1);
      • return client.getIntegerMultiBulkReply();
      • }
      • @Override
      • public byte[] scriptLoad(final byte[] script) {
      • client.scriptLoad(script);
      • return client.getBinaryBulkReply();
      • }
      • @Override
      • public String scriptKill() {
      • client.scriptKill();
      • return client.getStatusCodeReply();
      • }
      • @Override
      • public String slowlogReset() {
      • client.slowlogReset();
      • return client.getBulkReply();
      • }
      • @Override
      • public Long slowlogLen() {
      • client.slowlogLen();
      • return client.getIntegerReply();
      • }
      • @Override
      • public List slowlogGetBinary() {
      • client.slowlogGet();
      • return client.getBinaryMultiBulkReply();
      • }
      • @Override
      • public List slowlogGetBinary(final long entries) {
      • client.slowlogGet(entries);
      • return client.getBinaryMultiBulkReply();
      • }
      • @Override
      • public Long objectRefcount(final byte[] key) {
      • client.objectRefcount(key);
      • return client.getIntegerReply();
      • }
      • @Override
      • public byte[] objectEncoding(final byte[] key) {
      • client.objectEncoding(key);
      • return client.getBinaryBulkReply();
      • }
      • @Override
      • public Long objectIdletime(final byte[] key) {
      • client.objectIdletime(key);
      • return client.getIntegerReply();
      • }
      • @Override
      • public List objectHelpBinary() {
      • client.objectHelp();
      • return client.getBinaryMultiBulkReply();
      • }
      • @Override
      • public Long objectFreq(final byte[] key) {
      • client.objectFreq(key);
      • return client.getIntegerReply();
      • }
      • @Override
      • public Long bitcount(final byte[] key) {
      • checkIsInMultiOrPipeline();
      • client.bitcount(key);
      • return client.getIntegerReply();
      • }
      • @Override
      • public Long bitcount(final byte[] key, final long start, final long end) {
      • checkIsInMultiOrPipeline();
      • client.bitcount(key, start, end);
      • return client.getIntegerReply();
      • }
      • @Override
      • public Long bitop(final BitOP op, final byte[] destKey, final byte[]... srcKeys) {
      • checkIsInMultiOrPipeline();
      • client.bitop(op, destKey, srcKeys);
      • return client.getIntegerReply();
      • }
      • @Override
      • public byte[] dump(final byte[] key) {
      • checkIsInMultiOrPipeline();
      • client.dump(key);
      • return client.getBinaryBulkReply();
      • }
      • @Override
      • public String restore(final byte[] key, final int ttl, final byte[] serializedValue) {
      • checkIsInMultiOrPipeline();
      • client.restore(key, ttl, serializedValue);
      • return client.getStatusCodeReply();
      • }
      • @Override
      • public String restoreReplace(final byte[] key, final int ttl, final byte[] serializedValue) {
      • checkIsInMultiOrPipeline();
      • client.restoreReplace(key, ttl, serializedValue);
      • return client.getStatusCodeReply();
      • }
      • /**
      • * Set a timeout on the specified key. After the timeout the key will be automatically deleted by
      • * the server. A key with an associated timeout is said to be volatile in Redis terminology.
      • *

      • * Volatile keys are stored on disk like the other keys, the timeout is persistent too like all the
      • * other aspects of the dataset. Saving a dataset containing expires and stopping the server does
      • * not stop the flow of time as Redis stores on disk the time when the key will no longer be
      • * available as Unix time, and not the remaining milliseconds.
      • *

      • * Since Redis 2.1.3 you can update the value of the timeout of a key already having an expire
      • * set. It is also possible to undo the expire at all turning the key into a normal key using the
      • * {@link #persist(byte[]) PERSIST} command.
      • *

      • * Time complexity: O(1)
      • * @param key
      • * @param milliseconds
      • * @return Integer reply, specifically: 1: the timeout was set. 0: the timeout was not set since
      • * the key already has an associated timeout (this may happen only in Redis versions <
      • * 2.1.3, Redis >= 2.1.3 will happily update the timeout), or the key does not exist.
      • */
      • @Override
      • public Long pexpire(final byte[] key, final long milliseconds) {
      • checkIsInMultiOrPipeline();
      • client.pexpire(key, milliseconds);
      • return client.getIntegerReply();
      • }
      • @Override
      • public Long pexpireAt(final byte[] key, final long millisecondsTimestamp) {
      • checkIsInMultiOrPipeline();
      • client.pexpireAt(key, millisecondsTimestamp);
      • return client.getIntegerReply();
      • }
      • @Override
      • public Long pttl(final byte[] key) {
      • checkIsInMultiOrPipeline();
      • client.pttl(key);
      • return client.getIntegerReply();
      • }
      • /**
      • * PSETEX works exactly like {@link #setex(byte[], int, byte[])} with the sole difference that the
      • * expire time is specified in milliseconds instead of seconds. Time complexity: O(1)
      • * @param key
      • * @param milliseconds
      • * @param value
      • * @return Status code reply
      • */
      • @Override
      • public String psetex(final byte[] key, final long milliseconds, final byte[] value) {
      • checkIsInMultiOrPipeline();
      • client.psetex(key, milliseconds, value);
      • return client.getStatusCodeReply();
      • }
      • @Override
      • public byte[] memoryDoctorBinary() {
      • checkIsInMultiOrPipeline();
      • client.memoryDoctor();
      • return client.getBinaryBulkReply();
      • }
      • @Override
      • public byte[] aclWhoAmIBinary() {
      • checkIsInMultiOrPipeline();
      • client.aclWhoAmI();
      • return client.getBinaryBulkReply();
      • }
      • @Override
      • public byte[] aclGenPassBinary() {
      • checkIsInMultiOrPipeline();
      • client.aclGenPass();
      • return client.getBinaryBulkReply();
      • }
      • @Override
      • public List aclListBinary() {
      • checkIsInMultiOrPipeline();
      • client.aclList();
      • return client.getBinaryMultiBulkReply();
      • }
      • @Override
      • public List aclUsersBinary() {
      • checkIsInMultiOrPipeline();
      • client.aclUsers();
      • return client.getBinaryMultiBulkReply();
      • }
      • @Override
      • public AccessControlUser aclGetUser(byte[] name) {
      • checkIsInMultiOrPipeline();
      • client.aclGetUser(name);
      • return BuilderFactory.ACCESS_CONTROL_USER.build(client.getObjectMultiBulkReply());
      • }
      • @Override
      • public String aclSetUser(byte[] name) {
      • checkIsInMultiOrPipeline();
      • client.aclSetUser(name);
      • return client.getStatusCodeReply();
      • }
      • @Override
      • public String aclSetUser(byte[] name, byte[]... keys) {
      • checkIsInMultiOrPipeline();
      • client.aclSetUser(name, keys);
      • return client.getStatusCodeReply();
      • }
      • @Override
      • public Long aclDelUser(byte[] name) {
      • checkIsInMultiOrPipeline();
      • client.aclDelUser(name);
      • return client.getIntegerReply();
      • }
      • @Override
      • public List aclCatBinary() {
      • checkIsInMultiOrPipeline();
      • client.aclCat();
      • return client.getBinaryMultiBulkReply();
      • }
      • @Override
      • public List aclCat(byte[] category) {
      • checkIsInMultiOrPipeline();
      • client.aclCat(category);
      • return client.getBinaryMultiBulkReply();
      • }
      • @Override
      • public String clientKill(final byte[] ipPort) {
      • checkIsInMultiOrPipeline();
      • this.client.clientKill(ipPort);
      • return this.client.getStatusCodeReply();
      • }
      • @Override
      • public String clientKill(final String ip, final int port) {
      • checkIsInMultiOrPipeline();
      • this.client.clientKill(ip, port);
      • return this.client.getStatusCodeReply();
      • }
      • @Override
      • public Long clientKill(ClientKillParams params) {
      • checkIsInMultiOrPipeline();
      • this.client.clientKill(params);
      • return this.client.getIntegerReply();
      • }
      • @Override
      • public byte[] clientGetnameBinary() {
      • checkIsInMultiOrPipeline();
      • client.clientGetname();
      • return client.getBinaryBulkReply();
      • }
      • @Override
      • public byte[] clientListBinary() {
      • checkIsInMultiOrPipeline();
      • client.clientList();
      • return client.getBinaryBulkReply();
      • }
      • @Override
      • public String clientSetname(final byte[] name) {
      • checkIsInMultiOrPipeline();
      • client.clientSetname(name);
      • return client.getBulkReply();
      • }
      • public String clientPause(final long timeout) {
      • checkIsInMultiOrPipeline();
      • client.clientPause(timeout);
      • return client.getBulkReply();
      • }
      • public List<String> time() {
      • checkIsInMultiOrPipeline();
      • client.time();
      • return client.getMultiBulkReply();
      • }
      • @Override
      • public String migrate(final String host, final int port, final byte[] key,
      • final int destinationDb, final int timeout) {
      • checkIsInMultiOrPipeline();
      • client.migrate(host, port, key, destinationDb, timeout);
      • return client.getStatusCodeReply();
      • }
      • @Override
      • public String migrate(final String host, final int port, final int destinationDB,
      • final int timeout, final MigrateParams params, final byte[]... keys) {
      • checkIsInMultiOrPipeline();
      • client.migrate(host, port, destinationDB, timeout, params, keys);
      • return client.getStatusCodeReply();
      • }
      • /**
      • * Syncrhonous replication of Redis as described here: http://antirez.com/news/66 Since Java
      • * Object class has implemented "wait" method, we cannot use it, so I had to change the name of
      • * the method. Sorry :S
      • */
      • @Override
      • public Long waitReplicas(final int replicas, final long timeout) {
      • checkIsInMultiOrPipeline();
      • client.waitReplicas(replicas, timeout);
      • return client.getIntegerReply();
      • }
      • @Override
      • public Long pfadd(final byte[] key, final byte[]... elements) {
      • checkIsInMultiOrPipeline();
      • client.pfadd(key, elements);
      • return client.getIntegerReply();
      • }
      • @Override
      • public long pfcount(final byte[] key) {
      • checkIsInMultiOrPipeline();
      • client.pfcount(key);
      • return client.getIntegerReply();
      • }
      • @Override
      • public String pfmerge(final byte[] destkey, final byte[]... sourcekeys) {
      • checkIsInMultiOrPipeline();
      • client.pfmerge(destkey, sourcekeys);
      • return client.getStatusCodeReply();
      • }
      • @Override
      • public Long pfcount(final byte[]... keys) {
      • checkIsInMultiOrPipeline();
      • client.pfcount(keys);
      • return client.getIntegerReply();
      • }
      • public ScanResult scan(final byte[] cursor) {
      • return scan(cursor, new ScanParams());
      • }
      • public ScanResult scan(final byte[] cursor, final ScanParams params) {
      • checkIsInMultiOrPipeline();
      • client.scan(cursor, params);
      • List<Object> result = client.getObjectMultiBulkReply();
      • byte[] newcursor = (byte[]) result.get(0);
      • List rawResults = (List) result.get(1);
      • return new ScanResult<>(newcursor, rawResults);
      • }
      • @Override
      • public ScanResult<Map.Entry> hscan(final byte[] key, final byte[] cursor) {
      • return hscan(key, cursor, new ScanParams());
      • }
      • @Override
      • public ScanResult<Map.Entry> hscan(final byte[] key, final byte[] cursor,
      • final ScanParams params) {
      • checkIsInMultiOrPipeline();
      • client.hscan(key, cursor, params);
      • List<Object> result = client.getObjectMultiBulkReply();
      • byte[] newcursor = (byte[]) result.get(0);
      • List<Map.Entry> results = new ArrayList<>();
      • List rawResults = (List) result.get(1);
      • Iterator iterator = rawResults.iterator();
      • while (iterator.hasNext()) {
      • results.add(new AbstractMap.SimpleEntry(iterator.next(), iterator.next()));
      • }
      • return new ScanResult<>(newcursor, results);
      • }
      • @Override
      • public ScanResult sscan(final byte[] key, final byte[] cursor) {
      • return sscan(key, cursor, new ScanParams());
      • }
      • @Override
      • public ScanResult sscan(final byte[] key, final byte[] cursor, final ScanParams params) {
      • checkIsInMultiOrPipeline();
      • client.sscan(key, cursor, params);
      • List<Object> result = client.getObjectMultiBulkReply();
      • byte[] newcursor = (byte[]) result.get(0);
      • List rawResults = (List) result.get(1);
      • return new ScanResult<>(newcursor, rawResults);
      • }
      • @Override
      • public ScanResult<Tuple> zscan(final byte[] key, final byte[] cursor) {
      • return zscan(key, cursor, new ScanParams());
      • }
      • @Override
      • public ScanResult<Tuple> zscan(final byte[] key, final byte[] cursor, final ScanParams params) {
      • checkIsInMultiOrPipeline();
      • client.zscan(key, cursor, params);
      • List<Object> result = client.getObjectMultiBulkReply();
      • byte[] newcursor = (byte[]) result.get(0);
      • List<Tuple> results = new ArrayList<>();
      • List rawResults = (List) result.get(1);
      • Iterator iterator = rawResults.iterator();
      • while (iterator.hasNext()) {
      • results.add(new Tuple(iterator.next(), BuilderFactory.DOUBLE.build(iterator.next())));
      • }
      • return new ScanResult<>(newcursor, results);
      • }
      • @Override
      • public Long geoadd(final byte[] key, final double longitude, final double latitude, final byte[] member) {
      • checkIsInMultiOrPipeline();
      • client.geoadd(key, longitude, latitude, member);
      • return client.getIntegerReply();
      • }
      • @Override
      • public Long geoadd(final byte[] key, final Map memberCoordinateMap) {
      • checkIsInMultiOrPipeline();
      • client.geoadd(key, memberCoordinateMap);
      • return client.getIntegerReply();
      • }
      • @Override
      • public Double geodist(final byte[] key, final byte[] member1, final byte[] member2) {
      • checkIsInMultiOrPipeline();
      • client.geodist(key, member1, member2);
      • String dval = client.getBulkReply();
      • return (dval != null ? new Double(dval) : null);
      • }
      • @Override
      • public Double geodist(final byte[] key, final byte[] member1, final byte[] member2, final GeoUnit unit) {
      • checkIsInMultiOrPipeline();
      • client.geodist(key, member1, member2, unit);
      • String dval = client.getBulkReply();
      • return (dval != null ? new Double(dval) : null);
      • }
      • @Override
      • public List geohash(final byte[] key, final byte[]... members) {
      • checkIsInMultiOrPipeline();
      • client.geohash(key, members);
      • return client.getBinaryMultiBulkReply();
      • }
      • @Override
      • public List<GeoCoordinate> geopos(final byte[] key, final byte[]... members) {
      • checkIsInMultiOrPipeline();
      • client.geopos(key, members);
      • return BuilderFactory.GEO_COORDINATE_LIST.build(client.getObjectMultiBulkReply());
      • }
      • @Override
      • public List<GeoRadiusResponse> georadius(final byte[] key, final double longitude, final double latitude,
      • final double radius, final GeoUnit unit) {
      • checkIsInMultiOrPipeline();
      • client.georadius(key, longitude, latitude, radius, unit);
      • return BuilderFactory.GEORADIUS_WITH_PARAMS_RESULT.build(client.getObjectMultiBulkReply());
      • }
      • @Override
      • public List<GeoRadiusResponse> georadiusReadonly(final byte[] key, final double longitude, final double latitude,
      • final double radius, final GeoUnit unit) {
      • checkIsInMultiOrPipeline();
      • client.georadiusReadonly(key, longitude, latitude, radius, unit);
      • return BuilderFactory.GEORADIUS_WITH_PARAMS_RESULT.build(client.getObjectMultiBulkReply());
      • }
      • @Override
      • public List<GeoRadiusResponse> georadius(final byte[] key, final double longitude, final double latitude,
      • final double radius, final GeoUnit unit, final GeoRadiusParam param) {
      • checkIsInMultiOrPipeline();
      • client.georadius(key, longitude, latitude, radius, unit, param);
      • return BuilderFactory.GEORADIUS_WITH_PARAMS_RESULT.build(client.getObjectMultiBulkReply());
      • }
      • @Override
      • public List<GeoRadiusResponse> georadiusReadonly(final byte[] key, final double longitude, final double latitude,
      • final double radius, final GeoUnit unit, final GeoRadiusParam param) {
      • checkIsInMultiOrPipeline();
      • client.georadiusReadonly(key, longitude, latitude, radius, unit, param);
      • return BuilderFactory.GEORADIUS_WITH_PARAMS_RESULT.build(client.getObjectMultiBulkReply());
      • }
      • @Override
      • public List<GeoRadiusResponse> georadiusByMember(final byte[] key, final byte[] member, final double radius,
      • final GeoUnit unit) {
      • checkIsInMultiOrPipeline();
      • client.georadiusByMember(key, member, radius, unit);
      • return BuilderFactory.GEORADIUS_WITH_PARAMS_RESULT.build(client.getObjectMultiBulkReply());
      • }
      • @Override
      • public List<GeoRadiusResponse> georadiusByMemberReadonly(final byte[] key, final byte[] member, final double radius,
      • final GeoUnit unit) {
      • checkIsInMultiOrPipeline();
      • client.georadiusByMemberReadonly(key, member, radius, unit);
      • return BuilderFactory.GEORADIUS_WITH_PARAMS_RESULT.build(client.getObjectMultiBulkReply());
      • }
      • @Override
      • public List<GeoRadiusResponse> georadiusByMember(final byte[] key, final byte[] member, final double radius,
      • final GeoUnit unit, final GeoRadiusParam param) {
      • checkIsInMultiOrPipeline();
      • client.georadiusByMember(key, member, radius, unit, param);
      • return BuilderFactory.GEORADIUS_WITH_PARAMS_RESULT.build(client.getObjectMultiBulkReply());
      • }
      • @Override
      • public List<GeoRadiusResponse> georadiusByMemberReadonly(final byte[] key, final byte[] member, final double radius,
      • final GeoUnit unit, final GeoRadiusParam param) {
      • checkIsInMultiOrPipeline();
      • client.georadiusByMemberReadonly(key, member, radius, unit, param);
      • return BuilderFactory.GEORADIUS_WITH_PARAMS_RESULT.build(client.getObjectMultiBulkReply());
      • }
      • /**
      • * A decorator to implement Set from List. Assume that given List do not contains duplicated
      • * values. The resulting set displays the same ordering, concurrency, and performance
      • * characteristics as the backing list. This class should be used only for Redis commands which
      • * return Set result.
      • * @param
      • */
      • protected static class SetFromList extends AbstractSet implements Serializable {
      • private static final long serialVersionUID = -2850347066962734052L;
      • private final List list;
      • private SetFromList(List list) {
      • if (list == null) {
      • throw new NullPointerException("list");
      • }
      • this.list = list;
      • }
      • @Override
      • public void clear() {
      • list.clear();
      • }
      • @Override
      • public int size() {
      • return list.size();
      • }
      • @Override
      • public boolean isEmpty() {
      • return list.isEmpty();
      • }
      • @Override
      • public boolean contains(Object o) {
      • return list.contains(o);
      • }
      • @Override
      • public boolean remove(Object o) {
      • return list.remove(o);
      • }
      • @Override
      • public boolean add(E e) {
      • return !contains(e) && list.add(e);
      • }
      • @Override
      • public Iterator iterator() {
      • return list.iterator();
      • }
      • @Override
      • public Object[] toArray() {
      • return list.toArray();
      • }
      • @Override
      • public T[] toArray(T[] a) {
      • return list.toArray(a);
      • }
      • @Override
      • public String toString() {
      • return list.toString();
      • }
      • @Override
      • public int hashCode() {
      • return list.hashCode();
      • }
      • @Override
      • public boolean equals(Object o) {
      • if (o == null) return false;
      • if (o == this) return true;
      • if (!(o instanceof Set)) return false;
      • Collection c = (Collection) o;
      • if (c.size() != size()) {
      • return false;
      • }
      • return containsAll(c);
      • }
      • @Override
      • public boolean containsAll(Collection c) {
      • return list.containsAll(c);
      • }
      • @Override
      • public boolean removeAll(Collection c) {
      • return list.removeAll(c);
      • }
      • @Override
      • public boolean retainAll(Collection c) {
      • return list.retainAll(c);
      • }
      • protected static SetFromList of(List list) {
      • return new SetFromList<>(list);
      • }
      • }
      • @Override
      • public List<Long> bitfield(final byte[] key, final byte[]... arguments) {
      • checkIsInMultiOrPipeline();
      • client.bitfield(key, arguments);
      • return client.getIntegerMultiBulkReply();
      • }
      • @Override
      • public List<Long> bitfieldReadonly(byte[] key, final byte[]... arguments) {
      • checkIsInMultiOrPipeline();
      • client.bitfieldReadonly(key, arguments);
      • return client.getIntegerMultiBulkReply();
      • }
      • @Override
      • public Long hstrlen(final byte[] key, final byte[] field) {
      • checkIsInMultiOrPipeline();
      • client.hstrlen(key, field);
      • return client.getIntegerReply();
      • }
      • @Override
      • public List xread(int count, long block, Map streams) {
      • checkIsInMultiOrPipeline();
      • client.xread(count, block, streams);
      • client.setTimeoutInfinite();
      • try {
      • return client.getBinaryMultiBulkReply();
      • } finally {
      • client.rollbackTimeout();
      • }
      • }
      • @Override
      • public List xreadGroup(byte[] groupname, byte[] consumer, int count, long block, boolean noAck,
      • Map streams) {
      • checkIsInMultiOrPipeline();
      • client.xreadGroup(groupname, consumer, count, block, noAck, streams);
      • client.setTimeoutInfinite();
      • try {
      • return client.getBinaryMultiBulkReply();
      • } finally {
      • client.rollbackTimeout();
      • }
      • }
      • @Override
      • public byte[] xadd(byte[] key, byte[] id, Map hash, long maxLen, boolean approximateLength) {
      • checkIsInMultiOrPipeline();
      • client.xadd(key, id, hash, maxLen, approximateLength);
      • return client.getBinaryBulkReply();
      • }
      • @Override
      • public Long xlen(byte[] key) {
      • checkIsInMultiOrPipeline();
      • client.xlen(key);
      • return client.getIntegerReply();
      • }
      • @Override
      • public List xrange(byte[] key, byte[] start, byte[] end, long count) {
      • checkIsInMultiOrPipeline();
      • client.xrange(key, start, end, count);
      • return client.getBinaryMultiBulkReply();
      • }
      • @Override
      • public List xrevrange(byte[] key, byte[] end, byte[] start, int count) {
      • checkIsInMultiOrPipeline();
      • client.xrevrange(key, end, start, count);
      • return client.getBinaryMultiBulkReply();
      • }
      • @Override
      • public Long xack(byte[] key, byte[] group, byte[]... ids) {
      • checkIsInMultiOrPipeline();
      • client.xack(key, group, ids);
      • return client.getIntegerReply();
      • }
      • @Override
      • public String xgroupCreate(byte[] key, byte[] consumer, byte[] id, boolean makeStream) {
      • checkIsInMultiOrPipeline();
      • client.xgroupCreate(key, consumer, id, makeStream);
      • return client.getStatusCodeReply();
      • }
      • @Override
      • public String xgroupSetID(byte[] key, byte[] consumer, byte[] id) {
      • checkIsInMultiOrPipeline();
      • client.xgroupSetID(key, consumer, id);
      • return client.getStatusCodeReply();
      • }
      • @Override
      • public Long xgroupDestroy(byte[] key, byte[] consumer) {
      • checkIsInMultiOrPipeline();
      • client.xgroupDestroy(key, consumer);
      • return client.getIntegerReply();
      • }
      • @Override
      • public Long xgroupDelConsumer(byte[] key, byte[] consumer, byte[] consumerName) {
      • checkIsInMultiOrPipeline();
      • client.xgroupDelConsumer(key, consumer, consumerName);
      • return client.getIntegerReply();
      • }
      • @Override
      • public Long xdel(byte[] key, byte[]... ids) {
      • checkIsInMultiOrPipeline();
      • client.xdel(key, ids);
      • return client.getIntegerReply();
      • }
      • @Override
      • public Long xtrim(byte[] key, long maxLen, boolean approximateLength) {
      • checkIsInMultiOrPipeline();
      • client.xtrim(key, maxLen, approximateLength);
      • return client.getIntegerReply();
      • }
      • @Override
      • public List xpending(byte[] key, byte[] groupname, byte[] start, byte[] end, int count, byte[] consumername) {
      • checkIsInMultiOrPipeline();
      • client.xpending(key, groupname, start, end, count, consumername);
      • return client.getBinaryMultiBulkReply(); }
      • @Override
      • public List xclaim(byte[] key, byte[] groupname, byte[] consumername, long minIdleTime, long newIdleTime, int retries, boolean force, byte[][] ids){
      • checkIsInMultiOrPipeline();
      • client.xclaim(key, groupname, consumername, minIdleTime, newIdleTime, retries, force, ids);
      • return client.getBinaryMultiBulkReply();
      • }
      • public Object sendCommand(ProtocolCommand cmd, byte[]... args) {
      • checkIsInMultiOrPipeline();
      • client.sendCommand(cmd, args);
      • return client.getOne();
      • }
      • @Override
      • public StreamInfo xinfoStream(byte[] key) {
      • checkIsInMultiOrPipeline();
      • client.xinfoStream(key);
      • return BuilderFactory.STREAM_INFO.build(client.getOne());
      • }
      • @Override
      • public List<StreamGroupInfo> xinfoGroup (byte[] key) {
      • checkIsInMultiOrPipeline();
      • client.xinfoGroup(key);
      • return BuilderFactory.STREAM_GROUP_INFO_LIST.build(client.getBinaryMultiBulkReply());
      • }
      • @Override
      • public List<StreamConsumersInfo> xinfoConsumers (byte[] key, byte[] group) {
      • checkIsInMultiOrPipeline();
      • client.xinfoConsumers(key,group);
      • return BuilderFactory.STREAM_CONSUMERS_INFO_LIST.build(client.getBinaryMultiBulkReply());
      • }
      • public Object sendCommand(ProtocolCommand cmd) {
      • return sendCommand(cmd, dummyArray);
      • }
      • }
      • 遇到的问题

        连接不上cluster,报错,

        检查  cluster slots  查看redis集群信息,是否展示的是服务器ip,不可以是127.0.0.1

        修改redis集群配置重启,ok

      • 相关阅读:
        【仿真】Carla之收集数据快速教程 (附完整代码) [7]
        欧盟地区 iOS DMA 更新后,Brave浏览器安装量激增
        C++PrimerPlus(第6版)中文版:Chapter16.1.2string类输入
        一次js请求一般情况下有哪些地方会有缓存处理
        2024年中国AI服务器行业发展
        Python基础语法:数据分析利器
        【GIT版本控制】--高级GIT配置
        VUE扫码枪中文输入法兼容自动回车事件
        实验七 Python面向对象程序设计
        SpringBoot注册web组件
      • 原文地址:https://blog.csdn.net/weixin_41796956/article/details/134401381