Redis学习笔记(五)jedis(JedisCluster)操作Redis集群 redis-cluster

超、凢脫俗 2022-07-13 02:20 1742阅读 0赞

redis系列文章目录

  • 使用spring-data-redis实现incr自增
  • Redis 利用Hash存储节约内存
  • Redis学习笔记(九)redis实现时时直播列表缓存,支持分页[热点数据存储]
  • Redis学习笔记(八)redis之lua脚本学习
  • Redis学习笔记(七)jedis超时重试机制注意事项
  • Redis学习笔记(六)redis实现分布式锁
  • Redis学习笔记(五)jedis(JedisCluster)操作Redis集群 redis-cluster
  • redis学习笔记(四)缓存与数据库一致性问题
  • redis学习笔记(三)数据淘汰策略
  • redis学习笔记(二)JedisCluster + redis 3.2.5集群
  • redis学习笔记(一)redis3.2.5集群安装与测试

版本说明
jedis2.9.0
redis3.2.5

参考资料:redis命令参考。 不过这个稍微有一点点老

java(JedisCluster)操作redis集群

这里只是几个简单的demo,直接上代码吧,没啥好说的

  1. import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
  2. import org.junit.After;
  3. import org.junit.Before;
  4. import org.junit.Test;
  5. import redis.clients.jedis.*;
  6. import java.io.IOException;
  7. import java.util.*;
  8. import java.util.concurrent.*;
  9. import java.util.concurrent.atomic.AtomicInteger;
  10. /** * Created by liubenlong on 2016/12/20. */
  11. public class RedisTest {
  12. JedisCluster jedisCluster = null;
  13. static String prefix = "luffi:lbl";
  14. static String KEY_SPLIT = ":"; //用于隔开缓存前缀与缓存键值
  15. String nameKey = prefix + KEY_SPLIT + "name";
  16. /** * 因为是测试,这里没有写单例 */
  17. @Before
  18. public void before(){
  19. String[] serverArray = "redis集群地址".split(",");
  20. Set<HostAndPort> nodes = new HashSet<>();
  21. for (String ipPort : serverArray) {
  22. String[] ipPortPair = ipPort.split(":");
  23. nodes.add(new HostAndPort(ipPortPair[0].trim(), Integer.valueOf(ipPortPair[1].trim())));
  24. }
  25. //注意:这里超时时间不要太短,他会有超时重试机制。而且其他像httpclient、dubbo等RPC框架也要注意这点
  26. jedisCluster = new JedisCluster(nodes, 1000, 1000, 1, "redis集群密码", new GenericObjectPoolConfig());
  27. // 大多数测试都是使用【nameKey】测试的,所以在启动之前先把这个key删掉
  28. jedisCluster.del(nameKey);
  29. }
  30. /** * 发布 */
  31. @Test
  32. public void publish(){
  33. System.out.println(jedisCluster.publish("channel1", "ss"));
  34. }
  35. /** * 订阅 */
  36. @Test
  37. public void psubscribe(){
  38. // jedisCluster.psubscribe(new JedisPubSubListener(), "channel1");//带通配符
  39. jedisCluster.subscribe(new JedisPubSubListener(), "channel1");
  40. }
  41. /** * 简单字符串读写 */
  42. @Test
  43. public void setStringData(){
  44. System.out.println(jedisCluster.set(nameKey, "张三"));
  45. System.out.println(jedisCluster.get(nameKey));
  46. }
  47. /** * setnx : 如果key存在,返回0,如果不存在,则设置成功。 * setnx的意思是set if not exist. */
  48. @Test
  49. public void setnxTest(){
  50. System.out.println(jedisCluster.setnx(nameKey, "张三"));//key不存在,返回值为1
  51. System.out.println(jedisCluster.get(nameKey));
  52. System.out.println(jedisCluster.setnx(nameKey, "张三"));//已经存在,返回值为0
  53. System.out.println(jedisCluster.get(nameKey));
  54. }
  55. /** * 简单字符串读写,带过期时间 */
  56. @Test
  57. public void setexTest() throws InterruptedException {
  58. System.out.println(jedisCluster.setex(nameKey, 3, "张三"));//时间单位是秒
  59. for(int i = 0 ; i < 5 ; i ++){
  60. System.out.println(jedisCluster.get(nameKey));//过期以后redis集群自动删除
  61. Thread.sleep(1000);
  62. }
  63. }
  64. /** * 操作子字符串 */
  65. @Test
  66. public void setrangeTest() throws InterruptedException {
  67. System.out.println(jedisCluster.set(nameKey, "852026881@qq.com"));
  68. System.out.println(jedisCluster.get(nameKey));//结果:852026881@qq.com
  69. //从offset=8开始替换字符串value的值
  70. System.out.println(jedisCluster.setrange(nameKey, 8, "abc"));//结果:85202688abcq.com
  71. System.out.println(jedisCluster.get(nameKey));
  72. System.out.println(jedisCluster.setrange(nameKey, 8, "abcdefghhhhhh"));//结果:85202688abcdefghhhhhh
  73. System.out.println(jedisCluster.get(nameKey));
  74. //查询子串,返回startOffset到endOffset的字符
  75. System.out.println(jedisCluster.getrange(nameKey, 2, 5));//结果:2026
  76. }
  77. /** * 批量操作key * keySlot算法中,如果key包含{},就会使用第一个{}内部的字符串作为hash key,这样就可以保证拥有同样{}内部字符串的key就会拥有相同slot。 * 参考 http://brandnewuser.iteye.com/blog/2314280 * redis.clients.util.JedisClusterCRC16#getSlot(java.lang.String) * * 注意:这样的话,本来可以hash到不同的slot中的数据都放到了同一个slot中,所以使用的时候要注意数据不要太多导致一个slot数据量过大,数据分布不均匀! * * MSET 是一个原子性(atomic)操作,所有给定 key 都会在同一时间内被设置,某些给定 key 被更新而另一些给定 key 没有改变的情况,不可能发生。 */
  78. @Test
  79. public void msetTest() throws InterruptedException {
  80. /** * jedisCluster.mset("sf","d","aadf","as"); * 直接这样写,会报错:redis.clients.jedis.exceptions.JedisClusterException: No way to dispatch this command to Redis Cluster because keys have different slots. * 这是因为key不在同一个slot中 */
  81. String result = jedisCluster.mset("{" + prefix + KEY_SPLIT + "}" + "name", "张三", "{" + prefix + KEY_SPLIT + "}" + "age", "23", "{" + prefix + KEY_SPLIT + "}" + "address", "adfsa", "{" + prefix + KEY_SPLIT + "}" + "score", "100");
  82. System.out.println(result);
  83. String name = jedisCluster.get("{" + prefix + KEY_SPLIT + "}" + "name");
  84. System.out.println(name);
  85. Long del = jedisCluster.del("{" + prefix + KEY_SPLIT + "}" + "age");
  86. System.out.println(del);
  87. List<String> values = jedisCluster.mget("{" + prefix + KEY_SPLIT + "}" + "name", "{" + prefix + KEY_SPLIT + "}" + "age", "{" + prefix + KEY_SPLIT + "}" + "address");
  88. System.out.println(values);
  89. }
  90. /** * MSETNX 命令:它只会在所有给定 key 都不存在的情况下进行设置操作。 * http://doc.redisfans.com/string/mset.html */
  91. @Test
  92. public void msetnxTest() throws InterruptedException {
  93. Long msetnx = jedisCluster.msetnx(
  94. "{" + prefix + KEY_SPLIT + "}" + "name", "张三",
  95. "{" + prefix + KEY_SPLIT + "}" + "age", "23",
  96. "{" + prefix + KEY_SPLIT + "}" + "address", "adfsa",
  97. "{" + prefix + KEY_SPLIT + "}" + "score", "100");
  98. System.out.println(msetnx);
  99. System.out.println(jedisCluster.mget(
  100. "{" + prefix + KEY_SPLIT + "}" + "name",
  101. "{" + prefix + KEY_SPLIT + "}" + "age",
  102. "{" + prefix + KEY_SPLIT + "}" + "address",
  103. "{" + prefix + KEY_SPLIT + "}" + "score"));//[张三, 23, adfsa, 100]
  104. //name这个key已经存在,由于mset是原子的,该条指令将全部失败
  105. msetnx = jedisCluster.msetnx(
  106. "{" + prefix + KEY_SPLIT + "}" + "phone", "110",
  107. "{" + prefix + KEY_SPLIT + "}" + "name", "张三",
  108. "{" + prefix + KEY_SPLIT + "}" + "abc", "asdfasfdsa");
  109. System.out.println(msetnx);
  110. System.out.println(jedisCluster.mget(
  111. "{" + prefix + KEY_SPLIT + "}" + "name",
  112. "{" + prefix + KEY_SPLIT + "}" + "age",
  113. "{" + prefix + KEY_SPLIT + "}" + "address",
  114. "{" + prefix + KEY_SPLIT + "}" + "score",
  115. "{" + prefix + KEY_SPLIT + "}" + "phone",
  116. "{" + prefix + KEY_SPLIT + "}" + "abc"));//[张三, 23, adfsa, 100, null, null]
  117. }
  118. /** * getset:设置key值,并返回旧值 */
  119. @Test
  120. public void getsetTest() throws InterruptedException {
  121. System.out.println(jedisCluster.set(nameKey, "zhangsan"));
  122. System.out.println(jedisCluster.get(nameKey));
  123. System.out.println(jedisCluster.getSet(nameKey, "lisi"));
  124. System.out.println(jedisCluster.get(nameKey));
  125. }
  126. /** * append: 追加. 其返回值是追加后数据的长度 */
  127. @Test
  128. public void appendTest() throws InterruptedException {
  129. System.out.println(jedisCluster.append(nameKey, "aa"));
  130. System.out.println(jedisCluster.get(nameKey));
  131. System.out.println(jedisCluster.append(nameKey, "lisi"));
  132. System.out.println(jedisCluster.get(nameKey));
  133. }
  134. /** * incrf: * 将 key 中储存的数字值增一。 如果 key 不存在,那么 key 的值会先被初始化为 0 ,然后再执行 INCR 操作。 如果值包含错误的类型,或字符串类型的值不能表示为数字,那么返回一个错误。 本操作的值限制在 64 位(bit)有符号数字表示之内。 这是一个针对字符串的操作,因为 Redis 没有专用的整数类型,所以 key 内储存的字符串被解释为十进制 64 位有符号整数来执行 INCR 操作。 返回值: 执行 INCR 命令之后 key 的值。 这里有问题,最终数据结果大于10000 后续在研究 TODO 这是因为设置的超时时间太小了,他去重试了,所以最终结果大于10000 */
  135. @Test
  136. public void incrTest() throws InterruptedException {
  137. /** * 测试线程安全 */
  138. jedisCluster.del("incrNum");
  139. final AtomicInteger atomicInteger = new AtomicInteger(0);
  140. final CountDownLatch countDownLatch = new CountDownLatch(10);
  141. ExecutorService executorService = Executors.newFixedThreadPool(10);
  142. for(int i = 0 ; i < 10 ; i ++){
  143. executorService.submit(new Runnable() {
  144. @Override
  145. public void run() {
  146. //每个线程增加1000次,每次加1
  147. for(int j = 0 ; j < 1000 ; j ++){
  148. atomicInteger.incrementAndGet();
  149. jedisCluster.incr("incrNum");
  150. }
  151. countDownLatch.countDown();
  152. }
  153. });
  154. }
  155. countDownLatch.await();
  156. System.out.println(jedisCluster.get("incrNum"));
  157. System.out.println(atomicInteger);
  158. }
  159. /** * * @throws InterruptedException */
  160. @Test
  161. public void hashTest() throws InterruptedException {
  162. String hashKey = "hashKey";
  163. jedisCluster.del(hashKey);
  164. System.out.println(jedisCluster.hset(hashKey, "program_zhangsan", "111"));
  165. System.out.println(jedisCluster.hexists(hashKey, "program_zhangsan"));
  166. System.out.println(jedisCluster.hset(hashKey, "program_zhangsan", "222"));
  167. System.out.println(jedisCluster.hset(hashKey, "program_wangwu", "333"));
  168. System.out.println(jedisCluster.hset(hashKey, "program_lisi", "444"));
  169. System.out.println("hkeys:" + jedisCluster.hkeys(hashKey));
  170. System.out.println(jedisCluster.hgetAll(hashKey));
  171. System.out.println(jedisCluster.hincrBy(hashKey, "program_zhangsan", 2));
  172. System.out.println(jedisCluster.hmget(hashKey, "program_zhangsan", "program_lisi"));
  173. jedisCluster.hdel(hashKey, "program_wangwu");
  174. System.out.println(jedisCluster.hgetAll(hashKey));
  175. System.out.println("hsetnx:" + jedisCluster.hsetnx(hashKey, "program_lisi", "666"));
  176. System.out.println("hvals:" + jedisCluster.hvals(hashKey));
  177. System.out.println("expire:" + jedisCluster.expire(hashKey, 3));
  178. for(int i = 0 ; i < 5 ; i ++){
  179. System.out.println(jedisCluster.hgetAll(hashKey));
  180. Thread.sleep(1000);
  181. }
  182. }
  183. /** * 模拟先进先出队列 * 生产者 消费者 */
  184. @Test
  185. public void queue() throws InterruptedException {
  186. String key = prefix + KEY_SPLIT + "queue";
  187. jedisCluster.del(key);
  188. System.out.println(jedisCluster.lpush(key, "1", "2", "3"));
  189. System.out.println(jedisCluster.lpush(key, "4"));
  190. System.out.println(jedisCluster.lpush(key, "5"));
  191. System.out.println("lrange:" + jedisCluster.lrange(key, 0, -1));
  192. System.out.println("lindex[2]:" + jedisCluster.lindex(key, 2));
  193. //在“3”的前面插入“100”
  194. System.out.println("linsert:" + jedisCluster.linsert(key, Client.LIST_POSITION.BEFORE, "3", "100"));
  195. System.out.println("lrange:" + jedisCluster.lrange(key, 0, -1));
  196. //写进去的顺序是12345,读取出来的也是12345
  197. for(int i = 0 ; i< 6 ; i ++){
  198. System.out.println(jedisCluster.rpop(key));
  199. }
  200. // 如果想达到生产者消费者那种模式需要使用阻塞式队列才可。这个另外写多个客户端测试。
  201. }
  202. /** * Set集合 */
  203. @Test
  204. public void setTest() throws InterruptedException {
  205. String keyA = "{" + prefix + KEY_SPLIT + "set}a";
  206. String keyB = "{" + prefix + KEY_SPLIT + "set}b";
  207. jedisCluster.del(keyA);
  208. jedisCluster.del(keyB);
  209. System.out.println(jedisCluster.sadd(keyA, "a", "b", "c"));//给集合添加数据
  210. System.out.println(jedisCluster.sadd(keyA, "a"));//给集合添加数据.集合是不可以重复的
  211. System.out.println(jedisCluster.sadd(keyA, "d"));//给集合添加数据
  212. System.out.println(jedisCluster.smembers(keyA));//返回集合所有数据
  213. System.out.println(jedisCluster.scard(keyA));//返回集合长度
  214. System.out.println("c是否在集合A中:" + jedisCluster.sismember(keyA, "c"));//判断 member 元素是否集合 key 的成员。
  215. /* 从 Redis 2.6 版本开始, SRANDMEMBER 命令接受可选的 count 参数: 如果 count 为正数,且小于集合基数,那么命令返回一个包含 count 个元素的数组,数组中的元素各不相同。如果 count 大于等于集合基数,那么返回整个集合。 如果 count 为负数,那么命令返回一个数组,数组中的元素可能会重复出现多次,而数组的长度为 count 的绝对值。 */
  216. System.out.println(jedisCluster.srandmember(keyA));//返回集合中的一个随机元素。
  217. System.out.println(jedisCluster.spop(keyA)); //移除并返回集合中的一个随机元素。
  218. System.out.println(jedisCluster.smembers(keyA));//返回集合所有数据
  219. System.out.println("---------");
  220. /* SMOVE 是原子性操作。 如果 source 集合不存在或不包含指定的 member 元素,则 SMOVE 命令不执行任何操作,仅返回 0 。否则, member 元素从 source 集合中被移除,并添加到 destination 集合中去。 当 destination 集合已经包含 member 元素时, SMOVE 命令只是简单地将 source 集合中的 member 元素删除。 当 source 或 destination 不是集合类型时,返回一个错误。 注:不可以在redis-cluster中使用SMOVE:redis.clients.jedis.exceptions.JedisClusterException: No way to dispatch this command to Redis Cluster because keys have different slots. 解决办法可以参考上面的mset命令,使用“{}”来讲可以设置的同一个slot中 */
  221. System.out.println(jedisCluster.smove(keyA, keyB, "a"));//返回集合所有数据
  222. System.out.println("keyA: "+jedisCluster.smembers(keyA));//返回集合所有数据
  223. System.out.println("keyB: "+jedisCluster.smembers(keyB));//返回集合所有数据
  224. System.out.println(jedisCluster.sadd(keyB, "a", "f", "c"));//给集合添加数据
  225. System.out.println(jedisCluster.sdiff(keyA, keyB));//差集 keyA-keyB
  226. System.out.println(jedisCluster.sinter(keyA, keyB));//交集
  227. System.out.println(jedisCluster.sunion(keyA, keyB));//并集
  228. }
  229. /** * sortedSet集合 */
  230. @Test
  231. public void sortedSetTest() throws InterruptedException {
  232. String keyA = "{"+prefix + KEY_SPLIT + "sortedSet}a";
  233. String keyB = "{"+prefix + KEY_SPLIT + "sortedSet}b";
  234. String keyC = "{"+prefix + KEY_SPLIT + "sortedSet}c";
  235. jedisCluster.del(keyA);
  236. jedisCluster.del(keyB);
  237. System.out.println(jedisCluster.zadd(keyA, 10, "aa"));
  238. Map<String, Double> map = new HashMap<>();
  239. map.put("b", 8.0);
  240. map.put("c", 4.0);
  241. map.put("d", 6.0);
  242. System.out.println(jedisCluster.zadd(keyA, map));
  243. System.out.println(jedisCluster.zcard(keyA));//返回有序集 key 的数量。
  244. System.out.println(jedisCluster.zcount(keyA, 3, 8));//返回有序集 key 中score某个范围的数量。
  245. System.out.println("zrange: "+jedisCluster.zrange(keyA, 0, -1));//返回有序集 key 中,指定区间内的成员。按score从小到大
  246. System.out.println("zrevrange: "+jedisCluster.zrevrange(keyA, 0, -1));//返回有序集 key 中,指定区间内的成员。按score从大到小
  247. System.out.println("zrangeWithScores: "+jedisCluster.zrangeWithScores(keyA, 0, -1));//返回有序集 key 中,指定区间内的成员。按score从小到大.包含分值
  248. System.out.println("zscore: "+jedisCluster.zscore(keyA, "aa"));
  249. /* 返回有序集 key 中,所有 score 值介于 min 和 max 之间(包括等于 min 或 max )的成员。有序集成员按 score 值递增(从小到大)次序排列。 具有相同 score 值的成员按字典序(lexicographical order)来排列(该属性是有序集提供的,不需要额外的计算)。 */
  250. System.out.println("zrangeByScore: "+jedisCluster.zrangeByScore(keyA, 3, 8));
  251. System.out.println("zrank: "+jedisCluster.zrank(keyA, "c"));//返回有序集 key 中成员 member 的排名。其中有序集成员按 score 值递增(从小到大)顺序排列。
  252. System.out.println("zrevrank: "+jedisCluster.zrevrank(keyA, "c"));//返回有序集 key 中成员 member 的排名。其中有序集成员按 score 值递增(从大到小)顺序排列。
  253. System.out.println("zrem: "+jedisCluster.zrem(keyA, "c", "a"));//移除有序集 key 中的一个或多个成员,不存在的成员将被忽略。
  254. System.out.println("zrange: "+jedisCluster.zrange(keyA, 0, -1));
  255. System.out.println("zremrangeByRank: "+jedisCluster.zremrangeByRank(keyA, 1, 2));//按下标删除
  256. System.out.println("zrange: "+jedisCluster.zrange(keyA, 0, -1));
  257. System.out.println("zremrangeByScore: "+jedisCluster.zremrangeByScore(keyA, 1, 3));//按评分删除
  258. System.out.println("zrange: "+jedisCluster.zrange(keyA, 0, -1));
  259. /* 接下来这几个操作,需要使用"{}"使得key落到同一个slot中才可以 */
  260. System.out.println("-------");
  261. System.out.println(jedisCluster.zadd(keyB, map));
  262. System.out.println("zrange: "+jedisCluster.zrange(keyB, 0, -1));
  263. /* ZUNIONSTORE destination numkeys key [key ...] [WEIGHTS weight [weight ...]] [AGGREGATE SUM|MIN|MAX] 计算给定的一个或多个有序集的并集,其中给定 key 的数量必须以 numkeys 参数指定,并将该并集(结果集)储存到 destination 。 默认情况下,结果集中某个成员的 score 值是所有给定集下该成员 score 值之 和 。 WEIGHTS 使用 WEIGHTS 选项,你可以为 每个 给定有序集 分别 指定一个乘法因子(multiplication factor),每个给定有序集的所有成员的 score 值在传递给聚合函数(aggregation function)之前都要先乘以该有序集的因子。 如果没有指定 WEIGHTS 选项,乘法因子默认设置为 1 。 AGGREGATE 使用 AGGREGATE 选项,你可以指定并集的结果集的聚合方式。 默认使用的参数 SUM ,可以将所有集合中某个成员的 score 值之 和 作为结果集中该成员的 score 值;使用参数 MIN ,可以将所有集合中某个成员的 最小 score 值作为结果集中该成员的 score 值;而参数 MAX 则是将所有集合中某个成员的 最大 score 值作为结果集中该成员的 score 值。 */
  264. System.out.println("zunionstore: "+jedisCluster.zunionstore(keyC, keyA, keyB));//合并keyA和keyB并保存到keyC中
  265. System.out.println("zrange: "+jedisCluster.zrange(keyC, 0, -1));
  266. System.out.println("zinterstore: "+jedisCluster.zinterstore(keyC, keyA, keyB));//交集
  267. System.out.println("zrange: "+jedisCluster.zrange(keyC, 0, -1));
  268. }
  269. /** * 列表 排序 */
  270. @Test
  271. public void sort() throws InterruptedException {
  272. String key = prefix + KEY_SPLIT + "queue";
  273. jedisCluster.del(key);
  274. System.out.println(jedisCluster.lpush(key, "1", "5", "3", "20", "6"));
  275. System.out.println(jedisCluster.lrange(key, 0, -1));
  276. System.out.println(jedisCluster.sort(key));
  277. System.out.println(jedisCluster.lrange(key, 0, -1));
  278. }
  279. /** * lua脚本 */
  280. @Test
  281. public void script() throws InterruptedException {
  282. /* * 其中 "return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}" 是被求值的 Lua 脚本,数字 2 指定了键名参数的数量, * key1 和 key2 是键名参数,分别使用 KEYS[1] 和 KEYS[2] 访问,而最后的 first 和 second 则是附加参数,可以通过 ARGV[1] 和 ARGV[2] 访问它们。 * * 注意,这里一些操作不适用于redis-cluster,主要还是因为不同的key被分配到了不同的slot中 */
  283. Object eval = jedisCluster.eval("return {KEYS[1],ARGV[1],ARGV[2]}", 1, "lua", "key1", "dd");
  284. System.out.println(eval);
  285. //脚本里使用的所有键都应该由 KEYS 数组来传递:
  286. //因为:所有的 Redis 命令,在执行之前都会被分析,籍此来确定命令会对哪些键进行操作。因此,对于 EVAL 命令来说,必须使用正确的形式来传递键,才能确保分析工作正确地执行
  287. System.out.println(jedisCluster.eval("return redis.call('set', KEYS[1], ARGV[1])", 1, "luaTest", "cv"));
  288. System.out.println(jedisCluster.get("luaTest"));
  289. //注意这里需要指定KEY,因为这里lua脚本也是和slot挂钩的
  290. String scriptLoad = jedisCluster.scriptLoad("return redis.call('get', KEYS[1])", "luaTest");//加载脚本
  291. System.out.println(scriptLoad);//返回的SHA1校验和,后续可以直接使用这个进行操作。
  292. System.out.println(jedisCluster.scriptExists(scriptLoad, "luaTest"));//检查是否存在
  293. System.out.println(jedisCluster.evalsha(scriptLoad, 1, "luaTest"));//执行lua脚本
  294. System.out.println(jedisCluster.scriptFlush("luaTest".getBytes()));//删除KEY as 上的所有lua脚本
  295. System.out.println(jedisCluster.scriptExists(scriptLoad, "luaTest"));
  296. System.out.println(jedisCluster.evalsha(scriptLoad, 1, "luaTest"));//脚本已经删除,返回错误:NOSCRIPT No matching script. Please use EVAL.
  297. }
  298. /** * redis中的lua脚本做了很多限制,防止随机性的发生。比如lua脚本中返回的总是有序的集合。 * 详情见 http://doc.redisfans.com/script/eval.html - 纯函数脚本 */
  299. @Test
  300. public void scriptFuc() throws InterruptedException {
  301. String key = "luaTest";
  302. System.out.println(jedisCluster.del(key));
  303. System.out.println(jedisCluster.sadd(key, "10","3","7","40","6"));
  304. System.out.println(jedisCluster.smembers(key));//这里怎么返回的值是有序的? [3, 6, 7, 10, 40]
  305. System.out.println(jedisCluster.eval("return redis.call('smembers', KEYS[1])", 1, key));//根据字母序排序 [10, 3, 40, 6, 7]
  306. }
  307. /** * 使用lua脚本记录日志 * @throws InterruptedException */
  308. @Test
  309. public void redisLog() throws InterruptedException {
  310. //这里后面必须要有key???
  311. System.out.println(jedisCluster.eval("redis.log(redis.LOG_WARNING, 'Something is wrong with this script.')", 1, "afd"));
  312. }
  313. /** * 模拟先进先出 定长 队列 * 参考 http://www.cnblogs.com/stephen-liu74/archive/2012/02/14/2351859.html * https://www.v2ex.com/t/65663 */
  314. @Test
  315. public void queue1() throws InterruptedException {
  316. String key = prefix + KEY_SPLIT + "queue";
  317. Long del = jedisCluster.del(key);
  318. System.out.println(del);
  319. //我们定义队列长度是5
  320. int length = 5;
  321. System.out.println(jedisCluster.lpush(key, "1", "2", "3", "4", "5", "6", "7"));
  322. List<String> list = jedisCluster.lrange(key, 0, -1);//打印所有数据
  323. System.out.println(list);
  324. Long llen = jedisCluster.llen(key);
  325. System.out.println("目前队列长度:" + llen);
  326. /** * 该命令将仅保留指定范围内的元素 * 每次lpush以后,就用ltrim进行截取,已达到定长队列(或定长list)的目的 * * 注意: * 这里根据实际业务需求,超长了不一定截取丢掉,也可以进行分流限流报警处理或者其他阻塞操作 */
  327. System.out.println(jedisCluster.ltrim(key, 0, length - 1));
  328. System.out.println(jedisCluster.lrange(key, 0, -1));
  329. }
  330. /** * 分布式互斥锁 * 一般是通过 set nx ex 实现的 * 但是这样不完美,具体参考 http://ifeve.com/redis-lock/ */
  331. @Test
  332. public void lock() throws InterruptedException{
  333. String key = prefix + KEY_SPLIT + "lock";
  334. /** * 复合命令: SET KEY VALUE [EX seconds] [PX milliseconds] [NX|XX] */
  335. System.out.println(jedisCluster.set(key, "本机ID", "nx", "ex", 3));
  336. for (int i = 0 ; i < 6 ; i ++) {
  337. System.out.println(jedisCluster.get(key));
  338. Thread.sleep(1000);
  339. }
  340. }
  341. @After
  342. public void after(){
  343. try {
  344. if(jedisCluster != null) jedisCluster.close();
  345. } catch (IOException e) {
  346. e.printStackTrace();
  347. }
  348. }
  349. }

JedisPubSubListener .java

  1. import redis.clients.jedis.JedisPubSub;
  2. public class JedisPubSubListener extends JedisPubSub {
  3. // 取得订阅的消息后的处理
  4. public void onMessage(String channel, String message) {
  5. System.out.println(channel + "=" + message);
  6. }
  7. // 初始化订阅时候的处理
  8. public void onSubscribe(String channel, int subscribedChannels) {
  9. System.out.println(channel + "=" + subscribedChannels);
  10. }
  11. // 取消订阅时候的处理
  12. public void onUnsubscribe(String channel, int subscribedChannels) {
  13. System.out.println(channel + "=" + subscribedChannels);
  14. }
  15. // 初始化按表达式的方式订阅时候的处理
  16. public void onPSubscribe(String pattern, int subscribedChannels) {
  17. System.out.println(pattern + "=" + subscribedChannels);
  18. }
  19. // 取消按表达式的方式订阅时候的处理
  20. public void onPUnsubscribe(String pattern, int subscribedChannels) {
  21. System.out.println(pattern + "=" + subscribedChannels);
  22. }
  23. // 取得按表达式的方式订阅的消息后的处理
  24. public void onPMessage(String pattern, String channel, String message) {
  25. System.out.println(pattern + "=" + channel + "=" + message);
  26. }
  27. }

发表评论

表情:
评论列表 (有 0 条评论,1742人围观)

还没有评论,来说两句吧...

相关阅读