SpringBoot中RedisTemplate的RedisScript解析

本文涉及的产品
云数据库 Redis 版,社区版 2GB
推荐场景:
搭建游戏排行榜
简介: SpringBoot中RedisTemplate的RedisScript解析

在RedisTemplate执行lua脚本如果做呢? 查看下面方法代码,这是引入lua内容脚本到RedisScript的子类DefaultRedisScript类中,这是redis提供支持的脚本支持类,更多内容可参考=>redis脚本参考

protected RedisScript<Long> getRedisLockScript() {
        String script = "local key = ARGV[1];local expiration = ARGV[2];local value = 1;";
        script += "if redis.call('EXISTS', key) == 1 then return -1 else redis.call('SET', key, value);redis.call('EXPIRE', key, expiration);return 1;end";
        return new DefaultRedisScript<>(script, Long.class);
    }

这里可以通过查看execute方法查看执行的源码流程:

* 获取锁
eparam kex
大 @param expireSeconds 锁的过期时间 
@return 获取到锁返回true,否则false
public boolean tryLock(String key, int expireSeconds){
return stringRedisTemplate.execute(redisLockScript, EMPTY_LIST,key,String.value0f(expireSeconds)).intValue()==1;}

首先进入到RedisTemplate.java中的execute()方法中

LockServicejava x RedisTemplatejava x DefaultScriptExecutorjava x 
public <T>Texecute(RedisScript<T> script, List<k> keys, object... args) { 
return scriptExecutor.execute(script, keys, args);  
  public <i>T execute(RedisScript<>> script,RedisSerializer<?> argsSerializer, RedisSerializer<>> resultserializer  
  List<k> keys, object... args){  
  return scriptExecutor.execute(script,argsSerializer, resultSerializer, keys, args); 

通过方法重载,找到具体的执行类方法,主要有以下4步:

  1. execute()三个参数的方法
  2. execute()五个参数的方法
  3. execute()五个参数的方法体
  4. 最后eval()方法执行redis脚本命令
public <i>T execute(final RedisScript<T> script, final List<> keys, final Object... args) {
// use the Template's value serializer for args and result
return execute(script,template.getValueSerializer(),(RedisSerializer<T>) template.getValueSerializer(),keys,
args);
}
public <T>Texecute(final RedisScript<T> script, final RedisSerializer<?> argsSerializer,
final RedisSerializer<T> resultserializer, final List<k> keys, final Object... args) {
return template.execute((RedisCallback)(connection)>{
final ReturnType returnType =ReturnType.fromJavaType(script.getResultType()):
final byte[][] keysAndArgs = keysAndArgs(aresSerializer, keys, ares); final int keysize = keys != null ? keys.size() : 0;
if(connection.isPipelined()l| connection.isQueueing()){
// We could script load first and then do evalsha to ensure sha is present,// but this adds a sha1 to exec/closePipeline results. Instead, just eval connection.eval(scriptBytes(script),returnType, keySize, keysAndArgs); return null;}
return eval(connection, script, returnType, keySize, keysAndArgs, resultserializer);
});
  1. 接下来进入到eval()方法的对应实现类DefaultScriptExecute中: 首先直接传sha值,如果在Redis中找不到预加载的lua脚本导致报错,则catch住该错误,把整个脚本序列化后传入Redis进行执行:
protected<i>Teval(RedisConnection connection,RedisScript<T>script, ReturnType returnType, int numKeys,  
byte[][] keysAndArgs, RedisSerializer<T> resultSerializer){ 
Object result;  
try { 
  result=connection.evalsha(script.getSha1(),returnType,numKeys,keysAndArgs); 
} catch(Exception e){ 
if(!exceptionContainsNoScriptError(e)){ 
throweinstanceof RuntimeException?(RuntimeException)e:new RedisSystemException(e.getMessage(), e);  
  result = connection.eval(scriptBytes(script),returnType, numKeys,keysAndArgs);  
  } 
if (script.getResultType() == null){  
  return null;  
  } 
return deserializeResult(resultSerializer, result); 
} 

我们查看以下脚本序列化的执行代码scriptBytes(),其对应的执行类为StringRedisSerializer

keysAndArgsL1++」= argsserializer.serialize(arg);  
return keysAndArgs; 
protected byte[] scriptBytes(RedisScript<?> script) {
return template.getStringSerializer().serialize(script.getScriptAsString());  
  Choose Implementation of  FRedisSerializer.serialize(T) (7 found) 
GenericJackson2JsonRedisSerializer(org.springframework.data.redis.serializer) Maven:org.springframework.data:spring-data-redi 
GenericToStringSerializer(org.springframework.data.redis.serializer)  Maven:org.springframework.data:spring-data-redi 
Jackson2JsonRedisSerializer(org.springframework.data.redis.serializer)  Maven:org.springframework.data:spring-data-redi 
JacksonJsonRedisSerializer(org.springframework.data.redis.serializer) Maven:org.springframework.data:spring-data-redi 
JdkSerializationRedisSerializer(org.springframework.data.redis.serializer)  Maven:org.springframework.data:spring-data-redi   Oxmserializer(org.sprineframework.data.redis.serializer)  Maven:org.springframework.data:spring-data-redi 
  StringRedisSerializer(org.springframework.data.redis.serializer)  Maven:org.springframew

进入到StringRedisSerializer类,可以看出该序列化操作其实就是字符串String序列化操作

  package org.springframework.data.redis.serializer;  
import
/** Simple String to byte[](and back)serializer. Converts Strings into bytes and vice-versa using the specified charset ...*/ 
public class StringRedisSerializer implements RedisSerializer<String> { 
private final charset charset:  
  public StringRedisSerializer(){this(Charset.forName("UTF8"));}  
  @ public StringRedisSerializer(charset charset){  
Assert.notNull(charset, message:"Charset must not be null!"): this.charset = charset;
public string deserialize(byte[] bytes){ return(bytes == null ? null : new String(bytes, charset)); } 
public byte[] serialize(string string){ 
return(string == null ? null :string.getBytes(charset));  

至此,关于SpringBoot中RedisTemplate的RedisScript源码分析结束~



相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
5天前
|
NoSQL Java Redis
springboot之RedisTemplate的访问单机,哨兵,集群模式
以上是配置RedisTemplate以连接到单机、哨兵和集群模式的示例。在实际应用中,还可以根据需求配置连接池、序列化方式、超时等其他参数。
33 0
|
15天前
|
缓存 Java 开发者
10个点介绍SpringBoot3工作流程与核心组件源码解析
Spring Boot 是Java开发中100%会使用到的框架,开发者不仅要熟练使用,对其中的核心源码也要了解,正所谓知其然知其所以然,V 哥建议小伙伴们在学习的过程中,一定要去研读一下源码,这有助于你在开发中游刃有余。欢迎一起交流学习心得,一起成长。
|
19天前
|
Java Spring 容器
SpringBoot自动装配原理之@Import注解解析
SpringBoot自动装配原理之@Import注解解析
53 0
|
19天前
|
canal 缓存 关系型数据库
Spring Boot整合canal实现数据一致性解决方案解析-部署+实战
Spring Boot整合canal实现数据一致性解决方案解析-部署+实战
|
22天前
|
JSON Java Maven
Javaweb之SpringBootWeb案例之 SpringBoot原理的详细解析
Javaweb之SpringBootWeb案例之 SpringBoot原理的详细解析
45 0
Javaweb之SpringBootWeb案例之 SpringBoot原理的详细解析
|
22天前
|
Java 数据库连接 容器
SpringBoot之IOC&DI的详细解析
SpringBoot之IOC&DI的详细解析
10 0
SpringBoot之IOC&DI的详细解析
|
22天前
|
存储 Java 程序员
SpringBoot之分层解耦以及 IOC&DI的详细解析
SpringBoot之分层解耦以及 IOC&DI的详细解析
13 0
|
22天前
|
前端开发 Java
SpringBoot之三层架构的详细解析
SpringBoot之三层架构的详细解析
55 0
|
Java Spring
SpringBoot - 静态工具类中注入 RedisTemplate
SpringBoot - 静态工具类中注入 RedisTemplate
1049 0
|
1月前
|
Java Linux
Springboot 解决linux服务器下获取不到项目Resources下资源
Springboot 解决linux服务器下获取不到项目Resources下资源

推荐镜像

更多