• 分布式系列十一: Redis进阶


    分布式锁

    • 数据库

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

    • zookeeper

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

    • redis

      setNX实现

    // 为了简单就不用配置文件了
    @Configuration
    public 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 方法这里没有用异常处理.
    @Component
    public 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=1
    print(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);
    
  • 相关阅读:
    Timestamp 转 date
    【mysql】 mysql 子查询、联合查询、模糊查询、排序、聚合函数、分组----------语法
    【mysql】新增、修改、删除、查询 语法讲义
    【jQuery05】通过按键 来切换 class
    【jQuery04】折叠树
    【jQuery03】简单的选项卡切换
    【jQuery02】点击标题面板显示内容
    python-day70--django-Mysql-单表增删改查
    python-day68--模型层基础(model)
    python-day67--MTV之Template
  • 原文地址:https://www.cnblogs.com/walkinhalo/p/10710107.html
Copyright © 2020-2023  润新知