分布式系列十一: Redis进阶

分布式锁数据库数据库是使用唯一索引不允许重复的特性(或自定义实现如乐观锁).但持有锁的进程如果释放锁时异常则容易导致死锁.zookeeper使用临时节点,watcher可以获得节点被删除的通知,当客户端连接失效后,临时节点清除,所以这种情况下不会有死锁发生.redissetNX实现//为了简单就不用配置文件了@ConfigurationpublicclassRedisManager{private...

分布式锁

  • 数据库

    数据库是使用唯一索引不允许重复的特性(或自定义实现如乐观锁). 但持有锁的进程如果释放锁时异常则容易导致死锁.

  • zookeeper

    使用临时节点, watcher可以获得节点被删除的通知, 当客户端连接失效后, 临时节点清除, 所以这种情况下不会有死锁发生.

  • redis

    setNX实现

// 为了简单就不用配置文件了@Configurationpublic class RedisManager { private JedisPool jedisPool ; public RedisManager(){  JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();  jedisPoolConfig.setMaxTotal(20);  jedisPoolConfig.setMaxIdle(10);  this.jedisPool = new JedisPool(jedisPoolConfig, “127.0.0.1“,6379); } @Bean public Jedis getJedis(){  if (this.jedisPool==null){return null;  }  return jedisPool.getResource(); }}
// lock, unlock 方法这里没有用异常处理.@Componentpublic class RedisLock { @Autowired private Jedis jedis; public String lock(String key, int timeout){  String uuid = UUID.randomUUID().toString();  long lockTime = System.currentTimeMillis();  while(System.currentTimeMillis()-lockTime<timeout*1000) {long rs = jedis.setnx(key, uuid);if (rs==1){ jedis.expire(key, (int) timeout); return uuid;}// 保证key被设置了超时时间if (jedis.ttl(key)==-1){ jedis.expire(key, (int) timeout);}  }  return  uuid; } public boolean unlock(String key, String value){  while(true) {jedis.watch(key);String ret = jedis.get(key);if (value.equals(ret)) { Transaction transaction = jedis.multi(); transaction.del(key); List<Object> transResult = transaction.exec(); if (transResult == null) {  continue; } jedis.unwatch(); return true;}jedis.unwatch();break;  }  return false; }}

lua语言

redis可以使用lua脚本. lua是动态类型语言.

  • 减少网络开销

  • 原子操作

  • 代码可以复用

  • 轻量级

安装

tar -zxvf ...
make linux
make install

出现fatal error: readline/readline.h: No such file or directory 则需要运行

sudo apt-get install libreadline-dev

命令

  • 全局变量, 局部变量
a=1print(a)local b=2 print(b) //局部变量,在一条语句local array = {“a“,“b“} //数组定义
  • 逻辑表达式

      • / %

不等于使用~=

  • 逻辑运算

not (a and/or B)

  • 字符串连接

str1..str2

  • 字符串长度用#

#“hello“

  • 分支

if expression then elseif expression then end

  • 循环

while expression do ..... end

for i=1,100 do .... end

for i,v in iparis(array) do ..... end

  • 注释

单行使用-- ; 范围使用--[[ ..... ]]

  • 函数
function(params...) --...... return a;end

内置对象: String , Table tonumber()

  • lua 可以调用redis命令

redis.call() --需要引入库支持, redis内置的lua, 可以在redis内部执行

lua在Redis中的使用

  • 执行 eval 'lua script' keynumber key...

  • KEYS[] ARGV[] 入参, 必须大写

  • 执行lua脚本文件./redis-cli --eval luafile.lua keyparam1 ,valueparam2 vlaueparam3

程序中使用lua

String lua = “local num = redis.call('incr',KEYS[1]) ... “;jedis.eval();

可以使用摘要执行脚本, 这对大脚本文件比较有用.

jedis.evalsha(jedis.scriptLoad(lua),key,value);
源文地址:http://www.guoxiongfei.cn/cntech/14836.html