• 设为首页
  • 收藏本站
  • 积分充值
  • VIP赞助
  • 手机版
  • 微博
  • 微信
    微信公众号 添加方式:
    1:搜索微信号(888888
    2:扫描左侧二维码
  • 快捷导航
    福建二哥 门户 查看主题

    Redis高效查询大数据的实践与优化详细指南

    发布者: 雪落无声 | 发布时间: 2025-6-19 12:39| 查看数: 101| 评论数: 0|帖子模式

    1. 引言

    Redis 是一种高性能的键值存储数据库,广泛应用于缓存、排行榜、计数器等场景。在实际业务中,我们经常需要查询符合特定条件的数据,例如找出 value 大于某个阈值(如 10)的键值对。然而,直接遍历所有键并使用 GET 命令逐个检查可能会导致性能问题,尤其是当数据量较大时。
    本文将围绕 如何高效查询 Redis 中满足条件的数据 展开讨论,从最初的简单实现到优化后的高效方案,并结合 Java 代码示例,帮助开发者掌握 Redis 数据查询的最佳实践。

    2. 问题背景

    假设我们有以下需求:
    Redis 数据库 DB1(-n 1)存储了大量形如 flow:count:1743061930:* 的键。
    需要找出其中 value > 10 的所有键值对,并统计总数。
    初始实现方案
    最初的 Shell 脚本如下:
    1. redis-cli -h 10.206.0.16 -p 6379 -n 1 --scan --pattern "flow:count:1743061930:*" | \while read key; do  value=$(redis-cli -h 10.206.0.16 -p 6379 -n 1 GET "$key")  if [ "$value" != "1" ]; then    echo "$key: $value"  fidone | tee /dev/stderr | wc -l | awk '{print "Total count: " $1}'
    复制代码
    该方案的问题:
    多次 Redis 查询:每个键都要单独执行 GET,网络开销大。
    Shell 字符串比较低效:[ "$value" != "1" ] 是字符串比较,数值比较更合适。
    管道过多:tee、wc、awk 多个管道影响性能。

    3. 优化方案


    3.1 优化 Shell 脚本

    优化后的版本:
    1. redis-cli -h 10.206.0.16 -p 6379 -n 1 --scan --pattern "flow:count:1743061930:*" | \while read key; do  redis-cli -h 10.206.0.16 -p 6379 -n 1 GET "$key"done | \awk '$1 > 10 {count++; print} END {print "Total count: " count}'
    复制代码
    优化点:

    • 减少 Redis 命令调用:直接批量获取 value,减少网络开销。
    • 使用 awk 进行数值比较:$1 > 10 比 Shell 字符串比较更高效。
    • 合并计数逻辑:awk 同时完成过滤、输出和计数。
    如果仍需保留键名:
    1. redis-cli -h 10.206.0.16 -p 6379 -n 1 --scan --pattern "flow:count:1743061930:*" | \while read key; do  value=$(redis-cli -h 10.206.0.16 -p 6379 -n 1 GET "$key")  echo "$key: $value"done | \awk -F': ' '$2 > 10 {count++; print} END {print "Total count: " count}'
    复制代码
    3.2 使用 Redis Pipeline 优化

    Shell 脚本仍然存在多次 GET 的问题,我们可以使用 Redis Pipeline 批量获取数据,减少网络往返时间。
    优化后的 Shell + Pipeline 方案
    1. redis-cli -h 10.206.0.16 -p 6379 -n 1 --scan --pattern "flow:count:1743061930:*" | \xargs -I {} redis-cli -h 10.206.0.16 -p 6379 -n 1 MGET {} | \awk '$1 > 10 {count++; print} END {print "Total count: " count}'
    复制代码
    这里使用 xargs + MGET 批量获取 value,减少网络请求次数。

    4. Java 实现方案

    在 Java 应用中,我们可以使用 Jedis 或 Lettuce 客户端优化查询。

    4.1 使用 Jedis 查询
    1. import redis.clients.jedis.Jedis;
    2. import redis.clients.jedis.ScanParams;
    3. import redis.clients.jedis.ScanResult;
    4. import java.util.List;

    5. public class RedisValueFilter {
    6.     public static void main(String[] args) {
    7.         String host = "10.206.0.16";
    8.         int port = 6379;
    9.         int db = 1;
    10.         String pattern = "flow:count:1743061930:*";
    11.         int threshold = 10;

    12.         try (Jedis jedis = new Jedis(host, port)) {
    13.             jedis.select(db);

    14.             ScanParams scanParams = new ScanParams().match(pattern).count(100);
    15.             String cursor = "0";
    16.             int totalCount = 0;

    17.             do {
    18.                 ScanResult<String> scanResult = jedis.scan(cursor, scanParams);
    19.                 List<String> keys = scanResult.getResult();
    20.                 cursor = scanResult.getCursor();

    21.                 // 批量获取 values
    22.                 List<String> values = jedis.mget(keys.toArray(new String[0]));

    23.                 // 过滤并统计
    24.                 for (int i = 0; i < keys.size(); i++) {
    25.                     String key = keys.get(i);
    26.                     String valueStr = values.get(i);
    27.                     if (valueStr != null) {
    28.                         int value = Integer.parseInt(valueStr);
    29.                         if (value > threshold) {
    30.                             System.out.println(key + ": " + value);
    31.                             totalCount++;
    32.                         }
    33.                     }
    34.                 }
    35.             } while (!cursor.equals("0"));

    36.             System.out.println("Total count: " + totalCount);
    37.         }
    38.     }
    39. }
    复制代码
    优化点:

    • 使用 SCAN 代替 KEYS,避免阻塞 Redis。
    • 使用 MGET 批量查询,减少网络开销。
    • 直接数值比较,提高效率。

    4.2 使用 Lettuce(异步非阻塞)

    Lettuce 是高性能 Redis 客户端,支持异步查询:
    1. import io.lettuce.core.*;
    2. import io.lettuce.core.api.sync.RedisCommands;
    3. import java.util.List;

    4. public class RedisLettuceQuery {
    5.     public static void main(String[] args) {
    6.         RedisURI uri = RedisURI.create("redis://10.206.0.16:6379/1");
    7.         RedisClient client = RedisClient.create(uri);

    8.         try (RedisConnection<String, String> connection = client.connect()) {
    9.             RedisCommands<String, String> commands = connection.sync();
    10.             String pattern = "flow:count:1743061930:*";
    11.             int threshold = 10;
    12.             int totalCount = 0;

    13.             ScanCursor cursor = ScanCursor.INITIAL;
    14.             do {
    15.                 ScanArgs scanArgs = ScanArgs.Builder.matches(pattern).limit(100);
    16.                 KeyScanCursor<String> scanResult = commands.scan(cursor, scanArgs);
    17.                 List<String> keys = scanResult.getKeys();
    18.                 cursor = ScanCursor.of(scanResult.getCursor());

    19.                 // 批量获取 values
    20.                 List<KeyValue<String, String>> keyValues = commands.mget(keys.toArray(new String[0]));

    21.                 for (KeyValue<String, String> kv : keyValues) {
    22.                     if (kv.hasValue()) {
    23.                         int value = Integer.parseInt(kv.getValue());
    24.                         if (value > threshold) {
    25.                             System.out.println(kv.getKey() + ": " + value);
    26.                             totalCount++;
    27.                         }
    28.                     }
    29.                 }
    30.             } while (!cursor.isFinished());

    31.             System.out.println("Total count: " + totalCount);
    32.         } finally {
    33.             client.shutdown();
    34.         }
    35.     }
    36. }
    复制代码
    优势:
    非阻塞 I/O,适合高并发场景。
    支持 Reactive 编程(如 RedisReactiveCommands)。

    5. 性能对比

    方案查询方式网络开销适用场景原始 Shell单 GET 遍历高少量数据优化 Shell + awk批量 GET中中等数据量Shell + PipelineMGET 批量低大数据量Java + JedisSCAN + MGET低生产环境Java + Lettuce异步 SCAN最低高并发
    6. 结论


    • 避免 KEYS 命令:使用 SCAN 替代,防止阻塞 Redis。
    • 减少网络请求:使用 MGET 或 Pipeline 批量查询。
    • 数值比较优化:用 awk 或 Java 直接比较数值,而非字符串。
    • 生产推荐:Java + Jedis/Lettuce 方案,适合大规模数据查询。
    通过优化,我们可以显著提升 Redis 大数据查询的效率,降低服务器负载,适用于高并发生产环境。
    到此这篇关于Redis高效查询大数据的实践与优化详细指南的文章就介绍到这了,更多相关Redis查询数据内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

    来源:https://www.jb51.net/database/339326lk6.htm
    免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

    最新评论

    浏览过的版块

    QQ Archiver 手机版 小黑屋 福建二哥 ( 闽ICP备2022004717号|闽公网安备35052402000345号 )

    Powered by Discuz! X3.5 © 2001-2023

    快速回复 返回顶部 返回列表