RavenDB起步--文档标识符

简介: 在关系型数据库中表一般情况下都会存在主键,这个主键在所在表中是唯一的不可重复的,同样在 RavenDB 中也存在这样的主键,它被成为文档标识符或文档ID。文档ID是由 UTF8 字符串组成的最多 2025 字节长度的全局唯一值。一般来说文档 ID 的组成规则是: 集合名称 + / + 唯一值 ,当然如果你有其他文档 ID 组成的规则也可以使用。下面我们来看一下 RavenDB 生成文档 ID 的策略。

在关系型数据库中表一般情况下都会存在主键,这个主键在所在表中是唯一的不可重复的,同样在 RavenDB 中也存在这样的主键,它被成为文档标识符或文档ID。文档ID是由 UTF8 字符串组成的最多 2025 字节长度的全局唯一值。一般来说文档 ID 的组成规则是: 集合名称 + / + 唯一值 ,当然如果你有其他文档 ID 组成的规则也可以使用。下面我们来看一下 RavenDB 生成文档 ID 的策略。

TIP:RavenDB 的文档 ID 是数据库全局唯一的,这和关系型数据库的主键是所在表唯一不一样。另外文档 ID 建议使用可读性高的字符串,例如:User/Order/001 。

一、语义(外部)文档 ID

生成文档 ID 最常见的方式是用户生成文档 ID,它经常用在生成具有一定意义的 ID 的情况下。实现代码如下:

using Raven.Client.Documents;
var store = new DocumentStore
{
    Urls = new[] { "http://localhost:8080" },
    Database = "Tasks"
};
store.Initialize();
using (var session=store.OpenSession())
{
    var person = new Person
    {
        Name = "张三"
    };
    session.Store(person,"person/zhangsan@demo.com");
    session.SaveChanges();
}

session.Store(person,"person/zhangsan@demo.com");该行代码将文档 ID 设置为 email 地址,这样我们就可以根据用户输入的电子邮件轻松定位到文档。

二、嵌套文档 ID

嵌套文档 ID 是语义文档 ID 的一个特例,比如在一个大型电商系统中,每个 User 都有可能存在多个订单,那么如果我们将每个 User 的所有订单都放在 User 文档中显然是不合理的,正确的做法应该是将订单单独作为一个文档存储。那么这时订单文档的文档 ID 的生成策略就应该是:User文档 ID + / + Order 文档ID

三、客户端生成文档 ID (hilo)

在大部分情况下,我们不希望考虑文档 ID 的生成策略,希望由 RavenDB 来帮我们生成文档 ID。在 RavenDB 中我们可以使用hilo,在我们第一次需要生成 ID 时,向服务器请求保留文档 ID 范围,这时服务器将会确保所提供的范围只对一个客户端使用,然后我们的客户端就可以在给定的范围内安全的生成文档 ID。这种方法是目前最好的生成文档 ID 的方法,可以保证在客户端非常繁忙的情况下扩展,并快速生成大量文档 ID。

这里存在一个问题,当又多个客户端从不同的节点同时向服务端发送保留文档 ID 的请求时,很有可能出现这几个客户端获得打文档 ID 范文是一样的,那么为了解决这个问题各个节点之间会相互通信,如果发现有节点的文档 ID 范围和自己的一样的话,这些节点所生成的文档 ID 后面将会加上节点名称,比如 A 节点和 B 节点同时请求服务端保留文档 ID 范围,这时它俩的文档 ID 范围都是 100-150,那么这两个节点所生成的文档 ID 将会是类似于 User/100-A 和 User/100-B 这样的。

四、服务器端生成文档 ID

虽然 Hilo 可以生成可读性和可预测性较好的文档 ID,但是它需要客户端和服务端合作才能使用,但是如果我们需要手动在 RavenDB Studio 中编写文档或者只指定文档 ID 开头的情况呢?这时我们就可以使用服务端生成文档 ID 策略。比如我们要在 RavenDB Studio中创建一个订单数据,这时我们在 ID 中输入 order/ 然后单击 Save , RavenDB 就会为我们自动生成一个类似于下图的文档 ID。

在这里插入图片描述

同样,使用代码时我们可以在指定文档 ID 时只指定文档 ID 的开头,代码如下:

using Raven.Client.Documents;
var store = new DocumentStore
{
    Urls = new[] { "http://localhost:8080" },
    Database = "Tasks"
};
store.Initialize();
using (var session=store.OpenSession())
{
    var person = new Person
    {
        Name = "张三"
    };
    session.Store(person, "user/");
    session.SaveChanges();
}

运行下面代码后,在 RavenDB Studio 中查看 person 文档,新添加的数据如下:

在这里插入图片描述

五、Identity 生成文档 ID 策略

如果在开发中需要生成连续的文档 ID ,那么我们可以使用 Identity 生成文档 ID 策略。Identity 每次生成文档 ID 都需要向服务器发送请求。Identity 生成文档 ID 和服务器端生成文档 ID 很相似,但是不是使用 / 而是使用 | 来作为结尾生成 ID。我们在  RavenDB Studio 的 ID 中输入:order| 即可使用 Identity 生成 ID。生成结果如下图:

在这里插入图片描述

这个策略存在一个问题,如果我们尝试使用 ID 保存文档并且保存失败,值仍然会递增。因此,即使 Identity 生成连续数字,如果事务已回滚,它仍可能会跳过标识符。

同时在分布式环境中,这种策略需要我们防止竞争,例如两个客户端在两个不同的服务器上生成相同的 Identity ,生成新 Identity 的部分过程需要节点相互协调。这意味着我们需要通过网络与集群中的其他成员通信,以确保我们拥有 Identity 的下一个值。这会增加保存带有 Identity 的新文档的成本。更糟糕的是,在故障情况下,我们可能无法与集群中足够数量的节点进行通信。这意味着我们也将无法生成请求的 Identity。

TIP:除非有明确的要求必须使用连续的 ID,否则这种策略不予考虑。

六、总结

我们已经讨论了很多生成文档标识符的选项,每个选项都有自己的行为和成本,各种方法之间也存在性能差异。

RavenDB 通过将文档 ID 存储在 B+Tree 中来跟踪它们。如果文档 ID 非常大,则意味着 RavenDB 可以在给定空间中存储更少的文档 ID。

  1. hilo 生成的文档 ID 在词法上可排序,在大多数情况下,我们可以获得优质的树和非常有效的搜索,并且它还生成最易读的内容;
  2. 使用斜线的服务器端方法在存储适用性方面最佳值。比 hilo 生成的 ID 要大一些,但就底层存储而言,它是按词法排序的,以及时可预测的,从而弥补了这一点。它非常适合大型批处理作业,并且在其中包含许多额外的优化;
  3. 语义生成的 ID 是未排序的,RavenDB 可以轻松处理大量带有语义标识符的文档,对于性能来说也没什么大问题;
  4. Identity 生成文档 ID ,需要网络请求才能生成下一个值,如果节点无法与集群中的大多数节点通信,这个方法将变得不可用。
目录
相关文章
|
8月前
|
存储 自然语言处理 Linux
非常高兴地宣布,我们发布了RunFlow的第一个版本,这是一款全新且强大的效率工具
RunFlow v1 发布!这是一个跨平台的效率工具,类似 Wox、PowerToys、Alfred 和 Raycast。特色包括:跨平台支持(暂不包括Linux)、多语言(默认英/中文,可扩展)、自定义样式与主题、关键字驱动功能、后置匹配技术、实时刷新结果、上下文菜单、工具栏、固定关键字、可交互界面、独立窗口、热点事件、专注模式和数据安全同步。支持插件扩展,开发插件语言无限制,基于JetBrains Compose Multiplatform。
71 1
非常高兴地宣布,我们发布了RunFlow的第一个版本,这是一款全新且强大的效率工具
|
8月前
|
搜索推荐 关系型数据库 MySQL
手把手教你搭建子比主题的系统(亲测可用)|学习版本|虚拟知识付费平台比较合适
搭建Zibll子比主题涉及以下步骤: 1. 服务器环境需支持PHP 7.0+(推荐7.4+)和MySQL。 2. 下载并安装WordPress,可从官方站点获取最新版本。 3. 从指定链接下载子比主题文件。 4. 在WordPress后台上传并启用子比主题,配置固定链接和伪静态,例如使用宝塔面板。 5. 调整主题设置,如Logo和网站关键词。 6. 安装必要插件,如Yoast SEO和Contact Form 7,根据实际需求选择。 7. 完成后测试和调试网站功能。 记得参考官方文档以获取详细指导。
|
8月前
|
移动开发 小程序 安全
【社区每周】AIT现支持免登陆使用;小程序内嵌外跳H5页面支持支付宝端内官方应用(8月第一期)
【社区每周】AIT现支持免登陆使用;小程序内嵌外跳H5页面支持支付宝端内官方应用(8月第一期)
150 11
|
安全 算法 5G
了解 5G 安全标准,看这一篇就够了
了解 5G 安全标准,看这一篇就够了
626 0
|
存储 弹性计算 监控
阿里云存储子社区官方征稿来啦!
参加存储官方征稿,赢取定制好礼
7627 4
优秀开源项目推荐之--文档库bookstack
优秀开源项目推荐之--文档库bookstack
|
前端开发 安全 Java
PassJava 开源(十四)之 管理后台-题目类型功能
PassJava 开源(十四)之 管理后台-题目类型功能
268 0
PassJava 开源(十四)之 管理后台-题目类型功能
|
存储 弹性计算 容灾
项目4---罗列并解释阿里云服务的存储产品
项目4---罗列并解释阿里云服务的存储产品
325 0
项目4---罗列并解释阿里云服务的存储产品
|
存储 NoSQL 前端开发
前端培训-中级阶段(50)- MongoDB 简介,安装,数据库,集合,文档概念
前端最基础的就是 HTML+CSS+Javascript。掌握了这三门技术就算入门,但也仅仅是入门,现在前端开发的定义已经远远不止这些。前端小课堂(HTML/CSS/JS),本着提升技术水平,打牢基础知识的中心思想,我们开课啦(每周四)。
203 0
前端培训-中级阶段(50)- MongoDB 简介,安装,数据库,集合,文档概念