NewLifeX / NewLife.Redis

High performance redis client, support NETCore/. NET4. 0/. NET4. 5. It is specially optimized for big data and message queue. The average daily consumption of online single application is 10 billion. 高性能Redis客户端,支持.NETCore/.NET4.0/.NET4.5,为大数据与消息队列而特别优化,线上单应用日均100亿调用量

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

使用RedisHash对象HMGet方法获取对象内单个记录时偶然性报错,版本5.5.2023.1201

MCBGBG opened this issue · comments

我这里有一个简单的封装用于获取Redis Hash类型存储的单个记录,如下

public T HashGetOne<T>(string key, string field)
{
      RedisHash<string, T> hash = GetHashMap<T>(key);
      var result = hash.HMGet(field);
      return result[0];
}

但是该方法会偶尔抛出异常 Object reference not set to aninstance of an object,我通过断点调试看到 hash 对象内存在一条记录,并且key 就是我传入的 field, 但是 HMGet 方法并没有按预期返回,而是返回了 null。

image001

包版本: 5.5.2023.1201
.NET版本: 6

请问我需要如何解决这个问题。

redis.Log =XTrace.Log 打开日志,看看抛异常时redis返回报文内容是怎么样的。
如果日志实在过多,只能借助星尘监控来记录这个场景下的数据,进而分析问题。

redis.Log =XTrace.Log 打开日志,看看抛异常时redis返回报文内容是怎么样的。 如果日志实在过多,只能借助星尘监控来记录这个场景下的数据,进而分析问题。

我改造了方法。

public T HashGetOne<T>(string key, string field)
{
    var hash = GetHashMap<T>(key);
    var result = HMGet(hash, field);
    return result[0];
}

public static T[] HMGet<T>(RedisHash<string, T> hash, params string[] fields)
{
    List<object> args = [hash.Key, .. fields];

    return hash.Execute((RedisClient r, string k) =>
    {
        var res = r.Execute<T[]>("HMGET", [.. args]);
        return res ?? throw new NullReferenceException();
    });
}

image
我尝试使用 redis.Log =XTrace.Log,但是没有生效,不过我将HMGet方法拿出来了,我发现返回空值的是 Execute 方法。

设置Log日志,并不是为了解决你的问题,而是把日志打印出来,辅助分析问题

今天遇到类似的异常,经排查是因为HASH里面部分的Filed值为空值,例如:

127.0.0.1:6379[6]> HGETALL "100656"
1) "CompanyID"
2) "25"
3) "Name"
4) "aabbcc"
5) "Secret"
6) "12345678"
7) "ApiCmId"             <-------
8) ""                           <-------

如果获取Filed为"ApiCmId"的值则会报 “Object reference not set to aninstance of an object”

这应该是一个Bug,因为HASH的值是允许为空值的。

感谢反馈,从错误信息得知,空引用来自RedisBase.FromBytes,并且是返回为空字符串。

问题已修复!
代码已推送!
后台正自动发布nuget……