千家信息网

Redis 集群 lua 实现

发表于:2026-11-04 作者:千家信息网编辑
千家信息网最后更新 2026年11月04日,二话不说,直接上货.多多交流哈,谢谢各路大神..重点就是下面这段:Object object = redisTemplate.execute(redisUpdateOrderScript,//这里有k
千家信息网最后更新 2026年11月04日Redis 集群 lua 实现

二话不说,直接上货.多多交流哈,谢谢各路大神.
.
重点就是下面这段:

Object object = redisTemplate.execute(redisUpdateOrderScript,//这里有key 要像官网说的那样加个"{}",不然就报错了,这里3个key都要前缀一致Arrays.asList(hkey, amountKey, key),//值无要求amount.longValueExact(),price.doubleValue(),price.doubleValue());

我自己的理解是,执行脚本和执行hget 是一样的,只是lua脚本内容由Redis执行,但发送命令的要求是一样的.所以上面3个key 都得加一样的前缀.
.
.
.

业务逻辑是这样子的:
把20档盘口放到Redis里面
1.用有序集合(sorted set)进行自动价格排序

ZADD key 0.0354 "0.0354"

2.然后再根据价格到hash里去取值,取的val 就是这个价格的下单量

HGET key 0.0354

java 代码

加盘口

 public void addOrderForLua(BeforeMatchDTO model) {        //缓存失效        redisService.remove(RedisService.getPositionKey(model.getContract()));        BigDecimal price = model.getPrice();        BigDecimal amount = model.getAmount().multiply(PRECISION_DOUBLE);        String key = RedisKeyGen.getContractPositionZsetKey(model.getContract(), model.getDirection());        log.info("getContractPositionZsetKey:{}",key);        String hkey = RedisKeyGen.getContractPositionHashKey(model.getContract(), model.getDirection());        log.info("getContractPositionHashKey:{}",hkey);        String amountKey = RedisKeyGen.getContractPositionAmountKey(model.getContract(),price.stripTrailingZeros().toPlainString());        log.info("getContractPositionAmountKey:{}",amountKey);        log.info("addOrderForLua contract:{}, value:{}", model.getContract(), amount.longValueExact());        Object object = redisTemplate.execute(redisUpdateOrderScript, Arrays.asList(hkey, amountKey, key), amount.longValueExact(),price.doubleValue(),price.doubleValue());        log.info("addOrderForLua" + object);    }

减盘口

public void subOrderForLua(String contract,BigDecimal price,BigDecimal amount,int direction) {        //缓存失效        redisService.remove(RedisService.getPositionKey(contract));        String key = RedisKeyGen.getContractPositionZsetKey(contract, direction);        log.info("getContractPositionZsetKey:{}",key);        String hkey = RedisKeyGen.getContractPositionHashKey(contract, direction);        log.info("getContractPositionHashKey:{}",hkey);        String amountKey = RedisKeyGen.getContractPositionAmountKey(contract,price.stripTrailingZeros().toPlainString());        log.info("getContractPositionAmountKey:{}",amountKey);        log.info("subOrderForLua contract:{}, value:{}", contract, amount.doubleValue());        BigDecimal amountTag = amount.multiply(PRECISION_DOUBLE).negate();  //转成负数        Object nowAmount = redisService.hmGet(hkey, price.toPlainString());        log.info("subOrderForLua nowAmount:{},direction:{}", nowAmount, direction);        Object object = redisTemplate.execute(redisUpdateOrderScript, Arrays.asList(hkey, amountKey, key), amountTag.longValueExact(),price.doubleValue(),price.doubleValue());        log.info("subOrderForLua" + object);    }

查询(重点看取值的地方,转换请忽略)

public List query(String contract,int direction) {        List result = new ArrayList<>();        String key = RedisKeyGen.getContractPositionZsetKey(contract, direction);        log.info("getContractPositionZsetKey:{}",key);        String hkey = RedisKeyGen.getContractPositionHashKey(contract, direction);        log.info("getContractPositionHashKey:{}",hkey);        Set objectSet = null;        //卖从低到高        if(QuotationConstants.DIRECTION_SELL == direction) {            objectSet = redisService.rangeByIndex(key, 0, 19);        } else {            //买从高到低            objectSet = redisService.reverseRangeByIndex(key, 0, 19);        }        if (objectSet != null && objectSet.size() > 0) {            Integer [] digits = convertService.getContractDigitsForInt(contract);            for (Object obj : objectSet) {                log.info("query class:{},val:{}",obj.getClass(),JSON.toJSONString(obj));                BigDecimal price = new BigDecimal(obj.toString());                String amountKey = RedisKeyGen.getContractPositionAmountKey(contract,price.stripTrailingZeros().toPlainString());                Object object = redisService.hmGet(hkey, amountKey);                log.info("getContractPositionAmountKey hmGet key:{},val:{}",amountKey,object);                BigDecimal valTemp = getBigDecimal(object);                if(valTemp.compareTo(BigDecimal.ZERO) == 0) continue;                BigDecimal val = valTemp.divide(PRECISION_DOUBLE);                QuotationOrderRsgResp resp = new QuotationOrderRsgResp();                resp.setContract(contract);                resp.setDirection(direction);                resp.setPrice(convertService.setScale(price, digits[0]));                resp.setVolume(convertService.setScale(val,digits[1]));                resp.setTotal(convertService.setScale(price.multiply(val),add(digits[0] ,digits[1])));                result.add(resp);            }        } else {            log.info("query redis is null! contract:{},direction:{}", contract, direction);        }        return result;    }

key 生成

 public static final String getContractPositionZsetKey(String contract,int direction){        return "{POSITION:"+contract+"}.POSITION-ORDER-" + contract + "-" + direction;    }    public static final String getContractPositionHashKey(String contract,int direction){        return "{POSITION:"+contract+"}.POSITION-ORDER-VAL-" + contract + "-" + direction;    }    public static final String getContractPositionAmountKey(String contract,String amount){        return "{POSITION:"+contract+"}." + amount;    }

lua 脚本

local val1 = '"'local valAmount = redis.call('hget',KEYS[1],KEYS[2])if not valAmount then    redis.pcall('hset',KEYS[1],KEYS[2],ARGV[1])    if tonumber(ARGV[1]) > 0 then        local val2 = val1 .. ARGV[3] .. val1        return redis.pcall('ZADD', KEYS[3], tonumber(ARGV[2]), val2)    else        return 1    endelse    local tagAmount = tonumber(valAmount) + ARGV[1]    redis.pcall('hset',KEYS[1],KEYS[2],tagAmount)    local val2 = val1 .. ARGV[3] .. val1    local zset = redis.pcall('ZRANK', KEYS[3], val2)    if tagAmount <= 0 then        if not zset then            return 1        else            return redis.pcall('ZREMRANGEBYSCORE', KEYS[3], tonumber(ARGV[2]), tonumber(ARGV[2]))        end    else        if not zset then            local val2 = val1 .. ARGV[3] .. val1            return redis.pcall('ZADD', KEYS[3], tonumber(ARGV[2]), val2)        else            return 1        end    endend
价格 盘口 脚本 前缀 就是 缓存 重点 有序 一致 二话不说 业务 二话 代码 内容 只是 命令 地方 大神 样子 负数 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 互联网科技的发展 致骋互联网科技 世界互联网领先科技成果 安徽鑫晟辉互联网科技 互联网科技咨询 国外互联网科技网站 农村开互联网科技讲堂 互联网金融中的现代科技 花神(南京)互联网科技有限公司 爱医互联网络科技 元气玛特互联网科技公司是外包吗 郑州欣桑互联网科技有限公司 易企秀互联网科技是做什么的 新氧科技和美国互联网有关系吗 信承诺互联网科技有限公司 中国科技和美国互联网 张家口科技产业互联网平台 互联网科技博主张洲 前海云享互联网科技 武汉亿视互联网科技有限公司 深圳互联网科技公司 银优互联网科技有限公司 互联网金融科技平台 互联网科技上市公司 互联网教育科技公司vipkid 重庆威客帮互联网科技 消费医药和互联网科技 无锡工业互联网科技有限公司 互联网科技融合创新 济南小医互联网科技有限公司招聘
0