TL;博士
如何在具有大量数据的键/值存储中找到“无法访问的键”?
背景
与提供 ACID 保证的关系数据库相比,NoSQL 键/值数据库为处理“大数据”提供的保证较少。例如,它们仅在单个键/值对的上下文中提供原子性,但它们使用分布式哈希表等技术在任意大型机器集群中“分片”数据。
钥匙通常对人类不友好。例如,代表员工的数据块的键可能是
Employee:39045e87-6c00-47a4-a683-7aba4354c44a
. 员工可能还具有更人性化的标识符,例如jdoe
员工登录系统时使用的用户名。此用户名将存储为单独的键/值对,其中键可能是EmployeeUsername:jdoe
. key 的值EmployeeUsername:jdoe
通常是包含主键的字符串数组(将其视为二级索引,不一定包含唯一值)或员工 blob 的非规范化版本(可能从其他对象聚合数据以改进查询性能)。
问题
现在,鉴于键/值数据库通常不提供事务保证,当进程插入键
Employee:39045e87-6c00-47a4-a683-7aba4354c44a
(以及员工的序列化表示)但在插入
EmployeeUsername:jdoe
键之前崩溃时会发生什么?客户不知道员工数据的密钥——他或她只知道用户名jdoe
——那么如何找到
Employee:39045e87-6c00-47a4-a683-7aba4354c44a
密钥?
我唯一能想到的是枚举键/值存储中的键,一旦找到合适的键,“恢复”索引/非规范化。我非常了解诸如事件溯源之类的技术,其中幂等事件处理程序可以响应事件(例如,EmployeeRegistered
)以重新创建用户名到员工 uuid 二级索引,但仍然使用键/值存储上的事件溯源需要枚举键,这可能会降低性能。
比喻
我在 IT 方面的经验越多,我就越能看到在不同场景中解决相同的问题。例如,Linux 文件系统将文件和目录内容都存储在“inode”中。您可以将它们视为键/值对,其中键是整数,值是文件/目录内容。写入新文件时,系统会创建一个 inode 并用数据填充它然后修改父目录以添加“filename-to-inode”映射。如果系统在创建文件之后但在父目录中引用它之前崩溃,则您的文件“存在于磁盘上”但本质上是不可读的。当系统重新上线时,希望它会将此文件放入“lost+found”目录中(我想它是通过扫描整个磁盘来实现的)。
编辑
我发现这篇关于手动二级索引的有趣文章,但它没有“损坏”或“过时”二级索引。