Xml配置:

  1. <?xml version='1.0' encoding='UTF-8' ?>
  2. <!-- was: <?xml version="1.0" encoding="UTF-8"?> -->
  3. <beans xmlns="http://www.springframework.org/schema/beans"
  4. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
  5. xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
  6. xmlns:context="http://www.springframework.org/schema/context"
  7. xsi:schemaLocation="http://www.springframework.org/schema/beans
  8. http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
  9. http://www.springframework.org/schema/aop
  10. http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
  11. http://www.springframework.org/schema/tx
  12. http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
  13. http://www.springframework.org/schema/context
  14. http://www.springframework.org/schema/context/spring-context-4.0.xsd">
  15. <bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">
  16. <property name="maxIdle" value="50" />
  17. <property name="maxTotal" value="100" />
  18. <property name="maxWaitMillis" value="20000" />
  19. </bean>
  20.  
  21. <bean id="stringRedisSerializer"
  22. class="org.springframework.data.redis.serializer.StringRedisSerializer" />
  23.  
  24. <bean id="connectionFactory"
  25. class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
  26. <property name="hostName" value="localhost" />
  27. <property name="port" value="6379" />
  28. <property name="poolConfig" ref="poolConfig" />
  29. </bean>
  30.  
  31. <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
  32. <property name="connectionFactory" ref="connectionFactory" />
  33. <property name="defaultSerializer" ref="stringRedisSerializer" />
  34. <property name="keySerializer" ref="stringRedisSerializer" />
  35. <property name="valueSerializer" ref="stringRedisSerializer" />
  36. </bean>
  37.  
  38. <bean id="redisMsgListener"
  39. class="com.ssm.chapter19.redis.listener.RedisMessageListener">
  40. <property name="redisTemplate" ref="redisTemplate" />
  41. </bean>
  42.  
  43. <bean id="topicContainer"
  44. class="org.springframework.data.redis.listener.RedisMessageListenerContainer"
  45. destroy-method="destroy">
  46. <!--Redis连接工厂 -->
  47. <property name="connectionFactory" ref="connectionFactory" />
  48. <!--连接池,这里只要线程池生存,才能继续监听 -->
  49. <property name="taskExecutor">
  50. <bean
  51. class="org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler">
  52. <property name="poolSize" value="2" />
  53. </bean>
  54. </property>
  55. <!--消息监听Map -->
  56. <property name="messageListeners">
  57. <map>
  58. <!--配置监听者,key-ref和bean id定义一致 -->
  59. <entry key-ref="redisMsgListener">
  60. <!--监听类 -->
  61. <bean class="org.springframework.data.redis.listener.ChannelTopic">
  62. <constructor-arg value="chat" />
  63. </bean>
  64. </entry>
  65. </map>
  66. </property>
  67. </bean>
  68. </beans>

  监听类:

  1. public class RedisMessageListener implements MessageListener {
  2.  
  3. private RedisTemplate redisTemplate;
  4.  
  5. @Override
  6. public void onMessage(Message message, byte[] bytes) {
  7. // 获取消息
  8. byte[] body = message.getBody();
  9. // 使用值序列化器转换
  10. String msgBody = (String) getRedisTemplate().getValueSerializer().deserialize(body);
  11. System.err.println(msgBody);
  12. // 获取channel
  13. byte[] channel = message.getChannel();
  14. // 使用字符串序列化器转换
  15. String channelStr = (String) getRedisTemplate().getStringSerializer().deserialize(channel);
  16. System.err.println(channelStr);
  17. // 渠道名称转换
  18. String bytesStr = new String(bytes);
  19. System.err.println(bytesStr);
  20. }
  21.  
  22. public RedisTemplate getRedisTemplate() {
  23. return redisTemplate;
  24. }
  25.  
  26. public void setRedisTemplate(RedisTemplate redisTemplate) {
  27. this.redisTemplate = redisTemplate;
  28. }
  29. }

  测试:

  1. public class Chapter19Main {
  2.  
  3. public static void main(String[] args) {
  4. testTransaction();
  5. testPipeline();
  6. testJedisPipeline();
  7. testPubSub();
  8. testExpire();
  9. testLuaScript();
  10. testRedisScript();
  11. testLuaFile();
  12. }
  13.  
  14. public static void testTransaction() {
  15. ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
  16. RedisTemplate redisTemplate = applicationContext.getBean(RedisTemplate.class);
  17. SessionCallback callBack = (SessionCallback) (RedisOperations ops) -> {
  18. ops.multi();
  19. ops.boundValueOps("key1").set("value1");
  20. // 注意由于命令只是进入队列,而没有被执行,所以此处采用get命令,而value却返回为null
  21. String value = (String) ops.boundValueOps("key1").get();
  22. System.out.println("事务执行过程中,命令入队列,而没有被执行,所以value为空:value=" + value);
  23. // 此时list会保存之前进入队列的所有命令的结果
  24. List list = ops.exec();// 执行事务
  25. // 事务结束后,获取value1
  26. value = (String) redisTemplate.opsForValue().get("key1");
  27. return value;
  28. };
  29. // 执行Redis的命令
  30. String value = (String) redisTemplate.execute(callBack);
  31. System.out.println(value);
  32. }
        public static void testPipeline() {
  1. ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
  2. RedisTemplate redisTemplate = applicationContext.getBean(RedisTemplate.class);
  3. // 使用Java8的Lambda表达式
  4. SessionCallback callBack = (SessionCallback) (RedisOperations ops) -> {
  5. for (int i = 0; i < 100; i++) {
  6. int j = i + 1;
  7. ops.boundValueOps("pipeline_key_" + j).set("pipeline_value_" + j);
  8. ops.boundValueOps("pipeline_key_" + j).get();
  9. }
  10. return null;
  11. };
  12. long start = System.currentTimeMillis();
  13. // 执行Redis的流水线命令
  14. List resultList = redisTemplate.executePipelined(callBack);
  15. long end = System.currentTimeMillis();
  16. System.err.println(end - start);
  17. }
  18. private static JedisPool getPool() {
  19. JedisPoolConfig poolCfg = new JedisPoolConfig();
  20. // 最大空闲数
  21. poolCfg.setMaxIdle(50);
  22. // 最大连接数
  23. poolCfg.setMaxTotal(100);
  24. // 最大等待毫秒数
  25. poolCfg.setMaxWaitMillis(20000);
  26. // 使用配置创建连接池
  27. JedisPool pool = new JedisPool(poolCfg, "localhost");
  28. // 从连接池中获取单个连接
  29. Jedis jedis = pool.getResource();
  30. // 如果需密码
  31. // jedis.auth("password");
  32. return pool;
  33. }
  34. public static void testJedisPipeline() {
  35. JedisPool pool = getPool();
  36. Jedis jedis = pool.getResource();
  37. long start = System.currentTimeMillis();
  38. // 开启流水线
  39. Pipeline pipeline = jedis.pipelined();
  40. // 这里测试10万条的读写2个操作
  41. for (int i = 0; i < 100; i++) {
  42. int j = i + 1;
  43. pipeline.set("pipeline_key_" + j, "pipeline_value_" + j);
  44. pipeline.get("pipeline_key_" + j);
  45. }
  46. // pipeline.sync();//这里只执行同步,但是不返回结果
  47. // pipeline.syncAndReturnAll();将返回执行过的命令返回的List列表结果
  48. List result = pipeline.syncAndReturnAll();
  49. long end = System.currentTimeMillis();
  50. // 计算耗时
  51. System.err.println("耗时:" + (end - start) + "毫秒");
  52. }
  53. public static void testPubSub() {
  54. ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
  55. RedisTemplate redisTemplate = applicationContext.getBean(RedisTemplate.class);
  56. String channel = "chat";
  57. redisTemplate.convertAndSend(channel, "I am lazy!!");
  58. }
  59. public static void testExpire() {
  60. ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
  61. RedisTemplate redisTemplate = applicationContext.getBean(RedisTemplate.class);
  62. redisTemplate.execute((RedisOperations ops) -> {
  63. ops.boundValueOps("key1").set("value1");
  64. String keyValue = (String) ops.boundValueOps("key1").get();
  65. Long expSecond = ops.getExpire("key1");
  66. System.err.println(expSecond);
  67. boolean b = false;
  68. b = ops.expire("key1", 120L, TimeUnit.SECONDS);
  69. b = ops.persist("key1");
  70. Long l = 0L;
  71. l = ops.getExpire("key1");
  72. Long now = System.currentTimeMillis();
  73. Date date = new Date();
  74. date.setTime(now + 120000);
  75. ops.expireAt("key", date);
  76. return null;
  77. });
  78. }
  79. public static void testLuaScript() {
  80. // 如果是简单的对象,使用原来的封装会简易些
  81. ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
  82. RedisTemplate redisTemplate = applicationContext.getBean(RedisTemplate.class);
  83. // 如果是简单的操作,使用原来的Jedis会简易些
  84. Jedis jedis = (Jedis) redisTemplate.getConnectionFactory().getConnection().getNativeConnection();
  85. // 执行简单的脚本
  86. String helloJava = (String) jedis.eval("return 'hello java'");
  87. System.out.println(helloJava);
  88. // 执行带参数的脚本
  89. jedis.eval("redis.call('set',KEYS[1], ARGV[1])", 1, "lua-key", "lua-value");
  90. String luaKey = (String) jedis.get("lua-key");
  91. System.out.println(luaKey);
  92. // 缓存脚本,返回sha1签名标识
  93. String sha1 = jedis.scriptLoad("redis.call('set',KEYS[1], ARGV[1])");
  94. // 通过标识执行脚本
  95. jedis.evalsha(sha1, 1, new String[] { "sha-key", "sha-val" });
  96. // 获取执行脚本后的数据
  97. String shaVal = jedis.get("sha-key");
  98. System.out.println(shaVal);
  99. // 关闭连接
  100. jedis.close();
  101. }
  102. public static void testRedisScript() {
  103. ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
  104. RedisTemplate redisTemplate = applicationContext.getBean(RedisTemplate.class);
  105. // 定义默认脚本封装类
  106. DefaultRedisScript<Role> redisScript = new DefaultRedisScript<Role>();
  107. // 设置脚本
  108. redisScript.setScriptText("redis.call('set', KEYS[1], ARGV[1]) return redis.call('get', KEYS[1])");
  109. // 定义操作的key列表
  110. List<String> keyList = new ArrayList<String>();
  111. keyList.add("role1");
  112. // 需要序列化保存和读取的对象
  113. Role role = new Role();
  114. role.setId(1L);
  115. role.setRoleName("role_name_1");
  116. role.setNote("note_1");
  117. // 获得标识字符串
  118. String sha1 = redisScript.getSha1();
  119. System.out.println(sha1);
  120. // 设置返回结果类型,如果没有这句话,结果返回为空
  121. redisScript.setResultType(Role.class);
  122. // 定义序列化器
  123. JdkSerializationRedisSerializer serializer = new JdkSerializationRedisSerializer();
  124. // 执行脚本
  125. // 第一个是RedisScript接口对象,第二个是参数序列化器
  126. // 第三个是结果序列化器,第四个是Reids的key列表,最后是参数列表
  127. Role obj = (Role) redisTemplate.execute(redisScript, serializer, serializer, keyList, role);
  128. // 打印结果
  129. System.out.println(obj);
  130. }
  131. public static void testLuaFile() {
  132. ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
  133. RedisTemplate redisTemplate = applicationContext.getBean(RedisTemplate.class);
  134. // 读入文件流
  135. File file = new File("E:\\study_fold\\Java_EE_SSM\\ssm\\Chapter19\\src\\test.lua");
  136. byte[] bytes = getFileToByte(file);
  137. Jedis jedis = (Jedis) redisTemplate.getConnectionFactory().getConnection().getNativeConnection();
  138. // 发送文件二进制给Redis,这样REdis就会返回sha1标识
  139. byte[] sha1 = jedis.scriptLoad(bytes);
  140. // 使用返回的标识执行,其中第二个参数2,表示使用2个键
  141. // 而后面的字符串都转化为了二进制字节进行传输
  142. Object obj = jedis.evalsha(sha1, 2, "key1".getBytes(), "key2".getBytes(), "2".getBytes(), "4".getBytes());
  143. System.out.println(obj);
  144. }
  145. /**
  146. * 把文件转化为二进制数组
  147. *
  148. * @param file
  149. * 文件
  150. * @return 二进制数组
  151. */
  152. public static byte[] getFileToByte(File file) {
  153. byte[] by = new byte[(int) file.length()];
  154. try {
  155. InputStream is = new FileInputStream(file);
  156. ByteArrayOutputStream bytestream = new ByteArrayOutputStream();
  157. byte[] bb = new byte[2048];
  158. int ch;
  159. ch = is.read(bb);
  160. while (ch != -1) {
  161. bytestream.write(bb, 0, ch);
  162. ch = is.read(bb);
  163. }
  164. by = bytestream.toByteArray();
  165. } catch (Exception ex) {
  166. ex.printStackTrace();
  167. }
  168. return by;
  169. }
  170. }

  输出:

事务执行过程中,命令入队列,而没有被执行,所以value为空:value=null
value1

23

耗时:13毫秒

I am lazy!!
chat
chat
I am lazy!!
chat
chat
I am lazy!!
chat
chat

-1

hello java
lua-value
sha-val

731429de653665577edb661a6741c4083e103b77
com.ssm.chapter19.redis.pojo.Role@59474f18

2

对于高并发的需求,可以用主从同步同步,结合哨兵模式解决,参考:

https://blog.csdn.net/shenlf_bk/article/details/79095469

https://www.cnblogs.com/leirayen/p/8183111.html

Redis常用技术的更多相关文章

  1. Linux+Redis实战教程_day02_3、redis数据类型_4、String命令_5、hash命令_6、java操作redis数据库技术

    3. redis数据类型[重点] redis 使用的是键值对保存数据.(map) key:全部都是字符串 value:有五种数据类型 Key名:自定义,key名不要过长,否则影响使用效率 Key名不要 ...

  2. Redis常用命令

    Redis常用命令Redis提供了丰富的命令对数据库和各种数据类型进行操作,这些命令可以再Linux终端使用.1.键值相关命令2.服务器相关命令 一.键值相关命令 1.get get 键值 当 key ...

  3. 第2讲 Redis常用命令与高级应用

    目录 一.redis数据类型 5. sorted sets类型和操作 二.Redis常用命令 1.键值相关命令 2.服务器相关命令 三. redis高级应用 1. 给redis服务器设置密码 2.持久 ...

  4. Android无线开发的几种常用技术(阿里巴巴资深工程师原创分享)

    完整的开发一个android移动App需要经过从分解需求.架构设计到开发调试.测试.上线发布等多个阶段,在发布后还会有产品功能上的迭代演进,此外还会面对性能.安全.无线网络质量等多方面的问题. 移动A ...

  5. Redis常用数据类型介绍、使用场景及其操作命令

    Redis常用数据类型介绍.使用场景及其操作命令 本文章同时也在cpper.info发布. Redis目前支持5种数据类型,分别是: 1.String(字符串) 2.List(列表) 3.Hash(字 ...

  6. React.js 常用技术要点

    最近在公司的一个移动端WEB产品中使用了React这个框架(并不是React-Native),记录一下在开发过程中遇到的各种问题以及对应的解决方法,希望能对读者有所帮助. React原则 React不 ...

  7. Redis中7种集合类型应用场景&redis常用命令

    Redis常用数据类型 Redis最为常用的数据类型主要有以下五种: String Hash List Set Sorted set 在具体描述这几种数据类型之前,我们先通过一张图了解下Redis内部 ...

  8. Redis 管道技术

    Redis是一种基于客户端-服务端模型以及请求/响应协议的TCP服务.这意味着通常情况下一个请求会遵循以下步骤: 客户端向服务端发送一个查询请求,并监听Socket返回,通常是以阻塞模式,等待服务端响 ...

  9. Redis常用命令手册:服务器相关命令

    Redis提供了丰富的命令(command)对数据库和各种数据类型进行操作,这些command可以在Linux终端使用.在编程时,比如各类语言包,这些命令都有对应的方法.下面将Redis提供的命令做一 ...

随机推荐

  1. YsoSerial 工具常用Payload分析之URLDNS

    本文假设你对Java基本数据结构.Java反序列化.高级特性(反射.动态代理)等有一定的了解. 背景 YsoSerial是一款反序列化利用的便捷工具,可以很方便的生成基于多种环境的反序列化EXP.ja ...

  2. PO封装设计模式 -- App移动端测试

    前言: 一.App_Po 封装 (用互联网上随便一个app进行) base 存放的是页面基础类,后续的类需继承基础类 common 存放的是公共部分,测试固件分离部分,新增截图功能部分 Data 存放 ...

  3. JavaScript学习之路(个人理解&经验):构造函数、类、实例

    构造函数: 声明:"构造函数"是一类函数的 "名字" 正确的读法是"构造函数"而不是"构造 / 函数" 构造函数形如普通 ...

  4. Mysql数据量较大时分页查询优化

    据表 collect ( id, title ,info ,vtype) 就这4个字段,其中 title 用定长,info 用text, id 是主键,vtype是int,vtype是索引. 最后co ...

  5. .net 5+ 知新:【2】 .Net Framework 、.Net 、 .NET Standard的概念与区别

    作为了解历史和眼睛或者过程,我们需要将 .Net Framwork ..Net. .Net Stander几个概念进行下理解. .net 代表跨平台框架,从.net 5开始就统一叫.net,废弃原来的 ...

  6. NPM 所有的指令已经问题 使用淘宝镜像 出现code EAI_AGAIN

    windows怎么卸载cnpm? npm uninstall cnpm -g windows怎么检测cnpm是否安装成功 cnpm -v 我们直接将node的仓库地址换成淘宝仓库地址即可 单次使用 n ...

  7. 🔥 LeetCode 热题 HOT 100(11-20)

    20. 有效的括号 class Solution { public boolean isValid(String s) { Map<Character, Character> map = ...

  8. 利用 cgroup 的 cpuset 控制器限制进程的 CPU 使用

    最近在做一些性能测试的事情,首要前提是控制住 CPU 的使用量.最直观的方法无疑是安装 Docker,在每个配置了参数的容器里运行基准程序. 对于计算密集型任务,在只限制 CPU 的需求下,直接用 L ...

  9. 配置多个git用的ssh key

    参考 http://www.sail.name/2018/12/16/ssh-config-of-mac/ 有一点注意 Host 的名字和 HostName改为一致. 因为从git仓库复制的地址是全程 ...

  10. fastbin attack学习小结

    fastbin attack学习小结   之前留在本地的一篇笔记,复习一下. 下面以glibc2.23为例,说明fastbin管理动态内存的细节.先看一下释放内存的管理: if ((unsigned  ...