当前位置: 首页 > 面试题库 >

将数据从字典批量设置为Redis

程和煦
2023-03-14
问题内容

我正在使用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除非纯粹出于您的目的,否则无需锁定an ;SE.Redis内部处理线程安全,旨在供竞争线程使用
  • 目前,您的时间将包括所有序列化代码(JsonConvert.SerializeObject);这将加起来, 尤其是 当您的对象很大时;得到一个体面的措施,我强烈建议你的时间序列化和Redis的时间 分别
  • batch.Execute()方法使用管道API,并且不等待调用之间的响应,因此:您所看到的时间 不是 延迟的累积影响;只剩下本地CPU(用于序列化),网络带宽和服务器CPU;客户端库工具不会影响任何这些事情
  • 有一个StringSet接受的重载KeyValuePair<RedisKey, RedisValue>[]; 您 可以 选择使用它而不是批处理,但是这里唯一的区别是,它是方尖的MSET而不是多重的SET;无论哪种方式,您都将在此时间内阻止其他调用者的连接(因为批处理的目的是使命令连续)
  • 实际上 不需要在CreateBatch这里使用, 尤其是 因为您正在锁定数据库(但是我仍然建议您不需要这样做);的目的CreateBatch是使一系列命令 顺序化 ,但是我看不到您在这里需要这个;您可以只_database.StringSetAsync依次使用每个命令,这 具有与发送前一条命令 并行 运行序列化的优势-它可以让您重叠序列化(绑定CPU)和redis ops(绑定IO)除删除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));
    }
}


 类似资料:
  • 假设我想要一个变量包含从1到100的数字。我可以这样做: 但是把所有这些数字写下来需要很多时间。有没有办法给这个变量设置一个范围?类似的东西: 这听起来可能是一个非常愚蠢的问题,但我自己还没有弄清楚。提前感谢。

  • 用于自定义云管平台中常用菜单的显示名称。 该功能用于自定义系统菜单名称,全局生效,修改后系统菜单以及与菜单项有关的参数都以当前值显示为准。 目前支持修改的菜单项有认证源、域、组、用户、项目、角色、权限。 入口:在云管平台单击左上角导航菜单,在弹出的左侧菜单栏中单击 “系统配置/全局设置/字典设置” 菜单项,进入字典设置页面。 字典设置 在字典列表中,单击key对应的当前值图标,弹性修改当前值对话框

  • 问题内容: 我有如下的Python字典: 键是Unicode日期,值是整数。我想通过将日期及其对应的值作为两个单独的列将其转换为pandas数据框。示例:col1:日期col2:DateValue(日期仍为Unicode,日期值仍为整数) . 对此方向的任何帮助将不胜感激。我找不到有关熊猫文档的资源来帮助我。 我知道一种解决方案可能是将此dict中的每个键值对转换为dict,以便整个结构成为dic

  • 问题内容: 是否可以通过python中的字典创建对象,使得每个键都是该对象的属性? 像这样: 问题答案: 当然,是这样的: 更新资料 正如布伦特·纳什(Brent Nash)所建议的那样,您还可以通过允许使用关键字参数来使其更加灵活: 然后您可以这样称呼它: 或像这样: 甚至像这样:

  • 问题内容: 更新 :对于最新的Angular版本,该问题已过时,请参阅tsh对此职位的评论 我已经将复选框绑定到一个值: 控制器中复选框的值设置为1: 但是,最初该复选框未显示为选中状态。如果我将的初始值更改为,则可以。(jsfiddle演示) 我尝试了各种变化: 他们都不工作。如何使angular将参数视为数字? 问题答案: 您可以使用 ngChecked ,如果表达式为真,则将在元素上设置特殊

  • abilities - 所有权限节点 ability_role - 用户组权限 advertising - 广告列表 advertising_space - 广告位 answer_onlooker - 被围观的答案 answers - 答案 areas - 地区配置 around_amaps - 用户坐标 certification_categories - 认证分类 certifications