一、业务场景

需要把用户导入的excel数据存到redis,后期再入数据库。一开始都没有问题,后期出于性能考虑使用了pipeline来优化性能。但是却出现了本地操作没问题,一旦部署到服务器,就出现中文乱码的问题。

定位问题,大概率是在使用了pipeline后导致的异常。

二、原始代码及原因

使用pipeline插入zSet数据的代码如下:

1
public void executePipelined(String key, Map<Integer, String> map) {
2
    RedisSerializer<String> serializer = redisTemplate.getStringSerializer();
3
    redisTemplate.executePipelined(new RedisCallback<String>() {
4
           @Override
5
           public String doInRedis(RedisConnection connection) {
6
               map.forEach((score, value) -> {
7
               		connection.zSetCommands().zAdd(key.getBytes(), score, value.getBytes());
8
               });
9
               return null;
10
           }
11
       },serializer);
12
}

因为connection.zSetCommands().zAdd()这里需要传入byte[]的参数,因此考虑到问题应该出现在key.getBytes()上,经过查询,了解到String.getBytes()使用的操作系统的默认的字符集将字符串编码为byte序列,因此,这个就导致了为什么本地windows没问题,Linux服务器上的中文乱码了。

三、解决方法

因此,我们传入特定的编码格式即可解决此问题。代码如下:

1
public String doInRedis(RedisConnection connection) {
2
    map.forEach((score, value) -> {
3
        try {
4
            connection.zSetCommands().zAdd(key.getBytes("UTF-8"), score, value.getBytes("UTF-8"));
5
        } catch (UnsupportedEncodingException e) {
6
            e.printStackTrace();
7
        }
8
    });
9
    return null;
10
}

UTF-8传入即可,key.getBytes("UTF-8")

四、小结

出现问题后,需要冷静下来,找到问题的源头,再对症下药,不要自乱阵脚。