资源描述
单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,提 纲,概述和特点,数据模型,概念,排序,,twitter,,,rrd,Ring,写操作,读操作,API,性能测试和比较,配置说明,概 述,非关系的数据库,分布式的,Key-Value,存储系统,一堆数据库节点共同构成的一个分布式网络服务,对,Cassandra,的一个写操作,会被复制到其他节点上去,对,Cassandra,的读操作,也会被路由到某个节点上面去读取,特 点,模式灵活,:,使用,Cassandra,,像文档存储,你,不必提前解决记录中的字段,。你可以在系统运行时随意的添加或移除字段。这是一个惊人的效率提升,特别是在大型部署上。,真正的可扩展性,:,Cassandra,是纯粹意义上的水平扩展。为给集群添加更多容量,可以指向另一台电脑。你不必重启任何进程,改变应用查询,或手动迁移任何数据。,多数据中心识别,:,你可以调整你的节点布局来避免某一个数据中心起火,一个备用的数据中心将至少有每条记录的完全复制。,数据模型,数据模型,可以理解为四维或者五维的,hash,Cluster,包含多个,Keyspace,Keyspace,包含多个,ColumnFamily,,通常对应一个,application,,如,twitter,ColumnFamily,包含多个,Column,,或者是,SuperColumn,SuperColumn,:,包含有多个,Column,Column,最小数据单元,三元组:,name,value,timestamp,想象成一个,name/value,对,name,和,value,都是,byte,类型的,长度不限,例子:,name:,emailAddress,value:,foo,timestamp:123456789,所有的值都由客户点提供,包括,timestamp,,所以要求客户端同步;,Timestamp,的作用是用来解决数据冲突,几乎可以忽略;,Column,(三元组),SuperColumn,我们可以将,SuperColumn,想象成,Column,的数组,它包含一个,name,,以及一系列相应的,Column,/,这是一个,SuperColumn,name:,“Address,value:,name:,“,street,”,value:,“,中关村”,timestamp,:,1234,name:,“,city,”,value:,“,北京,”,,,timestamp,:,1234,Column,和,SuperColumn,都是,name,与,value,的组合,只是,value,部分不一样;,SuperColumn,的,value,部分是,columns,;,注意:,SuperColumn,本身是不包含,timestamp,的;,ColumnFamily,ColumnFamily,是一个包含了许多,Row,的结构,类似数据库的,Table,。,每一个,Row,都包含有,Key,以及和该,Key,关联的一系列,Column,。,UserProfile,/ColumnFamily,user1,:,/key,username:,“x,email:,“,x,phone:,“134666666,/,第一个,row,结束,user2,:,/key,username:,“,zi,email:,zi,phone:,“1399888888,age:“24”,/,第二个,row,结束,ColumnFamily,的类型:,Standard,(,column,)或,Super,(,Super column,),。,ColumnFamily,SuperColumn,family,Column family,Cassandra,和关系数据库的对比:,Column name,字段名,Column value,值,Key primary key;row,Columnfamily,table,Keyspace,database,Cluster server,插入:,cassandra,set Keyspace1.Standard1jsmithfirst=John,Value inserted.cassandra,set Keyspace1.Standard1jsmithlast=Smith,Value inserted.cassandra,set Keyspace1.Standard1jsmithage=42,Value inserted.,读取:,cassandra,get Keyspace1.Standard1jsmith (column=age,value=42;timestamp=1249930062801)(column=first,value=John;timestamp=1249930053103)(column=last,value=Smith;timestamp=1249930058345),Returned 3 rows.,排序,注意:在某一个,Key,的某个,CF,内的所有,Column,都是按照它的,Name,来排序的,不是按照,value,排序,故,cassandra,表设计有一个特殊的地方:,可以将真正的值存入,column name,,而将,column value,置为空“”,排序类型可以配置,BytesType,UTF8Type,,,LexicalUUIDType,TimeUUIDType,AsciiType,,,LongType,Cassandra,的排序功能是允许我们自己实现的,,只要你继承,org.apache.cassandra.db.marshal.IType,Supercolumn,可以指定两级排序,Twitter,的数据模型,Users CF,记录用户的信息,,Statuses CF,记录,tweets,的内容,,StatusRelationships,CF,记录用户看到的,tweets,UserRelationships,CF,记录用户看到的,followers,Users CF,记录用户的信息,,Statuses CF,记录,tweets,的内容,,StatusRelationships,CF,记录用户看到的,tweets,UserRelationships,CF,记录用户看到的,followers,RRD,数据的设计,只有一个,DS,的情况,可以只用,column,;多个,DS,,采用,supercolumn,;,要点:采用,timestamp,作为,super column name,,排序方式采用,TimeUUIDType,;,第一种方法:,“8.60”:/key,CpuUsage:/CF,“10000000”,:,“used”,:,”,30”,,,”,free”,:,”,70”/Super column,“10000300”,:,“used”,:,”,20”,,,”,free”,:,”,80”/Super column,“10000600”,:,“used”,:,”,25”,,,”,free”,:,”,75”/Super column,.,第二种方法:,相当于,super coumn name,就是,RRD,的,DS name,;,这种做法似乎更符合,cassandra,说的可以认为,super coumn name,是一个目录的这种结构。,“,8.60”:/key,CpuUsage:/CF,“free”,:,/super coumn name=free,“10000600”,:,“,30”,“10000900”,:,“,40”,.,“used”,:,/super coumn name=used,“10000600”,:,“,70”,“10000900”,:,“,60”,.,Ring,节点环,所有节点都是对等关系,Ring,数据到底存储在哪些个节点?,集群中的节点组成环,Token,给每一个节点指定一个唯一的整数,token,(,0,至,2127),作用:确定数据的第一个副本存储在哪个节点,所有的,key,都会被,MD5hash,成,0,至,2127,之间的整数,每个节点负责存储一个,key range,里面的,key,的第一个副本,按照副本放置策略(,ReplicaPlacementStrategy,)和 副本个数(,ReplicationFactor,),确定存储其它,n-1,个副本的 其它,n-1,个节点,两种副本策略:,RackUnawareStrategy,和,RackAwareStrategy,Ring,根据副本策略,在环上确定数据到底存储在哪些个节点,配置:(副本个数:,3,),org.apache.cassandra.locator.,RackUnawareStrategy,写操作,Commitlog,Memtable,Sstable,详细流程,Write,先写日志文件,commitlog,,然后数据才会写入到,Column Family,在内存中对应的,Memtable,中,,Memtable,满足一定条件后批量刷新到磁盘上,存储为,SSTable,。,Commitlog,位置:,disk,作用:确保异常情况下,根据持久化的,SSTable,和,Commitlog,重构内存中,Memtable,的内容,写操作:先写,Commitlog,再写,Memtable,当一个,Commitlog,文件写满以后,会新建一个的文件。,当旧的,Commitlog,文件不再需要时,会自动清除。,在恢复的时候,所有的磁盘上存在的,Commitlog,文件都是需要的,Memtable,一种,memory,结构,每个,CF,对应一个,Memtable,内容按照,key,排序,缓存写回机制,满足一定条件后批量刷新到磁盘上,存储为,SSTable,;,下一次,Memtable,需要刷新到一个新的,SSTable,文件中,优势,将随机,IO,写变成顺序,IO,写,降低大量的写操作对于存储系统的压力,可以认为只有顺序写,没有随机写操作,Sstable,存储位置:,disk,按照,key,排序后存储,key/value,键值字符串,Sstable,一旦完成写入,就不可变更,只能读取,为了避免大量,SSTable,带来的性能影响,定期将多个,SSTable,合并成一个新的,SSTable,,称之为,Compaction,Compaction,Merge keys,Combine columns,SSTable,中的,key,都是已经排序好的,因此只需要做一次合并排序就可以完成该任务,Sstable,的,data,目录,Column Family Name-,序号,-,Data.db,SSTable,数据文件,按照,key,排序后存储,key/value,键值,Column Family Name-,序号,-,Filter.db,Bloom Filter,算法生产的映射文件,;,Bloom Filter,算法,:,快速定位待查询的,key,所属的,SSTable,Column Family Name-,序号,-,index.db,索引文件,保存的是每个,key,在数据文件中的偏移位置,About writes.,No reads,No seeks,Sequential disk access,Atomic within a column family,Fast,Any node,Always writeable(hinted hand-o),写流程,假设副本个数:,n,写操作从客户端发送给一个节点,该节点作为代理,根据复制策略确定数据副本所在的,n,个节点,并发送写请求给这,n,个节点。,代理节点等待这,n,个节点中的某些节点的写响应并将写操作成功的消息告诉客户端(根绝写操作的,ConsistencyLevel,确定需要等待写成功的节点个数),这,n,个节点收到写请求后,做,2,个操作:,追加,commitlog,更新,memtable,所以写操作快的原因:写内存,慢的部分仅仅是写日志,后台有一些异步的事件可能发生:,Memtable,到阀值后要被,flush,到,sstable,同一个,cf,的多个,sstable,被合并成一个大的,sstable,写流程,写操作能覆盖老数据(根据,column,的,timestamp,来判断),Write,ConsistencyLevel,(副本个数:,n,),ONE,:确保写入至少一个节点的,commitlog,和,memtable,(其它,n-1,个节点也会去写),QUORUM,:确保至少写入,n/2+1,个节点,ALL,:确保写入,n,个节点,有单点失效问题,例子:,RackUnawareStrategy,的副本策略,Write,ConsistencyLevel,:,1,ReplicationFactor,=2,读操作,Read,查询数据时,需要去合并读取,Column Family,所有的,SSTable,和,Memtable,Bf,确定待查找,key,所在的,sstable,Idx,确定,key,在,sstable,中的偏移位置,读流程,假设副本个数:,n,读请求从客户端发送给一个节点,该节点作为代理,根据复制策略确定保存数据的,n,个节点,并发送读请求给这,n,个节点。,对于每一个收到读请求的节点:,读取,memtable,扫描,SSTable,ConsistencyLevel,ONE,:返回,第一个响应,的节点上面的数据,不保证数据时最新的;但是会做读修复,一致性检查,这样后续的调用能够得到最新的数据(有些延迟),QUORUM,:查询所有节点,返回至少,/2+1,个节点中的最新的数据;也有读修复,ALL,:查询所有节点,返回所有节点中最新的数据;,一个节点失效将导致读失败,About reads.,Any node,Read repair,Usual caching conventions apply,读写操作,API,update,insert():,(一行一列)写入一个,column,By key,batch insert():,(一行多列)写入多个,Columns or,SuperColumns,,还可以跨越不同的,ColumnFamily,By key,remove():,删除一行的一列,或者一行所有列,By key,并不会马上从,disk,中删除数据,Querying,get():,(,一行一列,),获取一个,column,或者,SuperColumn,get_slice,():,(,一行多列,)Get the group of,columnOrSupercolumn,,结果受排序方式影响,;by column name,or a range of names,multiget,():,(,多行一列,)by column name for a set of keys,multiget_slice,():,(,多行多列,)a subset of columns for a set of keys,get count:,number of columns or sub-columns,get_range_slice,():,支持指定范围查询(多行多列,),subset of columns for a range of keys,配置中要求是,order-preserving,partitioner,性能测试,Performance,vs,MySQL,w/50GB,官方数据,MySQL,300ms write,350ms read,Cassandra,0.12ms write,15ms read,测试性能,写入,20,万条数据,读出,20,万条数据,单线程:,Cassandra,Write,:,161125 ms,,平均,0.8 ms/,条,Read,:,2658516 ms,,平均,13 ms,并发性能好,配 置,集群最基本的配置,ClusterName,每一个集群的名称都应该是不一样的,AutoBootstrap,设置为,true,,节点自动加入集群,Seeds,本节点,ip,集群中任何一个节点的,ip,ReplicationFactor,数据备份的副本个数,ListenAddress,绑定自己的,ip,地址,用于其它节点和它通信,直接留空:,InetAddress.getLocalHost,(),ThriftAddress,Thrift,服务的的绑定地址,设置为,0.0.0.0,监听所有,interfaces,添加一台服务器,影响:,会自动迁移数据(,AutoBootstrap,)到该节点,这个过程是后台的,健壮的,智能的。比如,,bootstrap,启动后,你关闭了某个节点,过一段时间后再启动,原先中途终止的数据迁移会继续进行,不会有数据丢失。,只需要修改该服务器的配置文件,指向集群中任一个节点,8.10,本节点,8.60,集群中的任一个节点,自动加入集群,完成数据迁移工作,true,保证集群名字一样,Cluster1,可以使用命令查看加入集群成功与否(注意:只有在看到其它节点才算成功,最好确保其它节点和该节点之间彼此都能看到彼此),sh,nodeprobe,-host.8.60-port 8080 ring,删除一台服务器,影响:,因为可以对数据有多个备份,不会丢失数据;,删除并不会自动删除该节点的数据;,1.,对要,remove,的节点,执行,nodeprobe,decommission,命令;,2.,对其它每个节点,执行,nodeprobe,removetoken,命令,删除这个不用的,token,,同时其它节点会产生一些数据复制的工作。,对被删除节点:,sh,nodeprobe,-host 58.37 port 8080 decommission,;然后关闭其,cassandra,对其它节点:,sh,nodeprobe,-host 8.10-port 8282,removetoken,参数,token,sh,nodeprobe,-host 8.60-port 8080,removetoken,参数,token,sh,nodeprobe,-host 8.119-port 8080,removetoken,参数,token,注意:如果该节点要以不同的,token,再次加入该集群,就需要手动把数据都删除掉。,(,data,,,commitlog,,,log,文件都要删除掉),修改,keyspace,和,cf,目前是必须要修改配置文件并重启机器(以后可能会支持程序配置);,每个节点要依次修改;,修改步骤:,Kill cassandra process on one server of the cluster,Start it again,wait for the commit log to be written on the disk,and kill it again,Make the modifications in the storage.xml file,Rename or delete files in the data directories according to the changes we made(,新建,keyspace,和,cf,无须此操作,),Start cassandra,Goto 1 with next server on the list,Memtable,的配置,MemtableSizeInMB,每个,CF,的,Memtable,的阀值,到了这个阀值后将被,flush,到,sstable,;设置过大会使插入大量数据后变慢,MemtableObjectCountInMillions,每个,CF,的,Memtable,的最大,column,数目,如果有,100,行,每行有,1000,列,则这个数是,100*1000,列,这两个值用于控制内存的使用情况,设置大小:取决于,cf,个数,每个,cf,的,columns,数,还有,value,的大小,使用,jconsole,跟踪:,service:jmx:rmi:/jndi/rmi:/ip:8080/jmxrmi,参考,MemtableDataSize,来设置,MemtableSizeInMB,参考,MemtableColumnsCount,来设置,MemtableObjectCountInMillions,使用,jconsole,还可以手动,flush,memtable,到,sstable,Partitioner,当一个节点加入集群时,如果不指定,InitialToken,,则使用算法分配给节点一个,token,,使得这个节点将负责当前集群中负载最重的节点(,keys,最多)一半的负载(,keys,),Partitioner,:,决定了数据如何分布在集群中,一旦配置了就不能改变,除非将数据的删除掉,因为变化会修改,sstable,的磁盘格式,RandomPartitioner,能保证负载均衡地散落在节点中,但是不支持,range scan,OrderPreservingPartitioner,支持,range query,Knows how to map a range of keys directly onto one or more nodes,不一定保证负载均衡,可以通过配置,InitialToken,,确保负载均衡,ReplicaPlacementStrategy,假设,ReplicationFactor,=n,确定第一个节点:,key MD5Hash,后的值落在一个节点负责的,keyrange,,则这个节点存储这个,key,的第一个副本,RackUnawareStrategy,将其它,n-1,个副本存储在第一个节点随后的,n-1,个节点,(in increasing Token order,),RackAwareStrategy,(没明白),将第,2,个副本存储在另一个,DC,中,其它,n-2,个副本存储在第一个节点所在的,DC,中,其 它,MemtableFlushAfterMinutes,停留在,Memtable,的数据被,flush,到,sstable,的最长等待时间,尽量大,以免引起,a flush storm,ConcurrentReads,建议:,2 concurrent reads per processor core,ConcurrentWrites,最大并发写数目,可提高以支持更好的并发,GCGraceSeconds,删除数据并不会马上将数据删除掉,而是等待,GCGraceSeconds,秒后才真正删除,客户端,支持,Thrift,,可以使用多种语言开发,客户端连接到哪一个节点?,建议采用,round robin DNS,
展开阅读全文