You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Redis JSON全量取值函数性能优化方案咨询

现有函数

public IQueryable<T> getAllPositions<T>(RedisDbs redisDbKey)
{
    List<T> positions = new List<T>();
    List<string> keys = new List<string>();

    foreach (var key in _redisServer.Keys((int)redisDbKey))
    {
        keys.Add(key.ToString());
    }

    var sportEventRet = _redis.GetDatabase((int)redisDbKey).JsonMultiGetAsync(keys.ToArray());
    foreach (var sportEvent in sportEventRet.Result)
    {
        var redisValue = (RedisValue)sportEvent;
        if(!redisValue.IsNull)
        {
            var positionEntity = JsonConvert.DeserializeObject<T>(redisValue, jsonSerializerSettings);
            positions.Add(positionEntity);
        }
    }
    return positions.AsQueryable();
}

调用方式

IQueryable<IPosition> union = redisClient.getAllPositions<Position>(RedisDbs.POSITIONDB);

问题背景

Position是仅包含少量简单属性的模型,RedisDbs是代表特定数据库编号的枚举。在本地高性能服务器上,该函数查询20k条Redis JSON数据耗时2秒,需优化至最长1秒、最好600毫秒以内。

可行优化方案

  • 异步改造消除阻塞:将方法改为异步签名public async Task<IQueryable<T>> getAllPositionsAsync<T>(RedisDbs redisDbKey),用await sportEventRet替代sportEventRet.Result,避免线程阻塞导致的资源浪费,提升并发效率。
  • 替换Keys命令为Scan命令:Redis的Keys命令会全量遍历数据库,数据量越大耗时越长,改用Scan分批次迭代获取键,避免阻塞Redis实例,同时降低单次内存占用。
  • 预分配List容量:初始化List<T>和List<string>时指定初始容量(比如20000),避免List因扩容频繁触发内存分配和数据拷贝,提升内存操作效率。
  • 并行处理反序列化:反序列化属于CPU密集型操作,用Parallel.ForEach处理Redis返回的结果,充分利用多核CPU资源,缩短序列化耗时。注意使用线程安全的集合或拆分任务保证线程安全。
  • 替换JSON序列化库:将Newtonsoft.Json的JsonConvert替换为System.Text.Json,后者对简单模型的序列化/反序列化性能更优,尤其在.NET Core/.NET 5+环境下。
  • 分批次批量获取键值:将Scan和JsonMultiGet结合,每批次获取1000条左右的键值,避免单次请求传递过大的键数组,减少Redis服务器处理压力和网络传输开销。
  • 优化Redis连接池配置:确保连接池的最小/最大连接数设置合理,避免因连接不足导致的等待时间,同时启用连接复用,减少连接建立的开销。
  • 调整数据存储结构:如果所有Position属于同一业务集合,可改用Redis Hash结构(键为数据ID,值为JSON),或使用RedisJSON的批量查询语法,进一步提升批量读取效率。

内容的提问来源于stack exchange,提问作者user3533755

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 04:45:31