gpt4 book ai didi

c# - 将字典中的数据批量设置到 Redis

转载 作者:IT王子 更新时间:2023-10-29 06:03:07 24 4
gpt4 key购买 nike

我正在使用 StackExchange Redis DB 使用 Batch 插入键值对字典,如下所示:

private static StackExchange.Redis.IDatabase _database;
public void SetAll<T>(Dictionary<string, T> data, int cacheTime)
{
lock (_database)
{
TimeSpan expiration = new TimeSpan(0, cacheTime, 0);
var list = new List<Task<bool>>();
var batch = _database.CreateBatch();
foreach (var item in data)
{
string serializedObject = JsonConvert.SerializeObject(item.Value, Formatting.Indented,
new JsonSerializerSettings { ContractResolver = new SerializeAllContractResolver(), ReferenceLoopHandling = ReferenceLoopHandling.Ignore });

var task = batch.StringSetAsync(item.Key, serializedObject, expiration);
list.Add(task);
serializedObject = null;
}
batch.Execute();

Task.WhenAll(list.ToArray());
}
}

我的问题:仅设置 350 个字典项需要大约 7 秒

我的问题:这是将批量项目设置到 Redis 中的正确方法还是有更快的方法?任何帮助表示赞赏。谢谢。

最佳答案

“只是”是一个非常相对的术语,如果没有更多的上下文,尤其是:这些有效载荷有多大?

但是,澄清几点以帮助您调查:

  • 无需锁定 IDatabase除非那纯粹是为了您自己的目的; SE.Redis 在内部处理线程安全,旨在供竞争线程使用
  • 目前,您的时间安排将包括所有序列化代码 ( JsonConvert.SerializeObject );这将加起来,尤其是如果您的对象很大;为了获得合适的衡量标准,我强烈建议您分别
  • 对序列化时间和 redis 时间进行计时
  • batch.Execute()方法使用管道 API 并且不等待调用之间的响应,因此:您看到的时间不是延迟的累积效应;只剩下本地 CPU(用于序列化)、网络带宽和服务器 CPU;客户端库工具不会影响任何这些事情
  • 有一个StringSet接受 KeyValuePair<RedisKey, RedisValue>[] 的重载;您可以选择使用它而不是批处理,但这里唯一的区别是它是 varadic MSET而不是多个 SET ;无论哪种方式,您都将在持续时间内阻止其他调用者的连接(因为批处理的目的是使命令连续)
  • 实际上不需要使用CreateBatch在这里,尤其是,因为您要锁定数据库(但我仍然建议您不需要这样做); CreateBatch的目的|是制作一系列命令顺序,但我看不出你在这里需要这个;你可以使用 _database.StringSetAsync对于每个命令依次执行,这的优点是您可以并行运行序列化之前发送的命令 - 它可以让您重叠序列化( CPU 绑定(bind))和 redis ops(IO 绑定(bind))除了删除 CreateBatch 之外没有任何工作称呼;这也意味着您不会独占其他调用者的连接

所以; 我要做的第一件事删除一些代码:

private static StackExchange.Redis.IDatabase _database;
static JsonSerializerSettings _redisJsonSettings = new JsonSerializerSettings {
ContractResolver = new SerializeAllContractResolver(),
ReferenceLoopHandling = ReferenceLoopHandling.Ignore };

public void SetAll<T>(Dictionary<string, T> data, int cacheTime)
{
TimeSpan expiration = new TimeSpan(0, cacheTime, 0);
var list = new List<Task<bool>>();
foreach (var item in data)
{
string serializedObject = JsonConvert.SerializeObject(
item.Value, Formatting.Indented, _redisJsonSettings);

list.Add(_database.StringSetAsync(item.Key, serializedObject, expiration));
}
Task.WhenAll(list.ToArray());
}

我要做的第二件事是将序列化与 redis 工作分开计时。

我要做的第三件事是看看我是否可以序列化为 MemoryStream相反,理想情况下我可以重复使用 - 避免 string分配和 UTF-8 编码:

using(var ms = new MemoryStream())
{
foreach (var item in data)
{
ms.Position = 0;
ms.SetLength(0); // erase existing data
JsonConvert.SerializeObject(ms,
item.Value, Formatting.Indented, _redisJsonSettings);

list.Add(_database.StringSetAsync(item.Key, ms.ToArray(), expiration));
}
}

关于c# - 将字典中的数据批量设置到 Redis,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44585100/

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