Cassandra架构与应用

4,135 views
3,963 views

Published on

0 Comments
6 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
4,135
On SlideShare
0
From Embeds
0
Number of Embeds
3
Actions
Shares
0
Downloads
165
Comments
0
Likes
6
Embeds 0
No embeds

No notes for slide

Cassandra架构与应用

  1. 1. Cassandra架构与应用<br />For Cassandra 0.7.0<br />淘宝网 文茂<br />
  2. 2. Agenda<br />基础知识<br />数据模型<br />数据分布策略<br />存储机制<br />数据读写删<br />最终一致性<br />Gossiper<br />面向未来<br />
  3. 3. NoSql背景<br /> 随着互联网大规模的Web2.0应用的兴起,随着云计算需要的大规模分布式服务和分布式存储的发展,传统的关系数据库面临着诸多全新的挑战,特别是在那些超大规模和高并发的SNS类型的应用场景下,使用关系数据库来存储和查询用户动态数据已经显得力不从心,暴露了很多难以克服的问题,例如需要很高的实时插入性能;需要海量的数据存储能力同时还需要非常快的查询检索速度;需要将数据存储无缝扩展到整个群集环境下,并且能够在线扩展等等。在这样的背景下,NoSQL数据库就应运而生了。<br />
  4. 4. NOSQL<br /> is simply<br />Not Only SQL!<br />
  5. 5. NOSQL特点<br />不要叫它们数据库<br />它们可以处理超大量的数据<br />它们运行在便宜的PC服务器集群上<br />它们击碎了性能瓶颈<br />Bootstrap支持<br />
  6. 6. CAP<br />
  7. 7. ACID/BASE<br />ACID<br />原子性(Atomicity).<br />事务中的所有操作,要么全部成功,要么全部不做.<br />一致性(Consistency)<br />在事务开始与结束时,数据库处于一致状态.<br />隔离性(Isolation). <br />事务如同只有这一个操作在被数据库所执行一样.<br />持久性(Durability).<br />在事务结束时,此操作将不可逆转.(也就是只要事务提交,系统将保证数据不会丢失,即使出现系统Crash,译者补充).<br />BASE<br />Basically Available(基本可用)<br />Soft state(柔性状态)<br />状态可以有一段时间不同步,异步<br />Eventually consistent(最终一致)<br />最终数据是一致的就可以了,而不是时时一致<br />
  8. 8. 最终一致性<br />场景介绍<br />(1)存储系统 <br /> 存储系统可以理解为一个黑盒子,它为我们提供了可用性和持久性的保证。 <br />(2)Process A <br />ProcessA主要实现从存储系统write和read操作 <br />(3)Process B 和ProcessC  <br />ProcessB和C是独立于A,并且B和C也相互独立的,它们同时也实现对存储系统的write和read操作。<br />强一致性<br /> 强一致性(即时一致性) 假如A先写入了一个值到存储系统,存储系统保证后续A,B,C的读取操作都将返回最新值 <br />弱一致性 <br /> 假如A先写入了一个值到存储系统,存储系统不能保证后续A,B,C的读取操作能读取到最新值。此种情况下有一个“不一致性窗口”的概念,它特指从A写入值,到后续操作A,B,C读取到最新值这一段时间。 <br />最终一致性 <br /> 最终一致性是弱一致性的一种特例。假如A首先write了一个值到存储系统,存储系统保证如果在A,B,C后续读取之前没有其它写操作更新同样的值的话,最终所有的读取操作都会读取到最A写入的最新值。此种情况下,如果没有失败发生的话,“不一致性窗口”的大小依赖于以下的几个因素:交互延迟,系统的负载,以及复制技术中replica的个数(这个可以理解为master/salve模式中,salve的个数)。 <br />
  9. 9. Casandra是什么?<br />Cassandra是一个高可靠的大规模分布式存储系统。高度可伸缩的、一致的、分布式的结构化key-value存储方案。<br />2007由facebook开发<br />已经在生产环境中使用,比如emailindexsearch<br />2009年成为Apache的孵化项目<br />
  10. 10. Cassandra有什么特点?<br />列表数据结构<br /> 在混合模式可以将超级列添加到5维的分布式Key-Value存储系统。<br />模式灵活 <br />使用Cassandra,你不必提前解决记录中的字段。你可以在系统运行时随意的添加或移除字段。 <br />真正的可扩展性<br /> Cassandra是纯粹意义上的水平扩展。为给集群添加更多容量,可以增加动态添加节点即可。你不必重启任何进程,改变应用查询,或手动迁移任何数据。 <br />多数据中心识别 <br />你可以调整你的节点布局来避免某一个数据中心起火,一个备用的数据中心将至少有每条记录的完全复制。    <br />范围查询<br />如果你不喜欢全部的键值查询,则可以设置键的范围来查询。 <br />分布式写操作<br />有可以在任何地方任何时间集中读或写任何数据。并且不会有任何单点失败。 <br />
  11. 11. Agenda<br />基础知识<br />数据模型<br />数据分布策略<br />存储机制<br />数据读写删<br />最终一致性<br />Gossiper<br />面向未来<br />
  12. 12. 数据模型 <br />Column<br />SuperColumn<br />ColumnFamily<br />Keyspaces<br />Row<br />
  13. 13. Column<br />
  14. 14. Column Family{Columns}<br />
  15. 15. Super Column<br />
  16. 16. ColumnFamily {SuperColumns}<br />
  17. 17. Keyspaces<br />一个Keyspace是Cassandra哈希第一维,是ColumnFamilies容器。<br />一般来说,我们的一个程序应用只会有一个Keyspace,相当于关系数据库的一个数据库.<br />
  18. 18. Row<br />Row以key为表示,一个key对应的数据可以分布在多个column family中,通常我们都只会存放在一个column family中。<br />
  19. 19. 数据定位<br />第一层索引所用的 key 为 (row-key, cf-name), 即用一个 row-key 和 column-family-name 可以定位一个 column family。column family 是 column 的集合。 <br />第二层索引所用的 key 为 column-name, 即通过一个 column-name 可以在一个 column family 中定位一个 column。<br />
  20. 20. Agenda<br />基础知识<br />数据模型<br />数据分布策略<br />存储机制<br />数据读写删<br />最终一致性<br />Gossiper<br />面向未来<br />
  21. 21. 数据分布策略<br />Distributed hash table<br />Partitioner类型<br />RandomPartitioner<br />OrderPreservingPartitioner<br />ByteOrderedPartitioner<br />CollatingOrderPreservingPartitioner<br />副本策略<br />LocalStrategy<br />RackUnawareStrategy<br />RackAwareStrategy<br />DatacenterShardStategy<br />
  22. 22. Distributed hash table<br />
  23. 23. Partitioner类型<br />RandomPartitioner<br /> 随机分区是一种hash分区策略,使用的Token是大整数型(BigInteger),范围为0~2^127,因此极端情况下,一个采用随机分区策略的Cassandra集群的节点可以达到2^127+1个节点。<br />为什么是2^127?<br /> Cassandra采用了MD5作为hash函数,其结果是128位的整数值(其中一位是符号位,Token取绝对值为结果)。<br />
  24. 24. Partitioner类型<br />RandomPartitioner<br />4个节点,随机分配的Token分布情况<br />采用随机分区策略的集群无法支持针对Key的范围查询。<br />假如集群有N个节点,每个节点的hash空间采取平均分布的话,那么第i个节点的Token可以设置为:i * ( 2 ^ 127 / N )<br />
  25. 25. Partitioner类型<br />OrderPreservingPartitioner<br /> 如果要支持针对Key的范围查询,那么可以选择这种有序分区策略。该策略采用的是字符串类型的Token。<br />如果没有指定InitialToken,则系统会使用一个长度为16的随机字符串作为Token,字符串包含大小写字符和数字。<br />
  26. 26. Partitioner类型<br />
  27. 27. Partitioner类型<br />ByteOrderedPartitioner<br />和OrderPreservingPartitioner一样是有序分区策略。只是排序的方式不一样,采用的是字节型Token。<br />
  28. 28. Partitioner类型<br />
  29. 29. Partitioner类型<br />CollatingOrderPreservingPartitioner<br />和OrderPreservingPartitioner一样是有序分区策略。只是排序的方式不一样,采用的是字节型Token。支持设置不同语言环境的排序方式,代码中默认是en_US。<br />将制定的Token信息按照不同语言环境来编组转化为字节数组。<br />其它与ByteOrderedPartitioner完全一致。<br />
  30. 30. 副本策略<br />LocalStrategy:只在本地节点中保持一个副本。<br />RackUnawareStrategy:不考虑机柜因素,将Token按照从小到大的顺序,从第一个Token位置处依次取N个节点作为副本。<br />RackAwareStrategy:考虑机柜因素,在primaryToken之外,先找一个处于不同数据中心的点,然后在不同机柜找。<br />
  31. 31. 副本策略<br />LocalStrategy:只在本地节点中保持一个副本。<br />RackUnawareStrategy:不考虑机柜因素,将Token按照从小到大的顺序,从第一个Token位置处依次取N个节点作为副本。<br />RackAwareStrategy:考虑机柜因素,在primaryToken之外,先找一个处于不同数据中心的点,然后在不同机柜找。<br />
  32. 32. 副本策略<br />LocalStrategy:只在本地节点中保持一个副本。<br />RackUnawareStrategy:不考虑机柜因素,将Token按照从小到大的顺序,从第一个Token位置处依次取N个节点作为副本。<br />RackAwareStrategy:考虑机柜因素,在primaryToken之外,先找一个处于不同数据中心的点,然后在不同机柜找。<br />
  33. 33. 副本策略<br />DatacenterShardStategy:这需要复制策略属性文件,在该文件中定义在每个数据中心的副本数量。在各数据中心副本数量的总和应等于Keyspace的副本数量。<br />举例来说,如果Keyspace的副本总数是6,数据中心副本因子可能是3、2和1 ,3个副本、2个副本、1个副本分别在不同数据中心 - 共计6。<br />
  34. 34. 副本策略<br />Cassandra-rack.properties<br /># Cassandra Node IP=Data Center:Rack<br />192.168.1.200=DC1:RAC1<br />192.168.2.300=DC2:RAC2<br />10.0.0.10=DC1:RAC1<br />10.0.0.11=DC1:RAC1<br />10.0.0.12=DC1:RAC2<br />10.20.114.10=DC2:RAC1<br />10.20.114.11=DC2:RAC1<br />10.21.119.13=DC3:RAC1<br />10.21.119.10=DC3:RAC1<br />10.0.0.13=DC1:RAC2<br />10.21.119.14=DC3:RAC2<br />10.20.114.15=DC2:RAC2<br /># default for unknown nodes<br />default=DC1:r1<br />
  35. 35. Agenda<br />基础知识<br />数据模型<br />数据分布策略<br />存储机制<br />数据读写删<br />最终一致性<br />Gossiper<br />面向未来<br />
  36. 36. 存储机制<br />Storage Model<br />Memtable<br />SSTable<br />Commitlog<br />Compaction<br />
  37. 37. Storage Model<br />
  38. 38. Memtable/SSTable<br />数据先写入内存中的Memtable,写入关键路径上不需要持有任何锁,Memtable达到条件后刷新到磁盘,保存为SSTable,SSTable不可修改 <br />Memtable刷新到磁盘的三个条件<br />
  39. 39. Memtable/SSTable<br />同一个CF的多个SSTable可以合并(Compaction)以优化读操作<br />通过布隆过滤算法(Bloom Filter)减少对不可能包含查询key的SSTable的读取。<br />将随机写转变为顺序写,提升系统写性能。<br />
  40. 40. Memtable/SSTable<br />SSTable包含对应的三种文件<br />Datafile<br /> 按照Key排序顺序保存的数据文件<br /> 文件名称格式如下:ColumnFamilyName-序号-Data.db<br />Indexfile<br /> 保存每个Key在Datafile中的位置偏移<br /> 文件名称格式如下: ColumnFamilyName-序号-Filter.db<br />Filterfile<br /> 保存BloomFilter的Key查找树<br /> 文件名称格式如下: ColumnFamilyName-序号-index.db<br />
  41. 41. Commitlog<br />Commitlog是server级别的,不是Column Family级别的,每一个节点上的Commitlog都是统一管理。<br />每个Commitlog文件的大小是固定的,称之为一个CommitlogSegment,目前版本(0.7.0)中,这个大小是128MB,硬编码在代码中。<br />当一个Commitlog文件写满以后,会新建一个的文件。<br />SSTable持久后不可变更,故Commitlog只用于Memtable的恢复,相当于Oracle的Instance Recovery。Cassandra不需要做Media Recover<br />当节点异常重启后,将根据SSTable和Commitlog进行实例恢复,在内存中重新恢复出宕机前的Memtable。<br />当一个Commitlog文件对应的所有CF的Memtable都刷新到磁盘后,该Commitlog就不再需要,系统会自动清除。<br />
  42. 42. Commitlog<br />每个Commitlog文件(CommitlogSegment)都有一个CommitlogHeader,紧随其后则是序列化之后的变更的RowMutation对象。<br />Key是在Memtable中存在更新的CF_ID<br />Value保存的是Column Family在上一次Flush时日志的偏移位置,恢复时则可以从这个位置读取Commitlog记录。<br />
  43. 43. Commitlog<br />Commitlog刷新有两种机制:<br />Batch:当CommitlogSegment刷新到磁盘后,插入Memtable操作才可继续。并且需要等待CommitLogSyncBatchWindowInMS毫秒(默认值1,建议0.1~10)内的其他写操作一起批量刷日志到磁盘。可以类比为Oracle的batch/wait模式。<br />Periodic :每隔CommitLogSyncPeriodInMS毫秒(默认值10000)性刷新CommitlogSegment,不阻塞数据写操作,可以类比为Oracle的batch/nowait模式。<br />
  44. 44. Compaction<br />
  45. 45. Compaction<br />一个CF可能有很多SSTable,系统会将多个SSTable合并排序后保存为一个新的SSTable,称之为Compaction。<br />一次compaction最多请求合并32个SSTable,最少4个。超过32个则按时间排序分批进行(这两个阈值可以设置)。<br />如果空间不足,则尝试去掉最大的SSTable再合并,如果连合并两个最小的SSTable的空间都不足,则告警。<br />Major Comaction:合并CF的所有SSTable为一个新的SSTable,同时执行垃圾数据(已标记删除的数据tombstone)清理。<br />Minor Compaction:只合并大小差不多的SSTable,超过4个需要合并的SSTable就会自动触发。<br />可通过nodetool compact命令手动触发。<br />数据目录最好保持50%以上的可用空间。<br />
  46. 46. Compaction<br />Compaction将旧的SSTable的记录按序写入到新的名字包含tmp的SSTable,完成后重命名去掉tmp,切换到新文件后,再将原SSTable删除。<br />可以通过设置Compaction的minthreshold(默认4)和maxthreshold(默认32)来改变触发一次Comaction合并的最少SSTable数和最多SSTable数。<br />如果设置minthreshold=0或者maxthreshold=0,则会禁止系统自动执行Minor Compaction。建议在业务高峰期禁止Compaction,定期到业务低峰期通过nodetool compact手工执行Major Compaction。<br />以上两个参数可以通过nodetool设置:<br />Nodetoolsetcompactionthreshold[minthreshold] ([maxthreshold])<br />
  47. 47. Agenda<br />基础知识<br />数据模型<br />数据分布策略<br />存储机制<br />数据读写删<br />最终一致性<br />Gossiper<br />面向未来<br />
  48. 48. 数据读写删<br />Quorum NRW<br />Read<br />Write<br />ConsistencyLevel<br />Delete<br />
  49. 49. Quorum NRW<br /> N: 复制的节点数量<br /> R: 成功读操作的最小节点数<br /> W: 成功写操作的最小节点数<br />
  50. 50. Read<br />
  51. 51. Read<br />
  52. 52. Write<br />
  53. 53. ConsistencyLevel(Write)<br />
  54. 54. ConsistencyLevel(Read)<br />
  55. 55. Delete<br />分布式删除存在的问题?<br /> 一个删除操作不可能一下子就将被删除的数据立即删除掉:如果客户端执行一个删除操作,并且有一个副本还没有收到这个删除操作,这个时候这个副本依然是可用的,此外,该节点还认为那些已经执行删除操作的节点丢失了一个更新操作,它还要去修复这些节点。<br />
  56. 56. Delete<br />Cassandra中是怎么做的?<br />不会去直接删除数据,Cassandra使用一个被称为墓碑的值。这个墓碑可以被传播到那些丢失了初始删除请求的节点。让每一个节点跟踪本地数据的墓碑值年龄。<br />常量GCGraceSeconds,默认为10天。<br />一旦数据持有的墓碑值的年龄超过这个常量,它将进行收集。<br />
  57. 57. Delete<br />什么时候才真正被删除掉呢?<br /> 我们在使用客户端从Cassandra中读取数据的时候,节点在返回数据之前都会主动检查是否该数据被设置了删除标志,并且该删除标志的添加时长已经大于GCGraceSeconds,则要先删除该节点的数据再返回。<br />
  58. 58. Agenda<br />基础知识<br />数据模型<br />数据分布策略<br />存储机制<br />数据读写删<br />最终一致性<br />Gossiper<br />面向未来<br />
  59. 59. 最终一致性<br />Hinted Handoff(提示移交)<br />Read Repair(读修复)<br />Anti Entropy(逆熵)<br />
  60. 60. Hinted Handoff<br />Key A按照规则首要写入节点为N1,复制到N2<br />假如N1宕机,如果写入N2能满足ConsistencyLevel要求,则Key A对应的RowMutation将封装一个带hint信息的头部(包含了目标为N1的信息),然后随机写入一个节点N3,此副本不可读。同时正常复制一份数据到N2,此副本可以提供读。如果写N2不满足写一致性要求,则写会失败。 <br />N1恢复后,原本应该写入N1的带hint头的信息将重新写回N1。 <br />HintedHandoff是实现最终一致性的一个优化措施,可以减少最终一致的时间窗口。 <br />
  61. 61. Read Repair<br />读取Key A的数据时,系统会读取Key A的所有数据副本,如果发现有不一致,则进行一致性修复。<br />如果读一致性要求为ONE,会立即返回离客户端最近的一份数据副本。然后会在后台执行Read Repair。这意味着第一次读取到的数据可能不是最新的数据。<br />如果读一致性要求为QUORUM,则会在读取超过半数的一致性的副本后返回一份副本给客户端,剩余节点的一致性检查和修复则在后台执行。<br />如果读一致性要求高(ALL),则只有Read Repair完成后才能返回一致性的一份数据副本给客户端。<br />该机制有利于减少最终一致的时间窗口。<br />
  62. 62. Anti Entropy<br />
  63. 63. Agenda<br />基础知识<br />数据模型<br />数据分布策略<br />存储机制<br />数据读写删<br />最终一致性<br />Gossiper<br />面向未来<br />
  64. 64. Gossip的作用<br />Cassandra集群没有中心节点,各个节点的地位完全相同,它们通过一种叫做gossip的协议维护集群的状态。<br />通过gossip,每个节点都能知道集群中包含哪些节点,以及这些节点的状态,这使得Cassandra集群中的任何一个节点都可以完成任意key的路由,任意一个节点不可用都不会造成灾难性的后果。<br />
  65. 65. Gossip协议<br />gossip的学名叫做Anti-entropy(逆熵?),比较适合在没有很高一致性要求的场景中用作同步信息。信息达到同步的时间大概是log(N),这里N表示节点的数量。<br />gossip有两种形式:anti-entropy和rumor-mongering。<br />gossip中的每个节点维护一组状态,状态可以用一个key/value对表示,还附带一个版本号,版本号大的为更新的状态。<br />消息的处理有3种方式,Cassandra采用第三种方式——Push-pull-gossip<br />
  66. 66. Gossip消息如何如何发送<br />当一个节点启动时,获取配置文件(cassandra.yaml)中的seeds配置,从而知道集群中所有的seed节点。<br />Cassandra内部有一个Gossiper,每隔一秒运行一次(在Gossiper.java的start方法中),按照以下规则向其他节点发送同步消息:<br />1、随机取一个当前活着的节点,并向它发送同步请求<br /> 2、向随机一台不可达的机器发送同步请求<br />3、如果第一步中所选择的节点不是seed,或者当前活着的节点数少<br /> 于seed数,则向随意一台seed发送同步请求<br />
  67. 67. Gossip消息如何如何发送<br />如果没有这个判断,考虑这样一种场景,有4台机器,{A, B, C, D},并且配置了它们都是seed,如果它们同时启动,可能会出现这样的情形:<br /> 1、A节点起来,发现没有活着的节点,走到第三步,和任意一个种子同步,假设选择了B<br /> 2、B节点和A完成同步,则认为A活着,它将和A同步,由于A是种子,B将不再和其他种子同步<br /> 3、C节点起来,发现没有活着的节点,同样走到第三步,和任意一个种子同步,假设这次选择了D<br /> 4、C节点和D完成同步,认为D活着,则它将和D同步,由于D也是种子,所以C也不再和其他种子同步<br />这时就形成了两个孤岛,A和B互相同步,C和D之间互相同步,但是{A,B}和{C,D}之间将不再互相同步,它们也就不知道对方的存在了。<br />加入第二个判断后,A和B同步完,发现只有一个节点活着,但是seed有4个,这时会再和任意一个seed通信,从而打破这个孤岛。<br />
  68. 68. Gossip数据结构<br />gossip通信的状态信息主要有3种:<br /> 1、EndPointState<br /> 2、HeartBeatState<br /> 3、ApplicationState<br />HeartBeatState由generation和version组成,generation每次启动都会变化,用于区分机器重启前后的状态<br />ApplicationState用于表示系统的状态,每个对象表示一种状态,比如表示当前load的状态大概是这样:(1.2, 20),含义为版本号为20时该节点的load是1.2<br />EndPointState封装了一个节点的ApplicationState和HeartBeatState<br />一个节点自身的状态只能由自己修改,其他节点的状态只能通过同步更新。<br />
  69. 69. Gossip状态信息有哪些<br />负载信息(LOAD-INFORMATION)<br />迁移信息(MIGRATION)<br />节点状态信息(MOVE)<br />BOOT(启动阶段)节点正在启动<br />NORMAL(正常)节点加入了Token的ring,可以提供读<br /> LEAVING,节点准备离开Ring<br />LEFT,节点被踢出集群或者是Token信息被手工变更<br />
  70. 70. Gossip消息同步过程<br />
  71. 71. Agenda<br />基础知识<br />数据模型<br />数据分布策略<br />存储机制<br />数据读写删<br />最终一致性<br />Gossiper<br />面向未来<br />
  72. 72. Twitter放弃Cassandra<br />1. Cassandra仍然缺少大并发海量数据访问的案例及经验,Cassandra来源自Facebook,但是在Facebook内部Cassandra目前只用在inbox search产品上,容量大约有100-200T。且Inbox Search在Facebook的基础架构中也并非核心应用。<br />2. 新产品需要一定稳定期,Cassandra代码或许还存在不少问题,但是Twitter如果投入大量的精力来改进Cassandra和比较优化MySQL的投入来看有点得不偿失。<br />
  73. 73. Flowdock转向MongoDB<br />稳定性问题<br /> 所有的节点都陷入无限循环(infinite loop),运行垃圾回收工作(GC, Garbage Collection)并尝试压缩数据文件——并偶尔导致集群瘫痪。除了对集群进行重启并经常性的手工对节点做压缩工作以让其稳定一会外,无计可施。其他人也报告过类似的问题。在前面几周的时间里,我们的Cassandra节点总是会吃掉给他分配的所有资源,而导致Flowdock运行缓慢。<br />运维问题<br /> 从Cassandra 0.4升级到0.5的时候,我们被迫关闭了整个集群,仅仅是为了将所有的数据刷新到磁盘上(虽然,我们已经按照文档进行了手工刷新的操作)。这个操作导致我们丢失了几分钟的讨论内容,以及我们手工创建的索引出现严重的不一致,以致于需要做完全的重建。<br />
  74. 74. Nosql支持率调查报告<br />
  75. 75. Performance improve<br />
  76. 76. 路还很长……<br />
  77. 77. Thanks!<br />

×