二话不说,直接上货.多多交流哈,谢谢各路大神.
.
重点就是下面这段:
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
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
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
另外有需要云服务器可以了解下创新互联scvps.cn,海内外云服务器15元起步,三天无理由+7*72小时售后在线,公司持有idc许可证,提供“云服务器、裸金属服务器、高防服务器、香港服务器、美国服务器、虚拟主机、免备案服务器”等云主机租用服务以及企业上云的综合解决方案,具有“安全稳定、简单易用、服务可用性高、性价比高”等特点与优势,专为企业上云打造定制,能够满足用户丰富、多元化的应用场景需求。