2020年技术总结——JAVA篇

实践中遇到的一些问题及解决方案

  • 机器人画K线时出现插针问题
  • 钱包自动入账时的并发问题

机器人画K线时出现插针问题

问题描述:
交易所的K线是由定时任务里的“机器人”根据主流交易所行情信息画出来的,平时正常,在无人改动的情况下突然出现极低行情价格,造成K线插针,用户爆仓。
原因:
行情价格是从火币、币安等交易所获取的并存入redis的,机器人取到价格后根据行情价格画K线。由于火币等网站API在不帆蔷的情况下会有卡顿甚至调不通,所以前同事为了测试方便,在机器人获取行情价时,取出配置文件中的searchLocal进行了判断,如果是true,代表为本地测试环境,则生成一个随机数+机器人ID,作为币种的行情价格,如果是false,代表生产环境(香港服务器),则取API获取的行情价格作为币种的行情价。故障是由于配置文件在热加载的过程中出现了问题,造成服务器进程中的本地测试代码生效了。
解决方案:
注释掉本地测试假数据,也取火币行情数据。

if(searchLocal){
       price = searchPriceService.getDirectPrice(trade.getSearchName());
//price = MathUtil.add(new BigDecimal(id+10), RandomUtil.randomBigDecimal(new BigDecimal("0.01"),new BigDecimal("0.05"))).setScale(4,BigDecimal.ROUND_DOWN);
 }else{
       price = searchPriceService.getPrice(trade.getSearchName());
 }
          

钱包自动入账时的并发问题

问题描述:
给钱包做好自动入账功能之后,部署到服务器上发现和本地测试的效果不同,一次充值会出现两次入账,比如充100usdt,账户余额增加200usdt。
原因:
前同事的启动脚本中启动了两个进程,组建了集群,出现了并发问题。
解决:
使用redis分布式锁方案解决。关键点:redis中的setnx方法。此方法的作用是:在redis中存入key-value的同时判断是否已经存在该键值对,如果存在则不会覆盖,返回false,如果不存在,存入并返回true。

使用分布式锁时要注意的问题:给key-value设置存活期,避免形成死锁。

//核心代码:RedisUtil类中:
    public boolean setnx(String key, long delta,long timeout) {
        if(redisTemplate.opsForValue().setIfAbsent(key,delta)){
            redisTemplate.expire(key,timeout,TimeUnit.SECONDS);
            return true;
        }
        return false;
    }
//核心代码:自动入账类中:
private void autoConfirm(){
        List rechargeNotIn = rechargeMapper.findRechargeNotIn();
        if (null == rechargeNotIn||0==rechargeNotIn.size()){
            return;
        }
        for (int i = 0; i < rechargeNotIn.size(); i++) {
            RechargeModel rechargeModel = rechargeNotIn.get(i);
            String key = LockConstant.LOCK_IN_ACCOUNT+rechargeModel.getId();
            long value = System.currentTimeMillis();
            //加分布式锁:
            if(!redisRepository.setnx(key, value, 3L * 60)){
                return;
            }
            try {
                handleAutoConfirm(rechargeModel);
            }catch (Exception e){
                e.printStackTrace();
            } finally {
               redisRepository.unlockSetnx(key,value);
            }
        }
}

你可能感兴趣的:(2020年技术总结——JAVA篇)