gpt4 book ai didi

c# - 线程环境下的redis不一致

转载 作者:可可西里 更新时间:2023-11-01 11:20:00 24 4
gpt4 key购买 nike

在线程环境中运行时,我遇到了 redis 的一些问题。

我有一个名为 AwaitableParallelForeachWorker 的类,我可以在其中为有效负载中的每个项目运行特定函数。 (我知道它不漂亮,但它完成了工作)

 public class AwaitableParallelForeachWorker : IAwaitableParallelForeachWorker
{
private readonly object _lockObject = new object();
private int _tasksCompleted;

public async Task Run<T>(Func<T, Task> action, IEnumerable<T> payload)
{
var list = payload.ToList();
var tasks = list.Select(x => new Task(async () =>
{
await action(x);
TaskDone();
}));
Parallel.ForEach(tasks, task => task.Start());
while (_tasksCompleted < list.Count)
{
await Task.Delay(10);
}
}

public void TaskDone()
{
lock (_lockObject)
{
_tasksCompleted++;
}
}
}

这里是redis缓存代码:

 public class NewsappRedisCache : INewsappRedisCache
{
private static readonly string ConnectionString = ConfigurationManager.AppSettings["RedisCache"];

private static readonly Lazy<ConnectionMultiplexer> LazyConnection =
new Lazy<ConnectionMultiplexer>(() => ConnectionMultiplexer.Connect(ConnectionString));

private static IDatabase MimerArticleDatabase => Connection.GetDatabase(2);

public async Task<MimerArticle> GetMimerArticleAsync(Guid id)
{
var redisValue = await MimerArticleDatabase.StringGetAsync($"{nameof(MimerArticle)}-{id}");
if (!redisValue.HasValue) return null;
var mimerArticle = JsonConvert.DeserializeObject<MimerArticle>(redisValue.ToString());
return mimerArticle;
}

我编写了这个简单的测试,它使用 AwaitableParallelForeachWorker 调用我的 redis 缓存 1000 次

  public class Test
{
private NewsappRedisCache _redisCache;

[Fact]
public async void TestRedis()
{
var guids = new List<Guid>();

for (var i = 0; i < 1000; i++)
{
guids.Add(Guid.NewGuid());
}

_redisCache = new NewsappRedisCache();
await new AwaitableParallelForeachWorker().Run(CallRedis, guids);
}

private async Task CallRedis(Guid id)
{
await _redisCache.GetMimerArticleAsync(id);
}
}

现在变得奇怪了。有时 1000 gets 到 redis 缓存是在一瞬间执行的。我已经通过检查 azure 门户验证了获取实际上命中了缓存。但有时每次获取大约需要 1 秒。

我不知道为什么。我已经尝试更改 AwaitableParallelForeachWorker 的功能,但它始终不一致。如果我在正常的 foreach 中运行每个 get,它执行得很好,但不如 AwaitableParallelForeachWorker 实际工作时快。

所以我一直认为它与线程/任务有关。

谁能提供一些帮助?

最佳答案

我找不到确切的原因,但我也无法将其放入评论中,因此需要考虑以下几点:

  • 测试方法不应该是async Task,而不是async void吗?一些测试框架可以处理这种有争议的不正确用法,但您的可能不会。如果框架无法知道方法何时完成,它会认为在第一个 await 时一切都已完成。

  • 您的 Run() 方法可以显着简化为:

    public Task Run<T>(Func<T, Task> action, IEnumerable<T> payload)
    {
    return Task.WhenAll(payload.Select(action));
    }

    并摆脱类(class)的其余部分。

  • 您的 CallRedis() 方法不需要状态机开销;相反:

    private Task CallRedis(Guid id)
    {
    return _redisCache.GetMimerArticleAsync(id);
    }
  • 在我为您节省台词的同时:

    var guids = Enumerable.Range(0, 1000).Select(Guid.NewGuid()).ToList();
    // :)

关于c# - 线程环境下的redis不一致,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39657733/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com