Redis常用技术
Xml配置:
- <?xml version='1.0' encoding='UTF-8' ?>
- <!-- was: <?xml version="1.0" encoding="UTF-8"?> -->
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
- xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
- xmlns:context="http://www.springframework.org/schema/context"
- xsi:schemaLocation="http://www.springframework.org/schema/beans
- http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
- http://www.springframework.org/schema/aop
- http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
- http://www.springframework.org/schema/tx
- http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
- http://www.springframework.org/schema/context
- http://www.springframework.org/schema/context/spring-context-4.0.xsd">
- <bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">
- <property name="maxIdle" value="50" />
- <property name="maxTotal" value="100" />
- <property name="maxWaitMillis" value="20000" />
- </bean>
- <bean id="stringRedisSerializer"
- class="org.springframework.data.redis.serializer.StringRedisSerializer" />
- <bean id="connectionFactory"
- class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
- <property name="hostName" value="localhost" />
- <property name="port" value="6379" />
- <property name="poolConfig" ref="poolConfig" />
- </bean>
- <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
- <property name="connectionFactory" ref="connectionFactory" />
- <property name="defaultSerializer" ref="stringRedisSerializer" />
- <property name="keySerializer" ref="stringRedisSerializer" />
- <property name="valueSerializer" ref="stringRedisSerializer" />
- </bean>
- <bean id="redisMsgListener"
- class="com.ssm.chapter19.redis.listener.RedisMessageListener">
- <property name="redisTemplate" ref="redisTemplate" />
- </bean>
- <bean id="topicContainer"
- class="org.springframework.data.redis.listener.RedisMessageListenerContainer"
- destroy-method="destroy">
- <!--Redis连接工厂 -->
- <property name="connectionFactory" ref="connectionFactory" />
- <!--连接池,这里只要线程池生存,才能继续监听 -->
- <property name="taskExecutor">
- <bean
- class="org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler">
- <property name="poolSize" value="2" />
- </bean>
- </property>
- <!--消息监听Map -->
- <property name="messageListeners">
- <map>
- <!--配置监听者,key-ref和bean id定义一致 -->
- <entry key-ref="redisMsgListener">
- <!--监听类 -->
- <bean class="org.springframework.data.redis.listener.ChannelTopic">
- <constructor-arg value="chat" />
- </bean>
- </entry>
- </map>
- </property>
- </bean>
- </beans>
监听类:
- public class RedisMessageListener implements MessageListener {
- private RedisTemplate redisTemplate;
- @Override
- public void onMessage(Message message, byte[] bytes) {
- // 获取消息
- byte[] body = message.getBody();
- // 使用值序列化器转换
- String msgBody = (String) getRedisTemplate().getValueSerializer().deserialize(body);
- System.err.println(msgBody);
- // 获取channel
- byte[] channel = message.getChannel();
- // 使用字符串序列化器转换
- String channelStr = (String) getRedisTemplate().getStringSerializer().deserialize(channel);
- System.err.println(channelStr);
- // 渠道名称转换
- String bytesStr = new String(bytes);
- System.err.println(bytesStr);
- }
- public RedisTemplate getRedisTemplate() {
- return redisTemplate;
- }
- public void setRedisTemplate(RedisTemplate redisTemplate) {
- this.redisTemplate = redisTemplate;
- }
- }
测试:
- public class Chapter19Main {
- public static void main(String[] args) {
- testTransaction();
- testPipeline();
- testJedisPipeline();
- testPubSub();
- testExpire();
- testLuaScript();
- testRedisScript();
- testLuaFile();
- }
- public static void testTransaction() {
- ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
- RedisTemplate redisTemplate = applicationContext.getBean(RedisTemplate.class);
- SessionCallback callBack = (SessionCallback) (RedisOperations ops) -> {
- ops.multi();
- ops.boundValueOps("key1").set("value1");
- // 注意由于命令只是进入队列,而没有被执行,所以此处采用get命令,而value却返回为null
- String value = (String) ops.boundValueOps("key1").get();
- System.out.println("事务执行过程中,命令入队列,而没有被执行,所以value为空:value=" + value);
- // 此时list会保存之前进入队列的所有命令的结果
- List list = ops.exec();// 执行事务
- // 事务结束后,获取value1
- value = (String) redisTemplate.opsForValue().get("key1");
- return value;
- };
- // 执行Redis的命令
- String value = (String) redisTemplate.execute(callBack);
- System.out.println(value);
- }
public static void testPipeline() {
- ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
- RedisTemplate redisTemplate = applicationContext.getBean(RedisTemplate.class);
- // 使用Java8的Lambda表达式
- SessionCallback callBack = (SessionCallback) (RedisOperations ops) -> {
- for (int i = 0; i < 100; i++) {
- int j = i + 1;
- ops.boundValueOps("pipeline_key_" + j).set("pipeline_value_" + j);
- ops.boundValueOps("pipeline_key_" + j).get();
- }
- return null;
- };
- long start = System.currentTimeMillis();
- // 执行Redis的流水线命令
- List resultList = redisTemplate.executePipelined(callBack);
- long end = System.currentTimeMillis();
- System.err.println(end - start);
- }
- private static JedisPool getPool() {
- JedisPoolConfig poolCfg = new JedisPoolConfig();
- // 最大空闲数
- poolCfg.setMaxIdle(50);
- // 最大连接数
- poolCfg.setMaxTotal(100);
- // 最大等待毫秒数
- poolCfg.setMaxWaitMillis(20000);
- // 使用配置创建连接池
- JedisPool pool = new JedisPool(poolCfg, "localhost");
- // 从连接池中获取单个连接
- Jedis jedis = pool.getResource();
- // 如果需密码
- // jedis.auth("password");
- return pool;
- }
- public static void testJedisPipeline() {
- JedisPool pool = getPool();
- Jedis jedis = pool.getResource();
- long start = System.currentTimeMillis();
- // 开启流水线
- Pipeline pipeline = jedis.pipelined();
- // 这里测试10万条的读写2个操作
- for (int i = 0; i < 100; i++) {
- int j = i + 1;
- pipeline.set("pipeline_key_" + j, "pipeline_value_" + j);
- pipeline.get("pipeline_key_" + j);
- }
- // pipeline.sync();//这里只执行同步,但是不返回结果
- // pipeline.syncAndReturnAll();将返回执行过的命令返回的List列表结果
- List result = pipeline.syncAndReturnAll();
- long end = System.currentTimeMillis();
- // 计算耗时
- System.err.println("耗时:" + (end - start) + "毫秒");
- }
- public static void testPubSub() {
- ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
- RedisTemplate redisTemplate = applicationContext.getBean(RedisTemplate.class);
- String channel = "chat";
- redisTemplate.convertAndSend(channel, "I am lazy!!");
- }
- public static void testExpire() {
- ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
- RedisTemplate redisTemplate = applicationContext.getBean(RedisTemplate.class);
- redisTemplate.execute((RedisOperations ops) -> {
- ops.boundValueOps("key1").set("value1");
- String keyValue = (String) ops.boundValueOps("key1").get();
- Long expSecond = ops.getExpire("key1");
- System.err.println(expSecond);
- boolean b = false;
- b = ops.expire("key1", 120L, TimeUnit.SECONDS);
- b = ops.persist("key1");
- Long l = 0L;
- l = ops.getExpire("key1");
- Long now = System.currentTimeMillis();
- Date date = new Date();
- date.setTime(now + 120000);
- ops.expireAt("key", date);
- return null;
- });
- }
- public static void testLuaScript() {
- // 如果是简单的对象,使用原来的封装会简易些
- ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
- RedisTemplate redisTemplate = applicationContext.getBean(RedisTemplate.class);
- // 如果是简单的操作,使用原来的Jedis会简易些
- Jedis jedis = (Jedis) redisTemplate.getConnectionFactory().getConnection().getNativeConnection();
- // 执行简单的脚本
- String helloJava = (String) jedis.eval("return 'hello java'");
- System.out.println(helloJava);
- // 执行带参数的脚本
- jedis.eval("redis.call('set',KEYS[1], ARGV[1])", 1, "lua-key", "lua-value");
- String luaKey = (String) jedis.get("lua-key");
- System.out.println(luaKey);
- // 缓存脚本,返回sha1签名标识
- String sha1 = jedis.scriptLoad("redis.call('set',KEYS[1], ARGV[1])");
- // 通过标识执行脚本
- jedis.evalsha(sha1, 1, new String[] { "sha-key", "sha-val" });
- // 获取执行脚本后的数据
- String shaVal = jedis.get("sha-key");
- System.out.println(shaVal);
- // 关闭连接
- jedis.close();
- }
- public static void testRedisScript() {
- ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
- RedisTemplate redisTemplate = applicationContext.getBean(RedisTemplate.class);
- // 定义默认脚本封装类
- DefaultRedisScript<Role> redisScript = new DefaultRedisScript<Role>();
- // 设置脚本
- redisScript.setScriptText("redis.call('set', KEYS[1], ARGV[1]) return redis.call('get', KEYS[1])");
- // 定义操作的key列表
- List<String> keyList = new ArrayList<String>();
- keyList.add("role1");
- // 需要序列化保存和读取的对象
- Role role = new Role();
- role.setId(1L);
- role.setRoleName("role_name_1");
- role.setNote("note_1");
- // 获得标识字符串
- String sha1 = redisScript.getSha1();
- System.out.println(sha1);
- // 设置返回结果类型,如果没有这句话,结果返回为空
- redisScript.setResultType(Role.class);
- // 定义序列化器
- JdkSerializationRedisSerializer serializer = new JdkSerializationRedisSerializer();
- // 执行脚本
- // 第一个是RedisScript接口对象,第二个是参数序列化器
- // 第三个是结果序列化器,第四个是Reids的key列表,最后是参数列表
- Role obj = (Role) redisTemplate.execute(redisScript, serializer, serializer, keyList, role);
- // 打印结果
- System.out.println(obj);
- }
- public static void testLuaFile() {
- ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
- RedisTemplate redisTemplate = applicationContext.getBean(RedisTemplate.class);
- // 读入文件流
- File file = new File("E:\\study_fold\\Java_EE_SSM\\ssm\\Chapter19\\src\\test.lua");
- byte[] bytes = getFileToByte(file);
- Jedis jedis = (Jedis) redisTemplate.getConnectionFactory().getConnection().getNativeConnection();
- // 发送文件二进制给Redis,这样REdis就会返回sha1标识
- byte[] sha1 = jedis.scriptLoad(bytes);
- // 使用返回的标识执行,其中第二个参数2,表示使用2个键
- // 而后面的字符串都转化为了二进制字节进行传输
- Object obj = jedis.evalsha(sha1, 2, "key1".getBytes(), "key2".getBytes(), "2".getBytes(), "4".getBytes());
- System.out.println(obj);
- }
- /**
- * 把文件转化为二进制数组
- *
- * @param file
- * 文件
- * @return 二进制数组
- */
- public static byte[] getFileToByte(File file) {
- byte[] by = new byte[(int) file.length()];
- try {
- InputStream is = new FileInputStream(file);
- ByteArrayOutputStream bytestream = new ByteArrayOutputStream();
- byte[] bb = new byte[2048];
- int ch;
- ch = is.read(bb);
- while (ch != -1) {
- bytestream.write(bb, 0, ch);
- ch = is.read(bb);
- }
- by = bytestream.toByteArray();
- } catch (Exception ex) {
- ex.printStackTrace();
- }
- return by;
- }
- }
输出:
事务执行过程中,命令入队列,而没有被执行,所以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常用技术的更多相关文章
- Linux+Redis实战教程_day02_3、redis数据类型_4、String命令_5、hash命令_6、java操作redis数据库技术
3. redis数据类型[重点] redis 使用的是键值对保存数据.(map) key:全部都是字符串 value:有五种数据类型 Key名:自定义,key名不要过长,否则影响使用效率 Key名不要 ...
- Redis常用命令
Redis常用命令Redis提供了丰富的命令对数据库和各种数据类型进行操作,这些命令可以再Linux终端使用.1.键值相关命令2.服务器相关命令 一.键值相关命令 1.get get 键值 当 key ...
- 第2讲 Redis常用命令与高级应用
目录 一.redis数据类型 5. sorted sets类型和操作 二.Redis常用命令 1.键值相关命令 2.服务器相关命令 三. redis高级应用 1. 给redis服务器设置密码 2.持久 ...
- Android无线开发的几种常用技术(阿里巴巴资深工程师原创分享)
完整的开发一个android移动App需要经过从分解需求.架构设计到开发调试.测试.上线发布等多个阶段,在发布后还会有产品功能上的迭代演进,此外还会面对性能.安全.无线网络质量等多方面的问题. 移动A ...
- Redis常用数据类型介绍、使用场景及其操作命令
Redis常用数据类型介绍.使用场景及其操作命令 本文章同时也在cpper.info发布. Redis目前支持5种数据类型,分别是: 1.String(字符串) 2.List(列表) 3.Hash(字 ...
- React.js 常用技术要点
最近在公司的一个移动端WEB产品中使用了React这个框架(并不是React-Native),记录一下在开发过程中遇到的各种问题以及对应的解决方法,希望能对读者有所帮助. React原则 React不 ...
- Redis中7种集合类型应用场景&redis常用命令
Redis常用数据类型 Redis最为常用的数据类型主要有以下五种: String Hash List Set Sorted set 在具体描述这几种数据类型之前,我们先通过一张图了解下Redis内部 ...
- Redis 管道技术
Redis是一种基于客户端-服务端模型以及请求/响应协议的TCP服务.这意味着通常情况下一个请求会遵循以下步骤: 客户端向服务端发送一个查询请求,并监听Socket返回,通常是以阻塞模式,等待服务端响 ...
- Redis常用命令手册:服务器相关命令
Redis提供了丰富的命令(command)对数据库和各种数据类型进行操作,这些command可以在Linux终端使用.在编程时,比如各类语言包,这些命令都有对应的方法.下面将Redis提供的命令做一 ...
随机推荐
- YsoSerial 工具常用Payload分析之URLDNS
本文假设你对Java基本数据结构.Java反序列化.高级特性(反射.动态代理)等有一定的了解. 背景 YsoSerial是一款反序列化利用的便捷工具,可以很方便的生成基于多种环境的反序列化EXP.ja ...
- PO封装设计模式 -- App移动端测试
前言: 一.App_Po 封装 (用互联网上随便一个app进行) base 存放的是页面基础类,后续的类需继承基础类 common 存放的是公共部分,测试固件分离部分,新增截图功能部分 Data 存放 ...
- JavaScript学习之路(个人理解&经验):构造函数、类、实例
构造函数: 声明:"构造函数"是一类函数的 "名字" 正确的读法是"构造函数"而不是"构造 / 函数" 构造函数形如普通 ...
- Mysql数据量较大时分页查询优化
据表 collect ( id, title ,info ,vtype) 就这4个字段,其中 title 用定长,info 用text, id 是主键,vtype是int,vtype是索引. 最后co ...
- .net 5+ 知新:【2】 .Net Framework 、.Net 、 .NET Standard的概念与区别
作为了解历史和眼睛或者过程,我们需要将 .Net Framwork ..Net. .Net Stander几个概念进行下理解. .net 代表跨平台框架,从.net 5开始就统一叫.net,废弃原来的 ...
- NPM 所有的指令已经问题 使用淘宝镜像 出现code EAI_AGAIN
windows怎么卸载cnpm? npm uninstall cnpm -g windows怎么检测cnpm是否安装成功 cnpm -v 我们直接将node的仓库地址换成淘宝仓库地址即可 单次使用 n ...
- 🔥 LeetCode 热题 HOT 100(11-20)
20. 有效的括号 class Solution { public boolean isValid(String s) { Map<Character, Character> map = ...
- 利用 cgroup 的 cpuset 控制器限制进程的 CPU 使用
最近在做一些性能测试的事情,首要前提是控制住 CPU 的使用量.最直观的方法无疑是安装 Docker,在每个配置了参数的容器里运行基准程序. 对于计算密集型任务,在只限制 CPU 的需求下,直接用 L ...
- 配置多个git用的ssh key
参考 http://www.sail.name/2018/12/16/ssh-config-of-mac/ 有一点注意 Host 的名字和 HostName改为一致. 因为从git仓库复制的地址是全程 ...
- fastbin attack学习小结
fastbin attack学习小结 之前留在本地的一篇笔记,复习一下. 下面以glibc2.23为例,说明fastbin管理动态内存的细节.先看一下释放内存的管理: if ((unsigned ...