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提供的命令做一 ...
随机推荐
- lucene Hello World
一个lucene创建索引和查找索引的样例: 创建索引: public class Indexer { private IndexWriter indexWriter; /** * 构造器实例化inde ...
- 排列组合的实现(js描述)
组合的实现 排列组合描述和公式 犹记得高中数学,组合表示C(m, n),意思为从集合m,选出n个数生成一项,总共有多少个项的可能?组合是无序的,排列是有序的.所以排列的项数量多于组合 排列A(n,m) ...
- python之数据驱动Excel+ddt操作(方法二)
一.Mail163数据如下: 二.Excel+ddt代码如下: import xlrdimport unittestfrom selenium import webdriverfrom seleniu ...
- Debian10 / Ubuntu 20.10 /Linux Mint 20安装Microsoft Edge浏览器Dev版(每周更新)
安装方法如下: 打开终端命令,切换到 管理员身份,输入如下安装命令即可在Linux下使用 Microsoft Edge 浏览器了 ## Setup curl https://packages.micr ...
- 基于Redisson实现分布式锁源码解读
文章目录 一.分布式锁的概念 和 使用场景 二.将redis官网对于分布式锁(红锁)的定义和Redisson实现做概括性总结 三.基于Redisson的分布式实现方案 四.加锁过程分析 五.锁重入过程 ...
- 论文笔记:(2019)GAPNet: Graph Attention based Point Neural Network for Exploiting Local Feature of Point Cloud
目录 摘要 一.引言 二.相关工作 基于体素网格的特征学习 直接从非结构化点云中学习特征 从多视图模型中学习特征 几何深度学习的学习特征 三.GAPNet架构 3.1 GAPLayer 局部结构表示 ...
- netty系列之:netty架构概述
目录 简介 netty架构图 丰富的Buffer数据机构 零拷贝 统一的API 事件驱动 其他优秀的特性 总结 简介 Netty为什么这么优秀,它在JDK本身的NIO基础上又做了什么改进呢?它的架构和 ...
- javascript的入门学习
目录 JavaScript的学习 什么是javascript,如下简称JS 正式使用js js的两种引入方式 head标签与body标签的区别 js定义变量 可以分为如下四种类型: 有3种特殊的数据类 ...
- python实现常用五种排序算法
一.冒泡排序 原理: 比较相邻的元素.如果第一个比第二个大就交换他们两个 每一对相邻元素做同样的工作,直到结尾最后一对 每个元素都重复以上步骤,除了最后一个 第一步: 将乱序中的最大值找出,逐一移到序 ...
- CF832D题解
题目传送门 Description 给定一棵树上的三个点 \(a,b,c\),你要制定两条起点和终点都在这三个点中的路径,使得两条路径重叠的节点最多. Solution 感觉我的方法和大众不同,显然是 ...