Impala推送数据到Redis及String.valueOf()生产问题踩坑

背景

Impala数据推送到Redis,平台业务使用方反馈插入到Redis的数据不对:
在这里插入图片描述
Redis插入key没有问题;value是0.6nul有问题,正常的数据应该是0.6

排查

往Redis里面写数据的代码片段如下:

private void pushToRedis(Map query, List<Map<String, Object>> datalist) {
	if (CollectionUtils.isEmpty(datalist)) {
    	return null;
    }
	JedisCluster redisCluster = this.getConnection();
    String[] columnArr = (query.get(COLUMN) + "").replace("\n", "").replace(" ", "").split(",");
    String keyTo = String.valueOf(query.get("keyTo"));
    
    String valueSplit = String.valueOf(query.get("valueSplit"));
    if (StringUtils.isEmpty(valueSplit)) {
        // 默认分隔符
        valueSplit = ",";
    }
    // Redis key过期时间
    Object redisExpireObj = query.get("redisExpire");
    SetParams setParams;
    if (StringUtils.isNotEmpty(redisExpireObj)) {
        setParams = SetParams.setParams().ex(Integer.parseInt(redisExpireObj + ""));
    } else {
    	// 永不过期,待优化
        setParams = SetParams.setParams();
    }
    for (Map<String, Object> item : datalist) {
        StringBuilder sb = new StringBuilder();
        for (String s : columnArr) {
        	// 以指定的分隔符拼接String形式的Redis value
            sb.append(item.get(s)).append(valueSplit);
        }
        // 从
        String objectKey = String.valueOf(item.get(keyTo));
        // 去掉最后一个分隔符
        redisCluster.set(objectKey, sb.substring(0, sb.toString().length() - 1), setParams);
    }
}

此方法接收两个参数:

  • datalist是从Impala中查询得到的数据,数据有多条,故而用List包装。每一条数据对应数据表的一行记录,使用Map自是必然的,key对应表字段,value对应该字段具体的数据,数据有多种类型,故而统一使用Object。
  • Map<String, Object>类型的query里面则存储着数据推送到Redis时的一些信息,比如过期时间redisExpire,如Redis集群的appId(使用开源组件CacheCloud来维护及管理Redis集群),this.getConnection()方法就是通过appId连接到对应的集群,比如需要往什么Key写数据,比如value组合时使用什么分隔符。

附:

private JedisCluster getConnection(Map<String, Object>) {
    long appId = Long.parseLong(query.get("appId"));
    return ClientBuilder.redisCluster(appId)
            .setJedisPoolConfig(getPoolConfig())
            .setConnectionTimeout(2000)
            .setSoTimeout(1000)
            .build();
}

其结果来自于如下SQL语句:

select concat('fqz_appscore_list_yxd:', cast(appname AS string) ) as keyname, appscore from fqz.Yxd_AppScore_List;

在Impala 查询平台执行上述SQL,获取得到的数据,无论是key,还是value都是正常的。value没有带多余的nul

说明Impala数据源是正常的。

问题出现在推送到Redis的逻辑代码处,即上面的Java代码。

而key是没有问题,只是value有问题,最终落值的value为: sb.substring(0, sb.toString().length() - 1

中间赋值的地方为:sb.append(item.get(s)).append(valueSplit);

说明,问题在于这个valueSplit。再看下数据库原始数据,即Map query这个map。

{
    "redisExpire": "172800",
    "column": "appscore",
    "keyTo": "keyname"
  }

并没有valueSplit这个字段,query.get("valueSplit")的结果为null,好家伙!!

再看下String.valueOf()源码:

/**
 * Returns the string representation of the Object argument.
 */
public static String valueOf(Object obj) {
    return (obj == null) ? "null" : obj.toString();
}

问题定位到。

如何解决呢?

String valueSplit = String.valueOf(query.get("valueSplit"));
if (StringUtils.isEmpty(valueSplit) || "null".equalsIgnoreCase(valueSplit)) {
    // 默认分隔符
    valueSplit = ",";
}

参考

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

johnny233

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值