redis使用lua脚本循环调用SETBIT教程

star2017 1年前 ⋅ 930 阅读

背景介绍的文章地址:传送门

这边直接介绍怎么使用lua实现。

import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.RedisScript;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import java.util.List;


public class RedisManagerTest {
 
private RedisTemplate<String, String> redisTemplate;

private StringRedisSerializer stringRedisSerializer;

public void setRedisTemplate(RedisTemplate<String, String> redisTemplate) {
  this.redisTemplate = redisTemplate;
}

public void setStringRedisSerializer(StringRedisSerializer stringRedisSerializer) {
  this.stringRedisSerializer = stringRedisSerializer;
}

private  byte[][] deserializeByteListValue(Object... objs) {
  byte[][] result = new byte[objs.length][];
  for (int i=0;ilength;i++) {
    int index = i;
	result[index]=(objs[index]).toString().getBytes();
  }
        return result;
  }
 
 public Object eval(final RedisScript script, final List<String> keys, final Object... args) {
	  return redisTemplate.execute(script,stringRedisSerializer,stringRedisSerializer, keys, args);
  }

}

RedisTemplate<String, String> 这里的泛型建议使用String,之前使用Serializable,lua脚本里面死活解析不了传过去的数据。

下面是redis的配置

<bean id="lua" class="com.chai.utils.RedisManagerTest">
  <property name="redisTemplate" ref="luaRedisTemplate"/>
  <property name="stringRedisSerializer" ref="stringRedisSerializer"/>
</bean>
<bean id="luaRedisTemplate"
  class="org.springframework.data.redis.core.RedisTemplate"
  p:connectionFactory-ref="luaJedisConnFactory"/>
<bean id="luaJedisConnFactory"
  class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"
  p:hostName="${lua.redis.host}" p:port="${lua.redis.port}" p:timeout="${lua.redis.timeout}"
  p:password="${lua.redis.password}"
  p:poolConfig-ref="jedisPoolConfig"/>
<bean id="stringRedisSerializer"
  class="org.springframework.data.redis.serializer.StringRedisSerializer" />
<bean id="updateAvailableSavingsCard" class="org.springframework.data.redis.core.script.DefaultRedisScript">
  <property name="location" value="classpath:/test.lua"/>
  <property name="resultType" value="org.springframework.data.redis.connection.ReturnType"/>
</bean>
<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
	<property name="maxIdle" value="300"/> <!-- 最大能够保持idel状态的对象数  -->
	<property name="maxTotal" value="60000"/> <!-- 最大分配的对象数 -->
	<property name="testOnBorrow" value="true"/> <!-- 当调用borrow Object方法时,是否进行有效性检查 -->
</bean>

下面是测试类

public class test {
	@Autowired
    @Qualifier("lua")
    private RedisManagerTest lua;
	@Resource(name = "updateAvailableSavingsCard")
    private RedisScript<ReturnType> updateAvailableSavingsCard;
	
	@Test
    public void eval(){
        long startTime = System.currentTimeMillis();
        Object evalObject = lua.eval(updateAvailableSavingsCard, Lists.newArrayList("test1"), "1,2,3");
        long endTime = System.currentTimeMillis();
        System.out.println("耗时:"+(endTime-startTime));
    }
}

test.lua

local str = ARGV[1];
local sub_str_tab = {};

while (true) do
 local pos = string.find(str, ",");
 if (not pos) then
  local size_t = table.getn(sub_str_tab)
  table.insert(sub_str_tab,size_t+1,str);
  break;
 end

 local sub_str = string.sub(str, 1, pos - 1);
 local size_t = table.getn(sub_str_tab)
 table.insert(sub_str_tab,size_t+1,sub_str);
 local t = string.len(str);
 str = string.sub(str, pos + 1, t);
end
local count;
for index,value in pairs(sub_str_tab) do
    count=redis.call("SETBIT",KEYS[1],tonumber(value),1);
end
return count;

这边java传逗号隔开的数据到lua脚本,lua脚本拿到数据之后,转换成table,在循环table去setbit到redis。
测试了下10000条数据,脚本的执行时间371毫秒

之前没弄个lua,在这个lua解析上面花了不少时间。特记录下解决方案。

本文为博主原创文章,未经博主允许不得转载。
更多内容请访问:IT源点

相关文章推荐

全部评论: 0

    我有话说: