在听说NoSQL几年后,我终于开始在.Net MVC应用程序(简单博客)中使用RavenDB。启动并运行嵌入式数据库非常快速且轻松。
但是,我发现在将对象插入文档存储区后,当后续页面刷新时,它们并不总是存在。当我刷新页面时,它们会显示出来。我在某处读到这是由于陈旧的索引。
我的问题是,你应该如何在一直有插件发生的网站上使用它(例如:电子商务)。这不会导致陈旧的索引和不可靠的查询结果吗?
答案 0 :(得分:8)
想想像SQL Server这样的传统数据库实际发生了什么。
C
onsistency要求优先级高于A
vailability。 NoSQL的“最终一致性”概念旨在缓解这些问题。通过优先A
可用性高于C
onsistency,优化读取。 RavenDB在这方面并不是唯一的,但它有点特别之处在于它仍然具有一致性。如果您要检索单个文档,例如查看订单或查看其配置文件的最终用户,则这些操作符合ACID,并且不受“最终一致性”设计的影响。
要了解“最终一致性”,请考虑一下查看网站上产品列表的典型用户。与此同时,贵公司的销售人员正在修改目录,添加新产品,更改价格等。有人可能会说,列表与这些变化完全一致可能并不是非常重要。毕竟,几秒前访问该站点的用户无论如何都会收到数据而不进行任何更改。最重要的是快速提供产品结果。由于正在进行写入而阻止查询意味着对客户的响应时间较慢,从而导致您的网站体验较差,并且可能导致销售损失。
所以,在RavenDB中:
Load
操作直接转到文档商店。现在让我们举一个例子来说明这种方法的不足之处。
解决这个问题需要理解并非所有数据查看者都应该被认为是平等的。那个特定的销售人员可能会要求看到新添加的产品,但客户不会以同样的紧急程度了解或关心它。
因此,在销售人员正在查看的“产品列表”页面上,您可能会执行以下操作:
var results = session.Query<Product>()
.Customize(x => x.WaitForNonStaleResultsAsOfLastWrite())
.OrderBy(x=> x.Name)
.Skip((pageNumber-1) * pageSize).Take(pageSize);
在客户对目录的视图中,您不想要添加该自定义行。
如果你想要超精确,你可以使用稍微优化的策略:
在您查询该页面之前,如果传入了ProductID,则将您的查询代码更改为:
var product = session.Load(productId);
var etag = session.Advanced.GetEtagFor(product);
var results = session.Query<Product>()
.Customize(x => x.WaitForNonStaleResultsAsOf(etag))
.OrderBy(x=> x.Name)
.Skip((pageNumber-1) * pageSize).Take(pageSize);
这将确保您只需等待绝对必要的时间,即可获得结果列表中包含的一个产品的更改以及索引中的其他结果。
您可以通过向后传递etag而不是ProductId来稍微优化它,但这可能不再可以从应用程序中的其他位置重复使用。
但请记住,如果列表按字母顺序排序,并且我们添加了“Plums”而不是“Apples”,那么您可能无法立即看到这些结果。当用户跳过包含该产品的页面时,它可能已经存在。
答案 1 :(得分:3)
您正在遇到过时的查询。 这是RavenDB的设计部分。您需要区分查询(BASE)和按ID(ACID)加载。