redis-管道

本文详细阐述了在处理大量Redis数据时,从逐条命令写入到利用Pipeline批量处理的性能提升过程,以及背后的原理分析。通过优化连接管理和命令执行方式,显著减少了写入时间,从24分钟降至8秒,揭示了Redis CS模式下TCP请求响应协议的特性及其对性能的影响。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

注意到redis写入慢的问题

开始发现问题是因为发现写入redis越来越慢

刚开始做法

for {

//获取redis连接,

//写入一条

//释放连接

}

这样子3w条redis数据 需要24分钟

 

第一次尝试

修改逻辑为只获得一次连接

//获取redis连接

for{

//写入一条

}

//释放连接

速度有了提高 但是仍在5分钟左右

 

最终解决方案

//获取redis连接

//创建管道

for{

//写入管道

}

//将管道数据写入redis

 

速度显著提高 插入3w条数据 只需要8秒

 

原因

  • redis和java项目不在同一台服务器 建立连接开销比在同一台物理机大得多 这是前提
  • redis是一个cs模式的tcp server,使用和http类似的请求响应协议。一个client可以通过一个socket连接发起多个请求命令。每个请求命令发出后client通常会阻塞并等待redis服务处理,redis处理完后请求命令后会将结果通过响应报文返回给client.基本上四个命令需要8个tcp报文才能完成。由于通信会有网络延迟,假如从client和server之间的包传输时间需要0.125秒。那么上面的四个命令8个报文至少会需要1秒才能完成。这样即使redis每秒能处理100个命令,而我们的client也只能一秒钟发出四个命令。这显示没有充分利用 redis的处理能力。除了可以利用mget,mset 之类的单条命令处理多个key的命令外我们还可以利用pipeline的方式从client打包多条命令一起发出,不需要等待单条命令的响应返回,而redis服务端会处理完多条命令后会将多条命令的处理结果打包到一起返回给客户端。


解决方案代码

Jedis client = jedisPool.getResource();

try {
   Pipeline pipeline = client.pipelined();
 for (String key:inMap.keySet()){
      Map<String , String> valueMap = inMap.get(key);
  pipeline.hmset(key, valueMap);
  pipeline.expire(key, 60*60);
 }

   pipeline.sync();

}catch (Exception e){
   logger.error("inser into redis error!", e);
}finally {
   jedisPool.returnResource(client);
}

<think>好的,用户遇到了一个错误,当尝试使用管道导入数据到Redis时,命令报错“ERR unknown command '#'”。需要先理解这个错误的原因,然后找出解决方案。 首先,用户使用的命令是:cat redis_data.txt | redis-cli -p 6379 -a yourpassword --pipe。错误提示指出Redis服务器无法识别以#开头的命令,这说明在redis_data.txt文件中可能存在以#开头的行,被Redis误认为是命令。而实际上,这些行可能是注释,但Redis协议不支持注释,因此在数据文件中不应包含这些内容。 接下来需要确认数据文件的格式是否符合Redis协议要求。Redis管道传输需要严格按照RESP(Redis序列化协议)格式,每一条命令必须以正确的格式编码,比如使用*后面跟参数个数,然后是每个参数的$长度和值。如果文件中包含注释或不符格式的内容,就会导致解析错误。 解决方法包括: 1. 清理数据文件中的注释行,删除所有以#开头的行,可以使用sed或grep命令处理。 2. 检查文件中的命令是否符合RESP格式,可能需要使用redis-cli的--pipe选项正确生成数据文件。 3. 确保密码正确,且Redis服务器配置允许该连接,比如可能需要调整bind设置或保护模式。 另外,需要注意在命令行中直接使用-a参数可能存在安全风险,建议通过环境变量或输入提示来传递密码。如果问题仍然存在,可能需要更详细地检查数据文件的每一行,或者使用redis-cli的--pipe选项结合其他工具来验证数据格式的正确性。 总结步骤应该是:处理注释行,验证数据格式,调整Redis配置,最后重新运行导入命令。同时提醒用户注意密码安全,避免在命令中明文显示密码。</think>从错误信息 `ERR unknown command '#'` 可以看出,您的 `redis_data.txt` 文件中存在以 `#` 开头的行(可能是注释),而 Redis 将 `#` 识别为未知命令。Redis 协议不支持注释行,直接通过管道导入时需确保数据格式严格遵守 Redis 序列化协议(RESP)。 以下是分步解决方案: --- ### **步骤 1:清理数据文件** 使用 `grep` 或 `sed` 删除所有注释行: ```bash # 删除以 # 开头的行 grep -v '^#' redis_data.txt > redis_data_clean.txt # 或使用 sed sed '/^#/d' redis_data.txt > redis_data_clean.txt ``` --- ### **步骤 2:验证数据格式** Redis 协议要求每条命令按以下格式编码: ``` *<参数数量>\r\n $<参数1的长度>\r\n <参数1>\r\n $<参数2的长度>\r\n <参数2>\r\n ... ``` 例如,命令 `SET key value` 应编码为: ``` *3\r\n$3\r\nSET\r\n$3\r\nkey\r\n$5\r\nvalue\r\n ``` 若数据文件未按此格式生成,推荐使用 `redis-cli --pipe` 生成合法数据: ```bash # 生成测试文件 echo "SET mykey 123" | redis-cli --pipe > redis_data.txt ``` --- ### **步骤 3:调整 Redis 配置** 确保 Redis 服务器允许连接: 1. 检查密码是否正确(`-a yourpassword`)。 2. 检查 `bind` 配置(默认 `127.0.0.1` 仅允许本地连接)。 3. 若远程连接,关闭保护模式(`protected-mode no`)并设置密码。 --- ### **步骤 4:重新执行导入命令** 使用清理后的文件重新导入: ```bash cat redis_data_clean.txt | redis-cli -p 6379 -a yourpassword --pipe ``` --- ### **补充说明** 1. **安全提示**:避免在命令行中明文显示密码,建议通过输入重载或环境变量传递: ```bash read -s REDIS_PASS && cat redis_data_clean.txt | redis-cli -p 6379 -a $REDIS_PASS --pipe ``` 2. **调试技巧**:添加 `-v` 参数查看详细输出: ```bash cat redis_data_clean.txt | redis-cli -p 6379 -a yourpassword --pipe -v ``` --- 通过以上步骤,可解决 `ERR unknown command '#'` 错误并完成数据导入。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值