一、业务场景
需要把用户导入的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 | |
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")
四、小结
出现问题后,需要冷静下来,找到问题的源头,再对症下药,不要自乱阵脚。