如何使 Redis 缓存中数据层次结构(树)的部分内容无效

2024-05-14

我有一些产品数据,需要在 Redis 缓存中存储多个版本。数据由 JSON 序列化对象组成。获取普通(基本)数据的过程很昂贵,将其定制为不同版本的过程也很昂贵,因此我想缓存所有版本以尽可能进行优化。数据结构看起来像这样:

                                    BaseProduct
                                         /\
                                      /      \
                                   /            \
                                /                  \
                             /                        \
           CustomisedProductA                          CustomisedProductB
                  /  \                                       /  \
CustomisedProductA1  CustomisedProductA2   CustomisedProductB1  CustomisedProductB2

这里的总体思路是:

  • 数据库中存储有一个基础产品。
  • 可以对该产品应用一级定制 - 例如有关该产品在某个销售区域的特定版本的信息。
  • 可以在其中应用第二级定制 - 例如某个地区内特定商店的有关该产品的信息。

数据以这种方式存储是因为数据检索/计算过程的每个步骤都很昂贵。第一次检索某个地区的特定产品时,将执行一组定制以使其成为特定于地区的产品。第一次为商店检索特定产品时,我需要根据区域产品执行自定义以生成商店特定的产品。

问题的出现是因为我可能需要通过几种方式使数据无效:

  • 如果基础产品数据发生变化,则整个树需要失效并且所有内容都需要重新生成。我可以通过将整个结构存储在哈希中并通过其键删除哈希来实现此目的 https://stackoverflow.com/questions/36741096/store-multiple-versions-of-data-in-redis-cache?noredirect=1#comment61064845_36741096.
  • 如果产品的第一组自定义发生变化(即中间级别),那么我也需要使该级别下面的节点无效。例如,如果 CustomizedProductA 的自定义项受到更改的影响,我需要使 CustomizedProductA、CustomizedProductA1 和 CustomizedProductA2 过期。
  • 如果产品的第二组自定义发生变化(即底层),则需要使该节点失效。我可以通过调用在哈希中实现此目的HDEL key field (e.g. HDEL product CustomisedProductA:CustomisedProductA1).

因此,我的问题是:是否有一种方法可以表示这种类型的多级数据结构,以允许在多个级别中存储数据,同时仅使树的部分内容失效?或者,我是否仅限于使整棵树过期(DEL key)或特定节点(HDEL key field)但中间没有什么?


至少有 3 种不同的方法可以做到这一点,每种方法都有自己的优点和缺点。

第一种方法是使用树的非原子临时扫描来识别树的第二层(第一组自定义)并使之无效(删除)。为此,请对哈希字段使用分层命名方案,并使用以下命令迭代它们HSCAN http://redis.io/commands/hscan。例如,假设您的哈希键名称是产品的 ID(例如 ProductA),您可以使用“0001:0001”之类的内容作为第一个自定义的第一个版本的字段名称,使用“0001:0002”作为其第二个版本的字段名称,等等。同样,“0002:0001”将是第二个自定义第一个版本,依此类推...然后,找到所有自定义 42 的版本,使用HSCAN ProductA 0 MATCH 0042:*, HDEL http://redis.io/commands/hdel回复中的字段,然后重复,直到光标归零。

相反的方法是主动“索引”每个自定义的版本,以便您可以有效地获取它们,而不是执行哈希的完整扫描。解决这个问题的方法是使用 Redis 的集合 - 您保留一个包含给定产品版本的所有字段名称的集合。版本可以是连续的(如我的示例),也可以是其他任何版本,只要它们是唯一的即可。成本在于维护这些索引 - 无论何时添加或删除产品的自定义和/或版本,您都需要保持与这些集合的一致性。例如,版本的创建类似于:

HSET ProductA 0001:0001 "<customization 1 version 1 JSON payload"
SADD ProductA:0001 0001

请注意,这两个操作应该在单个事务中(即使用MULTI\EXEC http://redis.io/topics/transactions块或EVAL http://redis.io/commands/evalLua 脚本)。当您完成此设置后,只需调用即可使自定义无效SMEMBERS http://redis.io/commands/SMEMBERS相关集并从哈希中删除其中的版本(以及集本身)。然而,值得注意的是,读取大型 Set 中的所有成员可能会非常耗时 - 1K 个成员并不是那么糟糕,但对于较大的 Set 来说,SSCAN http://redis.io/commands/sscan.

最后,您可以考虑使用有序集而不是哈希。虽然在此用例中可能不太直观,但排序集将允许您执行所需的所有操作。然而,使用它的代价是与哈希的 O(1) 相比,添加/删除/读取的 O(logN) 复杂性增加,但考虑到数字,差异并不显着。

为了释放排序集的力量,您将使用字典顺序,因此排序集的所有成员都应具有相同的分数(例如使用 0)。每个产品都将由一个排序集表示,就像哈希一样。 Set 的成员相当于 Hash 字段,即定制版本。 “技巧”是以允许您执行范围搜索(或如果您愿意的话,可以进行 2 级失效)的方式构造成员。下面是它应该是什么样子的示例(请注意,这里的键 ProductA 不是哈希而是排序集):

ZADD ProductA 0 0001:0001:<JSON>

要读取自定义版本,请使用ZRANGEBYLEX ProductA [0001:0001: [0001:0001:\xff http://redis.io/commands/zrangebylex并从回复中分离 JSON 并删除整个自定义,请使用ZREMRANGEBYLEX http://redis.io/commands/zremrangebylex.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何使 Redis 缓存中数据层次结构(树)的部分内容无效 的相关文章

  • Redis是如何实现高吞吐量和高性能的?

    我知道这是一个非常普遍的问题 但是 我想了解允许 Redis 或 MemCached Cassandra 等缓存 以惊人的性能极限工作的主要架构决策是什么 如何维持连接 连接是 TCP 还是 HTTP 我知道它完全是用C写的 内存是如何管理
  • 本地化 ASP.NET 资源的滑动过期

    假设我们有 2 个站点 myDomain AU 和 myDomain RU 具有相同的代码和本地化资源文件 resx 和 ru resx 我们预计大多数英语用户将使用 AU 网站 大多数俄语用户将使用 RU 网站 但是 如果 AU 域的某些
  • 我们如何计算这段代码片段中缓存的读取/未命中次数?

    鉴于我目前正在学习的这本教科书中的代码片段 Randal E Bryant David R O Hallaron 计算机系统 程序员的视角 第 3 版 2016 年 Pearson 全球版 因此本书的练习可能是错误的 for i 31 i
  • ASP.NET 中 HTTP 缓存相关标头的有效含义

    我正在 ASP NET 2 0 中开发一个 Web 应用程序 其中涉及通过资源处理程序 ashx 提供图像 我刚刚实现了处理缓存标头和条件 GET 请求 这样我就不必为每个请求提供所有图像 但我不确定我是否完全理解浏览器缓存发生了什么 图像
  • redis 2.8.7 Linux Sentinel环境配置问题,如何使其自启动,应该订阅什么?

    现在我们尝试使用 redis 2 8 7 作为缓存存储 来自使用 booksleeve 客户端的 NET Web 应用程序 目前看来这是一个非常有趣和令人兴奋的任务 redis 文档非常好 但由于缺乏真正的实践经验 我确实有几个关于如何正确
  • 想要在后台不间断地运行redis-server

    我已经下载了 redis 2 6 16 tar gz 文件并安装成功 安装后我运行 src redis server 它工作正常 但我不想每次都手动运行 src redis server 而是希望 redis server 作为后台进程持续
  • make_shared<>() 中的 WKWYL 优化是否会给某些多线程应用程序带来惩罚?

    前几天我偶然看到这个非常有趣的演示 http channel9 msdn com Events GoingNative GoingNative 2012 STL11 Magic Secrets作者 Stephan T Lavavej 其中提
  • 如何禁用 CRM 2011 Xrm 缓存?

    我的 crm 2011 缓存有问题 我不需要它 但我不知道如何禁用它 首先我生成这个 CrmSvcUtil exe codeCustomization Microsoft Xrm Client CodeGeneration CodeCust
  • 使用redis进行树形数据结构

    我需要为基于树的键值开发一个缓存系统 与Windows注册表编辑器非常相似 其中缓存键是字符串 表示树中到值的路径 可以是原始类型 int string bool double 等 或子树本身 例如 key root x y z w val
  • 如何缓存 twitter api 结果?

    我想缓存 twitter api 结果的结果并将其显示给用户 缓存结果的最佳方法是什么 我正在考虑根据时间限制将结果写入文件 可以吗 还是应该使用任何其他方法 最重要的是 理想的缓存时间是多少 我想显示来自 twitter 的最新内容 但
  • 如何将“.csv”数据文件导入Redis数据库

    如何将 csv 数据文件导入 Redis 数据库 csv 文件中包含 id 时间 纬度 经度 列 您能否向我建议导入 CSV 文件并能够执行空间查询的最佳方法 这是一个非常广泛的问题 因为我们不知道您想要什么数据结构 您期望什么查询等等 为
  • Laravel 异常队列最大尝试次数超出

    我创建了一个应用程序来向多个用户发送电子邮件 但在处理大量收件人时遇到问题 该错误出现在failed jobs table Illuminate Queue MaxAttemptsExceededException App Jobs ESe
  • 节点应用程序之间共享会话?

    我目前有两个独立的节点应用程序在两个不同的端口上运行 但共享相同的后端数据存储 我需要在两个应用程序之间共享用户会话 以便当用户通过一个应用程序登录时 他们的会话可用 并且他们似乎已登录到另一个应用程序 在本例中 它是一个面向公众的网站和一
  • 返回导航缓存 - IE

    当我在 IE 11 上运行 Web 应用程序时 收到如下警告消息 DOM7011 此页面上的代码禁用了后退和前进缓存 为了 更多信息 请参阅 http go microsoft com fwlink LinkID 291337 http g
  • APC 将数据存储在哪里?

    我想用apc store 缓存一些结果 但我需要知道数据将存储在哪里 以及限制是什么 它总是存储在内存中吗 或者也写入磁盘 我希望将不经常访问的数据存储在磁盘上 我应该为此使用不同的缓存系统吗 这就是极限了吗 apc shm size 32
  • 当 Jedis 与 Spring Data 一起使用时,为什么数据会以奇怪的键存储在 Redis 中?

    我将 Spring Data Redis 与 Jedis 一起使用 我正在尝试存储带有密钥的哈希值vc list id 我能够成功插入到redis 但是 当我使用 redis cli 检查密钥时 我没有看到密钥vc 501381 相反我看到
  • 如何使用 Tomcat 启用浏览器缓存静态内容(图像、css、js)?

    如何使用 Tomcat 启用浏览器缓存静态内容 图像 css js 首选的解决方案是编辑 spring MVC 配置文件或 web xml 尝试 改变值
  • iOS 6 上的 Safari 是否缓存 $.ajax 结果?

    自从升级到 iOS 6 以来 我们看到 Safari 的网页视图擅自缓存 ajax来电 这是在 PhoneGap 应用程序的上下文中 因此它使用 Safari WebView 我们的 ajax电话是POST方法并且我们将缓存设置为 fals
  • Java 中的 LRU 缓存实现

    我看过下面的代码 我认为addElement方法的实现中有一个无用的while循环 它永远不应该有比 size 1 更多的元素 因为已经有一个写锁 那么为什么 addElement 方法会删除元素直到它达到这个条件 真的 while con
  • 使@lru_cache忽略一些函数参数

    我怎样才能使 functools lru cache https docs python org 3 library functools html functools lru cache装饰器忽略一些与缓存键有关的函数参数 例如 我有一个如

随机推荐

  • C# 中单个 & 符号的第二个含义是什么?

    我在 C 中使用了单个与号 来表示 检查second条件语句即使第一个是false 但以下似乎是不同的意思 of 总而言之 谁能解释一下如何i 1在下面的例子中有效吗 List
  • 表单中的表单:跳过父表单的验证

  • 如何仅注释堆积条形图的一个类别

    我有一个数据框示例 如下所示 data Date 2021 07 18 2021 07 19 2021 07 20 2021 07 21 2021 07 22 2021 07 23 Invalid NaN 1 1 NaN NaN NaN N
  • 如何在程序中将自己缝合到自己的尾部,无限循环地封装 64KB 代码段?

    如果指令的顺序执行经过偏移量 65535 则8086将从同一代码段中的偏移量 0 处获取下一个指令字节 接下来的 COM 程序利用这一事实 不断将其整个代码 总共 32 个字节 缝合到自己的尾部 环绕在 64KB 代码段中 你可以称之为二元
  • 在 IDbCommandInterceptor 中捕获调用方法名称

    我在用IDbCommandInterceptor捕获实体框架查询 这样我就可以访问一些重要信息 例如DbParameters and DbCommand etc 我还需要获取调用此查询的位置 我试图通过使用来得到这个StackTrace S
  • 为什么在将 String 与 null 进行比较时会出现 NullPointerException?

    我的代码在以下行中出现空指针异常 if stringVariable equals null 在此语句之前 我声明了 stringVariable 并将其设置为数据库字段 在这个声明中 我试图检测该字段是否有null值 但不幸的是它坏了 有
  • 如何为抽象工厂创建的类设置特定属性?

    是否可以让具体工厂使用抽象工厂模式为其创建具有特定类型参数的具体类 或者由各自的具体工厂创建的不同具体类是否需要具有相同的字段 例如 在下图中 您将如何使用客户端 应用程序 给出的不同参数集来实例化 WinButton 和 OSXButto
  • angularjs无法找到模板目录,flask作为后端

    我使用 Flask 作为后端 在客户端使用 angularjs 我的目录结构 dew gt app py gt templates gt hello html gt test html gt static gt js gt directiv
  • Toast 消息消失后​​完成活动吗?

    有谁知道 是否有可能对 Toast 消息执行某些操作 在我的情况下完成活动 将被关闭 您只需创建一个Thread持续时间只要Toast显示 然后您就可以完成您的Activity public void onCreate Bundle sav
  • 服务作为 SOA 中的中介

    我知道什么是 通常的 中介设计模式 维基百科中有一些描述 http en wikipedia org wiki Mediator pattern http en wikipedia org wiki Mediator pattern 在我的
  • 在 C# 中使用反射列出枚举中的值

    我正在尝试使用反射来列出一个 Visual Studio 解决方案内的各个项目中的一些类的公共成员和方法 我尝试访问的所有类都是 C 的 并且它们都是从 C 类访问的 我用来进行这些调用的代码如下 public void PopulateE
  • VS2010 RC - 调试器中只有 100 个 std::map 元素

    当我想查看 std map 容器的所有元素时 在 VS 2010 RC 中调试我的应用程序时遇到一个小问题 当调试器到达断点并且我想检查元素检查器中的映射值 在 本地 窗口中以及用鼠标悬停变量名称后的弹出窗口中 并且我正在向下滚动列表元素它
  • C++ 类成员函数和来自 C API 的回调

    我正在尝试学习如何称呼它write data 函数从funmain 类中的函数如下面的代码所示 我知道如果我只列出这两个函数而不将其放入类中 该程序就可以工作 curl easy setopt curl CURLOPT WRITEFUNCT
  • Excel 工作表到 iPhone 数据 -- A 点到 B 点

    尽可能简单 我有一个非常简单的 Excel 电子表格 只有 1000 多条记录 我想将其用作 iPhone 应用程序的静态数据源 最好的进攻计划是什么 我心中的可能性 1 直接读取XLS作为数据源 是否有Obj C库用于此 2 将XLS 转
  • 如何从 Javascript/Typescript 中的数组对象计算运行总计并使用 HTML 在每个实例上显示输出?

    我正在开发一个 MEAN 堆栈项目 并且有一个如下所示的数组 savings any 300 450 350 500 我还有一个名为 saving bf 的变量 它是从数据库中检索的结转储蓄 其值如下 savings bf 15000 我想
  • 本地化水晶报表

    在 Crystal Reports 上本地化标签 列标题 字段标签 页眉 页脚等 的好方法是什么 我们目前使用的是 XI R2 SP4 但希望迁移到 2008 年 看起来 2008 年提供了更好的查看器 UI 本地化 它有内容本地化的故事吗
  • 如何使用内联 SQL 参数化 IN 语句的集合? [复制]

    这个问题在这里已经有答案了 可能的重复 参数化 SQL IN 子句 https stackoverflow com questions 337704 parameterizing a sql in clause 你好 我有一个查询 如下所示
  • 如何使用 Excel.UriLink.16 更改 Excel URL 的文件关联?

    我正在尝试更改文件关联 以便在另一个浏览器中打开 Excel 单元格中的 URL 根据使用 CMD ftype命令与Excel UriLink 16 我应该能够使用以下命令从 powershell 通过 cmd 执行此操作 To chang
  • Vista幻影目录

    我们有一个程序 安装程序会检查配置文件是否存在 如果存在 它不会复制该文件 它假设用户已修改其配置文件并希望保留这些修改 不幸的是 这是一个 Vista 之前的应用程序 它将配置文件保存在 Program Files 中 问题是 如果你在重
  • 如何使 Redis 缓存中数据层次结构(树)的部分内容无效

    我有一些产品数据 需要在 Redis 缓存中存储多个版本 数据由 JSON 序列化对象组成 获取普通 基本 数据的过程很昂贵 将其定制为不同版本的过程也很昂贵 因此我想缓存所有版本以尽可能进行优化 数据结构看起来像这样 BaseProduc