Redis2-事务 连接Java 整合springboot 注解缓存

一、订阅和发布

Redis 发布订阅 (pub/sub) 是一种消息通信模式:发送者 (pub) 发送消息,订阅者 (sub) 接收消息。

Redis 客户端可以订阅任意数量的频道。

Redis的发布和订阅

客户端订阅频道发布的消息

频道发布消息 订阅者就可以收到消息

发布订阅的代码实现

1、 打开一个客户端订阅channel1

SUBSCRIBE channel1

2、打开另一个客户端,给channel1发布消息hello

publish channel1 hello

返回的1是订阅者数量

3、打开第一个客户端可以看到发送的消息

二、事务

1.事务简介:

可以一次执行多个命令,本质是一组命令的集合。一个事务中的 所有命令都会序列化,按顺序地串行化执行而不会被其它命令插入,不许加塞。

单独的隔离的操作

官网说明

https://redis.io/docs/interact/transactions/

MULTI、EXEC、DISCARD、WATCH。这四个指令构成了 redis 事务处理的基础。

1.MULTI 用来组装一个事务;将命令存放到一个队列里面

2.EXEC 用来执行一个事务;//commit

3.DISCARD 用来取消一个事务;//rollback

4.WATCH 用来监视一些 key,一旦这些 key 在事务执行之前被改变,则取消事务的执行。

例子:

有关事务,经常会遇到的是两类错误:

1.调用 EXEC 之前的错误

“调用 EXEC 之前的错误”,有可能是由于语法有误导致的,也可能时由于内存不足导致的。只要出现某个命令无法成功写入缓冲队列的情况,redis 都会进行记录,在客户端调用 EXEC 时,redis 会拒绝执行这一事务

2.调用 EXEC 之后的错误

2.redis事务冲突

双十一去购物的时候使用同一张银行卡去付款

10000

一个请求想给金额减8000

一个请求想给金额减5000

一个请求想给金额减1000

解决方案

悲观锁

select * from biao where 1=1 for update;

悲观锁(Pessimistic Lock), 顾名思义,就是很悲观,

每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,

这样别人想拿这个数据就会block直到它拿到锁。

传统的关系型数据库里边就用到了很多这种锁机制,

比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。

12306抢票

乐观锁

version 1

查余额 10000 version:1

10000>8000 -8000 update uuuu set moner-=8000 where version=1 1.1

10000 -5000 UPDATE uuuuu SET MONTY-=5000 WHERE VERSION=1

2000 2000>1000 UPDATE uuuu SET MONTY-=1000 WHERE VERSION=1.1 1.2

version

select * from ttt where uid =1

version money

1 10000

乐观锁(Optimistic Lock), 顾名思义,就是很乐观,

每次去拿数据的时候都认为别人不会修改,所以不会上锁,

但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,

可以使用版本号等机制。乐观锁适用于多读的应用类型,

这样可以提高吞吐量。Redis就是利用这种check-and-set机制实现事务的。

3.WATCH

“WATCH”可以帮我们实现类似于“乐观锁”的效果,即 CAS(check and set)。

执行顺序:multi(begin) ->  exec(commit) ->  discard(rollback)

WATCH 本身的作用是“监视 key 是否被改动过”,而且支持同时监视多个 key,只要还没真正触发事务,WATCH 都会尽职尽责的监视,一旦发现某个 key 被修改了,在执行 EXEC 时就会返回 nil,表示事务无法触发。

代码如下:

事务回滚:

三、Java连接redis

1. 创建java项目

2. 添加redis的依赖

<dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId><version>3.2.0</version>
</dependency>

3. 连接redis

四、redis整合springboot项目

1. 创建项目

2. 添加依赖

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><dependency><groupId>org.apache.commons</groupId><artifactId>commons-pool2</artifactId><version>2.6.0</version></dependency><dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId></dependency>

 3. 编写配置文件

 4. 设置配置类

package org.example.config;import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import redis.clients.jedis.JedisPoolConfig;import java.time.Duration;@EnableCaching
@Configuration
public class RedisConfig extends CachingConfigurerSupport {/*** 连接池的设置** @return*/@Beanpublic JedisPoolConfig getJedisPoolConfig() {JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();return jedisPoolConfig;}/*** RedisTemplate* @param factory* @return*/@Beanpublic RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {RedisTemplate<String, Object> template = new RedisTemplate<>();RedisSerializer<String> redisSerializer = new StringRedisSerializer();Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);ObjectMapper om = new ObjectMapper();// 指定要序列化的域,field,get和set,以及修饰符范围,ANY是都有包括private和publicom.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);// 指定序列化输入的类型,类必须是非final修饰的,final修饰的类,比如String,Integer等会跑出异常om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);jackson2JsonRedisSerializer.setObjectMapper(om);template.setConnectionFactory(factory);//key序列化方式template.setKeySerializer(redisSerializer);//value序列化template.setValueSerializer(jackson2JsonRedisSerializer);//value hashmap序列化template.setHashValueSerializer(jackson2JsonRedisSerializer);return template;}/*** 缓存处理* @param factory* @return*/@Beanpublic CacheManager cacheManager(RedisConnectionFactory factory) {RedisSerializer<String> redisSerializer = new StringRedisSerializer();Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
//解决查询缓存转换异常的问题ObjectMapper om = new ObjectMapper();om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);jackson2JsonRedisSerializer.setObjectMapper(om);
// 配置序列化(解决乱码的问题),过期时间600秒RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofSeconds(600)).serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer)).serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer)).disableCachingNullValues();RedisCacheManager cacheManager = RedisCacheManager.builder(factory).cacheDefaults(config).build();return cacheManager;}
}

五、注解缓存

spring缓存注解

从3.1开始,Spring引入了对Cache的支持。其使用方法和原理都类似于Spring对事务管理的支持。Spring Cache是作用在方法上的,其核心思想是这样的:当我们在调用一个缓存方法时会把该方法参数和返回结果作为一个键值对存放在缓存中,等到下次利用同样的参数来调用该方法时将不再执行该方法,而是直接从缓存中获取结果进行返回。所以在使用Spring Cache的时候我们要保证我们缓存的方法对于相同的方法参数要有相同的返回结果。

使用Spring Cache需要我们做两方面的事:

1. 声明某些方法使用缓存

2. 配置Spring对Cache的支持

和Spring对事务管理的支持一样,Spring对Cache的支持也有基于注解和基于XML配置两种方式。下面我们先来看看基于注解的方式。(基于配置的自己私下去了解即可)

基于注解的支持

@Cacheable

@Cacheable可以标记在一个方法上,也可以标记在一个类上。

当标记在一个方法上时表示该方法是支持缓存的,当标记在一个类上时则表示该类所有的方法都是支持缓存的。对于一个支持缓存的方法,Spring会在其被调用后将其返回值缓存起来,以保证下次利用同样的参数来执行该方法时可以直接从缓存中获取结果,而不需要再次执行该方法。

@Cacheable 的作用 主要针对方法配置,能够根据方法的请求参数对其结果进行缓存

@Cacheable可以指定三个属性,value、key和condition。

参数

解释

example

value

缓存的名称,在 spring 配置文件中定义,必须指定至少一个

例如:

@Cacheable(value=”mycache”)

@Cacheable(value={”cache1”,”cache2”}

key

缓存的 key,可以为空,如果指定要按照 SpEL 表达式编写,如果不指定,则缺省按照方法的所有参数进行组合

@Cacheable(value=”testcache”,key=”#userName”)

condition

缓存的条件,可以为空,使用 SpEL 编写,返回 true 或者 false,只有为 true 才进行缓存

@Cacheable(value=”testcache”,condition=”#userName.length()>2”)

a. value属性指定Cache名称

value其表示当前方法的返回值是会被缓存在哪个Cache上的,对应Cache的名称。其可以是一个Cache也可以是多个Cache,当需要指定多个Cache时其是一个数组。

 @Cacheable("cache1")//Cache是发生在cache1上的public User find(Integer id) {returnnull;}@Cacheable({"cache1", "cache2"})//Cache是发生在cache1和cache2上的public User find(Integer id) {returnnull;}
b. 使用key属性自定义key

key属性是用来指定Spring缓存方法的返回结果时对应的key的。该属性支持SpringEL表达式。当我们没有指定该属性时,Spring将使用默认策略生成key。我们这里先来看看自定义策略

自定义策略是指我们可以通过Spring的EL表达式来指定我们的key。这里的EL表达式可以使用方法参数及它们对应的属性。使用方法参数时我们可以直接使用“#参数名”或者“#p参数index”。下面是几个使用参数作为key的示例。

@Cacheable(value="users", key="#id")public User find(Integer id) {return  null;}// p  param 参数   0 @Cacheable(value="users", key="#p0")public User find(Integer id) {returnnull;}@Cacheable(value="users", key="#user.id")public User find(User user) {returnnull;}@Cacheable(value="users", key="#p0.id")public User find(User user) {returnnull;}

除了上述使用方法参数作为key之外,Spring还为我们提供了一个root对象可以用来生成key。通过该root对象我们可以获取到以下信息。

属性名称

描述

示例

methodName

当前方法名

#root.methodName

method

当前方法

#root.method.name

target

当前被调用的对象

#root.target

targetClass

当前被调用的对象的class

#root.targetClass

args

当前方法参数组成的数组

#root.args[0]

caches

当前被调用的方法使用的Cache

#root.caches[0].name

 当我们要使用root对象的属性作为key时我们也可以将“#root”省略,因为Spring默认使用的就是root对象的属性。如:

 @Cacheable(value={"users", "xxx"}, key="caches[1].name")public User find(User user) {returnnull;}
condition属性指定发生的条件

有的时候我们可能并不希望缓存一个方法所有的返回结果。通过condition属性可以实现这一功能。condition属性默认为空,表示将缓存所有的调用情形。其值是通过SpringEL表达式来指定的,当为true时表示进行缓存处理;当为false时表示不进行缓存处理,即每次调用该方法时该方法都会执行一次。如下示例表示只有当user的id为偶数时才会进行缓存。

 @Cacheable(value={"users"}, key="#user.id", condition="#user.id%2==0")public User find(User user) {System.out.println("find user by user " + user);return user;}
@CachePut

在支持Spring Cache的环境下,对于使用@Cacheable标注的方法,Spring在每次执行前都会检查Cache中是否存在相同key的缓存元素,如果存在就不再执行该方法,而是直接从缓存中获取结果进行返回,否则才会执行并将返回结果存入指定的缓存中。@CachePut也可以声明一个方法支持缓存功能。与@Cacheable不同的是使用@CachePut标注的方法在执行前不会去检查缓存中是否存在之前执行过的结果,而是每次都会执行该方法,并将执行结果以键值对的形式存入指定的缓存中。

一般使用在保存,更新方法中。

@CachePut也可以标注在类上和方法上。使用@CachePut时我们可以指定的属性跟 @Cacheable是一样的。

 @Cacheable(cacheNames = "user", key = "#id")//每次都会执行方法,并将结果存入指定的缓存中public User find(Integer id) {return null;}
@CacheEvict

@CacheEvict是用来标注在需要清除缓存元素的方法或类上的。当标记在一个类上时表示其中所有的方法的执行都会触发缓存的清除操作。@CacheEvict可以指定的属性有value、key、condition、allEntries和beforeInvocation。其中value、key和condition的语义与@Cacheable对应的属性类似。即value表示清除操作是发生在哪些Cache上的(对应Cache的名称);key表示需要清除的是哪个key,如未指定则会使用默认策略生成的key;condition表示清除操作发生的条件。下面我们来介绍一下新出现的两个属性allEntries和beforeInvocation。

1、 allEntries属性

allEntries是boolean类型,表示是否需要清除缓存中的所有元素。默认为false,表示不需要。当指定了allEntries为true时,Spring Cache将忽略指定的key。有的时候我们需要Cache一下清除所有的元素,这比一个一个清除元素更有效率。

@CacheEvict(value="users",key = "#id", allEntries=true)
public void delete(Integer id) {System.out.println("delete user by id: " + id);
}
2、 beforeInvocation属性

清除操作默认是在对应方法成功执行之后触发的,即方法如果因为抛出异常而未能成功返回时也不会触发清除操作。使用beforeInvocation可以改变触发清除操作的时间,当我们指定该属性值为true时,Spring会在调用该方法之前清除缓存中的指定元素。

@CacheEvict(value="users",key = "#id", beforeInvocation=true)
public void delete(Integer id) {System.out.println("delete user by id: " + id);
}

六、springboot基于注解的redis缓存

1.开启注解缓存

 2. 添加缓存

3. 测试

第一次访问,控制台会打印数据

 缓存之后,清空控制台,再次访问,直接通过缓存获取

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/650018.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ENVI下基于知识决策树提取地表覆盖信息

基于知识的决策树分类是基于遥感影像数据及其他空间数据,通过专家经验总结、简单的数学统计和归纳方法等,获得分类规则并进行遥感分类。分类规则易于理解,分类过程也符合人的认知过程,最大的特点是利用的多源数据。 决策树分类主要的工作是获取规则,本文介绍使用CART算法…

NQA测试机制—UDP Jitter测试

概念 UDP Jitter是以UDP报文为承载&#xff0c;通过记录在报文中的时间戳信息来统计时延、抖动、丢包的一种测试方法。Jitter&#xff08;抖动时间&#xff09;是指相邻两个报文的接收时间间隔减去这两个报文的发送时间间隔。 UDP Jitter测试的过程如下&#xff1a; 1. 源端&a…

shell编程之循环语句与函数

一 echo命令 echo -n 表示不换行输出 echo -e 表示输出转义符 常用的转义符 二 date date查看当前系统时间 -d 你描述的日期&#xff0c;显示指定字符串所描述的时间&#xff0c;而非当前时间 %F 完整日期格式&#xff0c;等价于 %Y-%m-%d % T 时间&#xff08;24小时…

1.26学习总结

连通性判断 DFS连通性判断步骤&#xff1a; 1.从图上任意一点u开始遍历&#xff0c;标记u已经走过 2.递归u的所有符合连通条件的邻居点 3.递归结束&#xff0c;找到了的所有与u的连通点&#xff0c;就是一个连通块 4.然后重复这个步骤找到所有的连通块 BFS连通性判断步骤…

linux 查看zookeeper server运行版本号

zookeeper版本查看运行命令&#xff1a;echo stat|nc localhost 2181 显示如下图所示&#xff1a; Zookeeper version: 3.4.5-cdh6.3.2--1, built on 11/08/2019 13:15 GMT Clients: /127.0.0.1:44814[0](queued0,recved1,sent0) Latency min/avg/max: 0/0/0 Received: 9 Se…

防火墙的NAT

目录 1. NAT 概念解析 2. 配置NAT策略&#xff1a; 1. NAT 概念解析 静态NAT --- 一对一 动态NAT --- 多对多 NAPT --- 一对多的NAPT --- easy ip --- 多对多的NAPT 服务器映射 源NAT --- 基于源IP地址进行转换。我们之前接过的静态NAT&#xff0c;动态NAT&#xff0c;NAPT都属…

*【艺恩娱数】Python爬虫+数据分析可视化中国影院票房*¶

文章目录 一、记得登入才能看到所有的数据二、使用步骤艺恩数据可视化艺恩影院票房Top10艺恩影院票房销售额对比艺恩影院票房省份人次分析艺恩影院场次top10榜单 这个里面的影院名称&#xff0c;省份&#xff0c;城市&#xff0c;票房&#xff0c;场次&#xff0c;人次&#xf…

ESXI 本地和虚拟机之间可以自由复制和粘贴

文章目录 ESXI 本地和虚拟机之间可以自由复制和粘贴 ESXI 本地和虚拟机之间可以自由复制和粘贴 web访问esxi&#xff0c;然后&#xff1a; 1、右击新建的虚拟机&#xff0c;确保是在关机状态下&#xff0c;点击编辑设置 2. 找到 虚拟机选项→高级→常规→配置参数 3、点击添加…

Unity3d C#实现三维场景中图标根据相机距离动态缩放功能

前言 如题的需求&#xff0c;其实可以通过使用UI替代场景中的图标来实现&#xff0c;不过这样UI的处理稍微麻烦&#xff0c;而且需要在图标上添加粒子特效使用SpriteRender更方便快捷。这里就根据相机离图标的位置来计算图标的缩放大小即可。这样基本保持了图标的大小&#xf…

Vulnhub靶场DC-3

本机192.168.223.128 靶机192.168.223.139 目标发现nmap -sP 192.168.223.0/24 端口扫描nmap -p- 192.168.223.139 之开启了一个80端口 看一下是什么服务 nmap -sV -p- -A 192.168.223.139是一个apache服务&#xff0c;joomla模板 看一下web 没什么有用信息。 扫描一下后台…

华为HCIP Datacom H12-831 卷18

判断题 1、对于同一个MAC地址,手工配置的MAC表项优先级高于动态的表项,某二层报文的源MAC地址已经绑定在了交换机的GEO/0/1接口,当交换机从GEO/0/2收到该报文时,会丢弃该报文 A 对 B 错 正确答案 A 解析:为了提高接口安全性,网络管理员可手工在MAC地址表中加入特定M…

银行数据仓库体系实践(3)--数据架构

狭义的数据仓库数据架构用来特指数据分布&#xff0c;广义的数据仓库数据架构还包括数据模型、数据标准和数据治理。即包含相对静态部分如元数据、业务对象数据模型、主数据、共享数据&#xff0c;也包含相对动态部分如数据流转、ETL、整合、访问应用和数据全生命周期管控治理。…

在 Vue 项目中,可以通过设置不同的环境变量来区分不同的环境,例如本地开发环境、测试环境和生产环境。以下是设置环境变量的步骤:

1、在src下新建三个文件夹 &#xff08;.env.local、.env.test 和 .env.prod&#xff09; 2、配置信息 .env.local VUE_APP_ENVlocal VUE_APP_API_URLhttp://localhost:8080.env.test VUE_APP_ENVtest VUE_APP_API_URLhttp://124.220.110.203:9090/ .env.prod VUE_APP_…

Android源码设计模式解析与实战第2版笔记(一)

第一章 走向灵活软件之路 — 面向对象的六大原则 优化代码的第一步 — 单一职责原则 单一职责原则的英文名称是Single Responsibility Principle&#xff0c;缩写是SRP。 SRP&#xff1a;就一个类而言&#xff0c;应该仅有一个引起它变化的原因。 一个类中应该是一组相关性很…

Redis创建集群

主要内容 搭建redis集群 能力目标 搭建redis集群 一 应用场景 为什么需要redis集群&#xff1f; 当主备复制场景&#xff0c;无法满足主机的单点故障时&#xff0c;需要引入集群配置。 一般数据库要处理的读请求远大于写请求 &#xff0c;针对这种情况&#xff0c;我们优…

ES 分布式搜索的运行机制

ES 分布式搜索的运行机制-腾讯云开发者社区-腾讯云 ES 分布式搜索的运行机制 ES 有两种 search_type 即搜索类型&#xff1a; •query_then_fetch &#xff08;默认&#xff09;•dfs_query_then_fetch query_then_fetch query_then_fetch 1.用户发起搜索&#xff0c;请求…

Python的hashlib模块:7种加密算法深入剖析

目录 一、引言 二、哈希算法简介 三、hashlib模块中的加密算法 MD5 SHA1 SHA224/SHA256/SHA384/SHA512 SHA3 其他算法&#xff1a; 四、加密算法比较与选择 五、实际应用与注意事项 六、总结 本文将深入探讨Python的hashlib模块&#xff0c;重点解析其中的七种加密算…

【GitHub项目推荐--GitHub 上的高仿项目】【转载】

整理了现在比较热门 App 的高仿项目&#xff0c;这些项目都是有「recently updated」&#xff0c;而不是年代久远不再维护的项目。包括高仿微信、微博、B站、斗鱼、抖音、美团、头条、掘金等等。 这些项目涉及的技术栈有 Vue、Flutter 等等&#xff0c;看这些高仿项目的源码有…

element-ui 树形控件 实现点击某个节点获取本身节点和底下所有的子节点数据

1、需求&#xff1a;点击树形控件中的某个节点&#xff0c;需要拿到它本身和底下所有的子节点的id 1、树形控件代码 <el-tree:data"deptOptions"node-click"getVisitCheckedNodes"ref"target_tree_Speech"node-key"id":default-ex…

Discuz论坛搭建:Linux宝塔面板一键部署,固定地址畅享公网访问

&#x1f308;个人主页&#xff1a;聆风吟 &#x1f525;系列专栏&#xff1a;网络奇遇记、Cpolar杂谈 &#x1f516;少年有梦不应止于心动&#xff0c;更要付诸行动。 文章目录 &#x1f4cb;前言一. 安装基础环境二. 一键部署Discuz三. 安装cpolar工具四. 配置域名访问Discuz…