楼主: jieforest

[转载] Cassandra数据模型设计最佳实践

[复制链接]
论坛徽章:
277
马上加薪
日期:2014-02-19 11:55:14马上有对象
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14马上有车
日期:2014-02-19 11:55:14马上有车
日期:2014-02-18 16:41:112014年新春福章
日期:2014-02-18 16:41:11版主9段
日期:2012-11-25 02:21:03ITPUB年度最佳版主
日期:2014-02-19 10:05:27现任管理团队成员
日期:2011-05-07 01:45:08
31#
 楼主| 发表于 2013-11-8 10:20 | 只看该作者
一个不合适的comparator 将不能按照你预期所想的顺序将column name排序并存放到磁盘上。它将很难(或者不能)根据column name进行范围查询。

一旦完成定义,你将不能修改comparator,除非重写所有数据。但是validator 是可以事后变更的。

通过Cassandra文档看看comparators 和 validators 支持的数据类型。

保持column name简短

因为它将会在被重复存储

如果你使用column name存储数据,那这个实践是不适用的。除此之外,保持column name简短,因为它将和每个column value一起被重复存储(根据数据副本数)。当column value的大小比column name小很多时,内存和存储的开销可能会是个问题。

比如,‘fname’ 优于 ‘firstname’,‘lname’ 优于 ‘lastname’。

注意:Cassandra-4175可能会导致本实践在未来失效。

使用道具 举报

回复
论坛徽章:
277
马上加薪
日期:2014-02-19 11:55:14马上有对象
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14马上有车
日期:2014-02-19 11:55:14马上有车
日期:2014-02-18 16:41:112014年新春福章
日期:2014-02-18 16:41:11版主9段
日期:2012-11-25 02:21:03ITPUB年度最佳版主
日期:2014-02-19 10:05:27现任管理团队成员
日期:2011-05-07 01:45:08
32#
 楼主| 发表于 2013-11-8 10:20 | 只看该作者
将数据模型设计为支持幂等操作

或者确保你能够接受用例数据不准确或者最终准确的情况

像Cassandra这样具有最终一致性以及完全分布式的系统,幂等操作非常有用。幂等操作允许系统因出现错误而导致的重试是安全的,它不会影响数据的最终结果。此外,幂等有时可以降低对强一致性的需求,因为它允许在不产生数据重复和其它异常的情况下实现最终一致性。让我们看看这些原则如何应用到Cassandra上。我将只讨论部分失败的情况,降低强一致性需求放到后续文章里讲,因为它非常依赖用例。

因为Cassandra具有完全分布式(多个master)的特性,写失败不能确保数据没有被写入,这与关系型数据库不同。换句话说,即使客户端接收到一个写入操作失败的响应,数据仍可能被写入其中一个副本,数据将最终被传播到其它副本。没有回滚或者清理动作来处理已经写入的数据。因此,虽然客户端出现写失败,但数据最终是成功写入的。所以如果你的模型不具有更新幂等性,错误的重试将导致未知的结果。

使用道具 举报

回复
论坛徽章:
277
马上加薪
日期:2014-02-19 11:55:14马上有对象
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14马上有车
日期:2014-02-19 11:55:14马上有车
日期:2014-02-18 16:41:112014年新春福章
日期:2014-02-18 16:41:11版主9段
日期:2012-11-25 02:21:03ITPUB年度最佳版主
日期:2014-02-19 10:05:27现任管理团队成员
日期:2011-05-07 01:45:08
33#
 楼主| 发表于 2013-11-8 10:20 | 只看该作者
注意:

1)这里的“更新幂等性”意味着模型的操作是幂等的。如果一个操作被多次调用却不影响最终结果,那它就具有幂等性。

2)在大多数情况,幂等性不会受到关注,因为将数据写入正常的Colum Family总是更新幂等的,Counter column family是比较特殊的例子,后面我们会说到。有时你的用例可以设计为非更新幂等的。比如我们第一部分文章中,最终方案的模型User_by_Item和Item_by_User就不具有更新幂等性,因为当“User喜爱某个Item”的操作被执行多次将导致数据时间戳发生改变,从而无法获知真实的User喜爱某个Item的时间。但是,“User喜爱某个Item”的操作仍然是幂等的,因为我们在出现错误的时候重试多次。更多具体的例子,我可能会在后面讲到。

3)即使一致性层级为“ONE”,写入失败仍然不能确保数据没有被写入。数据仍然有可能最终传播到其它副本。

使用道具 举报

回复
论坛徽章:
277
马上加薪
日期:2014-02-19 11:55:14马上有对象
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14马上有车
日期:2014-02-19 11:55:14马上有车
日期:2014-02-18 16:41:112014年新春福章
日期:2014-02-18 16:41:11版主9段
日期:2012-11-25 02:21:03ITPUB年度最佳版主
日期:2014-02-19 10:05:27现任管理团队成员
日期:2011-05-07 01:45:08
34#
 楼主| 发表于 2013-11-8 10:21 | 只看该作者
示例:

假设我们想计算某个Item被多少User所喜爱,一种方式是使用counter column family保存多少个user喜欢某个item。因为counter增加(减少)特性不是更新幂等的,当出现失败并重试的时候就会导致数量被重复累加的情况。让模型具有更新幂等性可以通过维护user id来代替增加counter记数。无论何时user喜爱某个item,我们都将user id写入item,如果写入失败,我们可以安全的重试。如果希望获取所有喜爱某个item的user,我们只需要读取item中user id信息手动累加就行。



在上面更新幂等(Update idempotent)模型中,获取counter值要求读取所有user id值,这样的实现可能不够好(因为它可能有上百万个)。在本用例中,如果counter读操作很频繁,同时你能接受一个与真实值接近的值,counter column将是一个更好的、更高效的选择。如果需要,counter值也可以周期的通过user id计算出来并更新,这样的设计也是具有更新幂等性。

使用道具 举报

回复
论坛徽章:
277
马上加薪
日期:2014-02-19 11:55:14马上有对象
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14马上有车
日期:2014-02-19 11:55:14马上有车
日期:2014-02-18 16:41:112014年新春福章
日期:2014-02-18 16:41:11版主9段
日期:2012-11-25 02:21:03ITPUB年度最佳版主
日期:2014-02-19 10:05:27现任管理团队成员
日期:2011-05-07 01:45:08
35#
 楼主| 发表于 2013-11-8 10:21 | 只看该作者
在上面更新幂等(Update idempotent)模型中,获取counter值要求读取所有user id值,这样的实现可能不够好(因为它可能有上百万个)。在本用例中,如果counter读操作很频繁,同时你能接受一个与真实值接近的值,counter column将是一个更好的、更高效的选择。如果需要,counter值也可以周期的通过user id计算出来并更新,这样的设计也是具有更新幂等性。

注意:Cassandra-2495可能会为失败的counter请求添加一个合适的重试机制。但是,这个实践仍然有效。所以记得经常测试模型更新幂等性。

根据需要,围绕事务建模

但这可能不总是能够实现,具体情况具体分析

Cassandra没有多行、集群范围的事务或者回滚机制,取而代之,它提供行级别原子性。换句话说,对某个row key的一次mutation操作是原子的。所以当你需要事务性的时候,尝试设计你的模型,让它一次永远只更新一行。但还是要考虑你的用例,这样的设计不总是有效,如果你的系统需要ACID事务,那你需要重新考虑数据库的选择了。

使用道具 举报

回复
论坛徽章:
277
马上加薪
日期:2014-02-19 11:55:14马上有对象
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14马上有车
日期:2014-02-19 11:55:14马上有车
日期:2014-02-18 16:41:112014年新春福章
日期:2014-02-18 16:41:11版主9段
日期:2012-11-25 02:21:03ITPUB年度最佳版主
日期:2014-02-19 10:05:27现任管理团队成员
日期:2011-05-07 01:45:08
36#
 楼主| 发表于 2013-11-9 10:26 | 只看该作者
如果可以的话,预先设计好合适的TTL

因为很难改变既有数据TTL

在Cassandra中,TTL(存活时间)不是设置在column family上,它设置于每个column value,一旦设置后就很难改变。或者说,如果创建column时候没有设置,那之后就很难对其设置TTL。对于既有数据修改TTL唯一的方式就是读取然后再次插入所有数据,并赋予TTL。所以要考虑好如何清除你的数据,如果可能进来在创建数据的时候设置合适的TTL。

不要使用counter column family生成key信息

它不是干这个用的

counter column family保存分布式counter信息,这意味着它要做分布式的累加(递减)运算。不要使用counter生成序列编号(比如oracle的sequence或者MySQL的自增列)来生成你的rowkey(column key),否则你将可能得到重复序列编号,从而导致数据覆盖。大多数时间你真的不需要全局序列编号,更好的选择是使用timeuuid (type-1 uuid)来生成key信息。如果你真的需要一个全局序列编号生成器,这里有个可行的办法,就是需要一个中央协调器,但这会影响系统的扩展性和可用性。

使用道具 举报

回复
论坛徽章:
277
马上加薪
日期:2014-02-19 11:55:14马上有对象
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14马上有车
日期:2014-02-19 11:55:14马上有车
日期:2014-02-18 16:41:112014年新春福章
日期:2014-02-18 16:41:11版主9段
日期:2012-11-25 02:21:03ITPUB年度最佳版主
日期:2014-02-19 10:05:27现任管理团队成员
日期:2011-05-07 01:45:08
37#
 楼主| 发表于 2013-11-9 10:27 | 只看该作者
composite columns 优于 super columns

使用super columns可能会产生性能瓶颈

在Cassandra中,super column常被用于对column key进行分组,或者建立两层数据结构。但是super column有下列实现问题导致它并不那么美好:

问题:

1)Super column的子column不能被索引,读取一个字column意味着要反序列化整个super column

2)子column无法使用内建二级索引

3)Super column无法实现超过两层的结构

类似的功能,可以通过Composite column实现,它是包含子column的标准的column,因此标准column所有的好处它都具备,比如排序、范围查询,同时你可以设计出多层级的结构。

使用道具 举报

回复
论坛徽章:
277
马上加薪
日期:2014-02-19 11:55:14马上有对象
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14马上有车
日期:2014-02-19 11:55:14马上有车
日期:2014-02-18 16:41:112014年新春福章
日期:2014-02-18 16:41:11版主9段
日期:2012-11-25 02:21:03ITPUB年度最佳版主
日期:2014-02-19 10:05:27现任管理团队成员
日期:2011-05-07 01:45:08
38#
 楼主| 发表于 2013-11-9 10:27 | 只看该作者
注意composite columns中子column顺序

因为排序决定数据存储位置

举个例子,一个composite column key为<state | city>,将被先按照state然后按照city的顺序存储,换句话说,一个state的所有cities在磁盘存储上是紧挨着的。

优先使用内置的composite types,而不是自定义类型

因为自定义类型不总是可用

避免使用字符串连接(如果通过分隔符“:”或者“|”)的composite column key,取而代之,应该使用内置composite types (以及 comparators),它在cassandra0.8.1版本以上被支持。

使用道具 举报

回复
论坛徽章:
277
马上加薪
日期:2014-02-19 11:55:14马上有对象
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14马上有车
日期:2014-02-19 11:55:14马上有车
日期:2014-02-18 16:41:112014年新春福章
日期:2014-02-18 16:41:11版主9段
日期:2012-11-25 02:21:03ITPUB年度最佳版主
日期:2014-02-19 10:05:27现任管理团队成员
日期:2011-05-07 01:45:08
39#
 楼主| 发表于 2013-11-9 10:28 | 只看该作者
Why?

1)如果sub-columns是不同的数据类型,自定义类型将不能正常工作。比如,composite key<state|zip|timeuuid>将不能适用于根据类型感知排序(state是字符串,zip是整型,timeuuid是时间类型)。

2)你不能针对每个sub-columns进行不同的顺序查找。比如,上面的例子中,不能根据state升序,zip进行降序。

注意:Cassandra内置composite types有两种使用方法:

1)静态 composite type:composite column的每部分的数据类型都在column family中被提前定义好。Column family中所有column name 必须是之前定义好的类型。

2)动态composite type:这个类型允许你将不同的composite type的column name在一个column family中混合使用,甚至在一行中。

关于composite type更多信息,请查看这里: Introduction to composite columns

使用道具 举报

回复
论坛徽章:
277
马上加薪
日期:2014-02-19 11:55:14马上有对象
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14马上有车
日期:2014-02-19 11:55:14马上有车
日期:2014-02-18 16:41:112014年新春福章
日期:2014-02-18 16:41:11版主9段
日期:2012-11-25 02:21:03ITPUB年度最佳版主
日期:2014-02-19 10:05:27现任管理团队成员
日期:2011-05-07 01:45:08
40#
 楼主| 发表于 2013-11-9 10:28 | 只看该作者
无论何时,尽量优先使用静态composite type

因为动态composite太灵活

如果一个column family中的column keys都是相同的composite type,则一定要使用静态composite type。创建动态composite type最初的目的是为了在一个column family中保存多用户自定义索引。如果可能,请不要在一行中使用不同的composite type,除非真的有必要这么做。Cassandra-3625已经修复了一些动态composite的严重问题。

注意:CQL3支持column name使用静态composite type。如果想知道CQL3如何处理wide row,请参考这篇文章DataStax docs。

就这么多,如果您能从这些最佳实践中获益,非常欢迎看到您的回复,这就是我们Cassandra今天的使用情况。

– Jay Patel, architect@eBay.

使用道具 举报

回复

您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

TOP技术积分榜 社区积分榜 徽章 团队 统计 知识索引树 积分竞拍 文本模式 帮助
  ITPUB首页 | ITPUB论坛 | 数据库技术 | 企业信息化 | 开发技术 | 微软技术 | 软件工程与项目管理 | IBM技术园地 | 行业纵向讨论 | IT招聘 | IT文档
  ChinaUnix | ChinaUnix博客 | ChinaUnix论坛
CopyRight 1999-2011 itpub.net All Right Reserved. 北京盛拓优讯信息技术有限公司版权所有 联系我们 未成年人举报专区 
京ICP备16024965号-8  北京市公安局海淀分局网监中心备案编号:11010802021510 广播电视节目制作经营许可证:编号(京)字第1149号
  
快速回复 返回顶部 返回列表