Implementation of Redis cluster lua

Keywords: Programming Redis Java JSON

Two words don't say, directly on the goods. A lot of exchanges ha, thank all the gods
.
The main point is as follows:

Object object = redisTemplate.execute(redisUpdateOrderScript,
//If there is a key here, add "{}" as the official website says, or it will be reported as an error. All three keys here should have the same prefix
Arrays.asList(hkey, amountKey, key),
//The value is not required.
amount.longValueExact(),price.doubleValue(),price.doubleValue());

My own understanding is that executing scripts is the same as executing hget, except that the content of lua scripts is executed by Redis, but the requirements for sending commands are the same. So the above three key s must be prefixed with the same prefix
.
.
.

The business logic looks like this:
Put the 20th gear in Redis
1. Automatic price sorting with sorted set

ZADD key 0.0354 "0.0354"

2. Then take the value in hash according to the price. The val is the order quantity of this price

HGET key 0.0354

java code

Add dish mouth

 public void addOrderForLua(BeforeMatchDTO model) {

        //Cache invalidation
        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);

    }

Reduction of opening

public void subOrderForLua(String contract,BigDecimal price,BigDecimal amount,int direction) {

        //Cache invalidation
        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();  //Turn negative

        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);

    }

Query (focus on the value, please ignore the conversion)

public List<QuotationOrderRsgResp> query(String contract,int direction) {

        List<QuotationOrderRsgResp> result = new ArrayList<>();
        String key = RedisKeyGen.getContractPositionZsetKey(contract, direction);
        log.info("getContractPositionZsetKey:{}",key);
        String hkey = RedisKeyGen.getContractPositionHashKey(contract, direction);
        log.info("getContractPositionHashKey:{}",hkey);
        Set<Object> objectSet = null;

        //Sell from low to high
        if(QuotationConstants.DIRECTION_SELL == direction) {
            objectSet = redisService.rangeByIndex(key, 0, 19);
        } else {
            //Buy from high to low
            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 generation

 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 script

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
    end
else
    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
    end
end

Posted by zhangy on Sat, 02 Nov 2019 16:11:18 -0700