1.基于特性或功能的分片
2.基于键的分片
3.查找表
cassandra 数据库没有主从架构,所有节点是一样的
cassandra 会基于键值,将数据分片到多个节点
canssandra 分布式的去中心化的
cassandra 分布式 使用p2p协议,并使用gossip维护存活节点列表
水平扩展 简单来说就是增加更多服务器 需要同步机制
垂直扩展 增加机器能力
Cassandra是通过更新时,将数据传播给所有副本。Casandra保证总是可写,将冲突留给读操作。
Cassandra 让客户端选择一致性级别,也就是传播多少副本才允许不阻塞
Cassandra 分区的行数据库,数据库存储在稀疏的多维哈希表里面。稀疏是指,对于一行可以有一个或多个列,但是类似的每一行不需要有相同的列。
cassandra 使用cql 语句。
cassandra 是针对很大的写吞吐量实现的
集群
keyspace 键空间 ----》数据库
表
行
列
分区键
时间戳
ttl 生存时间 在列级存贮
uuid
timruuid
可以以set list map的方式存贮数据
如果想不通过主键查询数据,可以建立二级索引
canssandra 没有连接 通常建议采用反规范化的表来表示连接
没有表之间的引用完整性
反规范化不需要害怕
相关的列定义在同一个表里面
分区是否过大 即宽行是否过长 分区大小由分区中存储的单元限制
cassandra的故障检测由phi值累积型故障检测 通过对心跳检测 输出可信度
确定一个集群中各个节点的远近程度,这可以确定那些节点。snitch会收集网络拓扑的有关信息,使Cassandra有效的路由请求
默认的snitch 不适合多集群中心
将一个数据的管理表示为环 用64位标志作为id
新版本采用虚拟节点 即一个节点多个令牌 避免节点替换的大量开销
通过分区键哈希计算然后得到令牌,根据令牌分布到环中
采用得到多少节点的响应即可
读操作 协调器会标志那些节点作为读数据的副本,并将查询转发给它
写操作 协调器会联系所有的副本节点 (由一致性和副本因子决定),副本数达到一定的数目时,这个写操作成功。
写操作完成 会写入提交日志 一种失败恢复机制(保证数据没写入内存中的数据结构Memtable时,还有可能恢复数据。如果数据库意外关闭,奔溃,提交日志确保数据不会丢失)
写入提交日志之后,值会写入内存的一个数据结构中,称为memtable。
每个memtable包含一个特定的表的数据结构。在cassandra的早期实现中,memtable 存在jvm中,2.1版本以后,已将大多数memtable 存入原生内存中。可以使cassdra不那么容易受jvm影响。
存储在memtable中的对象数达到阈值时,memtable的内容会刷新到磁盘一个名为sstable的地方,然后创建新的memtable。这个刷新输出是一个非阻塞操作。对应一个表有多个memtable,其中一个memtable,其余的等待刷新输出。节点会很快的刷新输出,除非压力过大。
提交日志会维护一个内部标志位,指示它是否需要刷新输出。
Sstable 可压缩 节约空间
canssandra 所有的写操作都是顺序的,所以性能较好
读操作是会读取SSTable 和 memtable 来查找数据值,因为memtable可能包含没有刷新到磁盘的值
键缓存 存储分区键到行索引条目的映射,以便更快的读取存储在磁盘上的SStable.键缓存存在jvm堆上面。
行缓存 缓存所有的行 较大的内存消耗 存在堆外内存中
计数器缓存 减少堆最常访问的计数器的锁竞争来改善计数器性能
默认启用键缓存和计数器缓存
当一个写操作要提交给一个节点假设位b,此时b节点故障,cassandra会将实现移交给其他节点,其他节点会注意b节点什么时候回复正常,就向他发送写操作。注意提示投递到b节点,此期间数据不可读
提示移交存在一个问题:当一个节点下线一段时间会积累大量的提示,之后回复正常时,大量的提示发送过来时,节点压力过大,十分脆弱。
为了解决此问题,可以将提示存储限制在一定时间。也可以禁用
基于主流的paxos 实现
实现较复杂 开支比较大 节点和副本要有4次的通信 不同分区有不同 的Paxos状态,确保不同分区的事务不会互相影响
相当于一个标志删除位
默认10天后彻底删除
方便确定是否可能存在
sstable 会定期合并:
键会归并,列会组合,墓碑将被删除
另外会创建一个新的索引
合并策略 有多种
分别适合写密集 读密集 时间序列数据和基于日期的数据
合并还有一个 反合并 的操作 处理未修复的数据 将起和已修复数据分开
Cassandra 使用了一个逆熵协议,这是修复复制数据的一种gossip协议
简单来说就是比较副本数据,并调节观察副本之间的差异
逆熵修复 又叫主动修复 基于哈希树实现,用哈希树来表示一张表,通过和不同节点对哈希树的比较,如果不匹配则需要修复。
cassandra 并发模型是基于seda 的 一个操作可以在一个线程开始,然后工作转交给另一个线程,以此类推。实际上,工作会划分到阶段,并由与阶段关联的线程池来确定如何执行
阶段是一个基本工作单元,一个操作在内部可能会从一个阶段转到下一个阶段,每个阶段由不同的线程池完成。
cassandra 的基本控制机制由一组类构成。
可以通过程序调试 cassandra
包含基本的生命周期
存储引擎 理解底层可以仔细看看
一个服务包装存储引擎
相应客户的请求工作
创建套接字监听器,完成消息交换:这个节点的入站消息和出站消息都会通过这个服务。
流传输是cassandra的一个持久tcp连接将ssstable文件的各部分从一个节点 发送到另一个节点。
cql原生协议是客户端用来cassandra通信的二进制协议
cassandra 采用“内部测试” ,利用自己的存储来跟踪集群和本地节点的元数据。
ccm 可以通过github 获得 可以实现单台机器多节点集群
通过集群名区分机器
集群中的新节点,需要一个节点作为参考,由它(种子节点)获得数据
分区器设置如何根据分区键进行分区
大多数选项可以选择默认 可以更详细配置jmx
executeAsync() 操作支持与cassandra 的非阻塞交互
Future 是一个java泛型类型,用来描述异步的操作结果。可以查看每个Future来确认是否操作完成,然后根据绑定类型查询操作的结果。另外还有一些阻塞的wait()操作可以用来等待结果。
ListenableFuture接口 扩展了Future 并且增加了以给addlistener()操作,允许客户端注册一个回调方法,future完成时就会调用这个回调方法。这个回调方法在驱动程序管理的一个线程中调用,所以方法很快完成以避免调用占用驱动程序资源。
cassandra 一个列族的写操作总是原子操作。
canssandra 的可调一致性级别 意味着你可以在查询中
any 至少写入一个副本 ,提示算是一个写操作
one two three 返回到客户端之前,确保至少1个,2个或3个的提交日志和memtable
local_one 至少一个本地数据中心的响应
quorum 至少一半以上节点相应
local_quorum 至少本地数据中心 一半以上节点响应
each_quorum 类似上条 但是为每个数据中心
all 所有节点
Java 设置一致性级别 语句
Statement.setConsistencyLevel(ConsistencyLevel.LOCAL_ONE)
发送一个写请求到一个节点,该节点作为一个协调器。协调器使用分区器确定根据键空间的副本因子确定集合中那些节点时副本节点。协调器节点本身也可能是一个副本,如果没有足够的节点,满足一致性,会直接返回错误。
接下来,协调器节点为所写的数据向所有的副本发送写请求。确保线上节点数据一致。
集群跨数据中心,则会在其他各个数据中心分别选择一个远程协调器。
如果一个副本在超时时间内没有相应,就认为它已经下线,并存储一个写操作提示。提示通常不算成功的副本。
一个副本请求发生的交互:
1,追加到磁盘的提交日志中
2,增加到jvm 的memtable中
3,如果有行缓存,设置对应行无效
4,如果memtable或提交日志满了,将sstable刷新输出到磁盘
5,如果是协调器节点,将失败的写操作提示保存到其他节点
每个事务的范围仅限一个分区
每个事务由一个读和一个写完成,比较和设置
如果由于现有的值与你不期望的值不匹配导致事务失败,Cassandra会包含当前的值,你能直接决定是重试还是撤销。
批处理只能包含(Insert,update,delete)
批处理具有原子性,也就是说,批处理成功就是全部成功。
一个批处理,属于给定分区键的所有更新会独立完成,不过分区之间不能保证隔离。
批处理可以包含轻量级事务,一个批处理的多个轻量级事务必须应用于同一个分区。
计数器批处理 只能包含计数器
批处理适合对多个表进行更新操作
批处理不适合进行批量加载
cassandra 的读数据很容易,连接任意节点即可完成读操作。
cassandra 读操作比写操作慢。因为读操作要进行查找。
one two three 立即返回第一个节点包含的记录。会创建一个后台线程对这个记录与其他副本的相同记录进行比较。如何有任何记录过期,就会完成一个读修复。
local one 类似一,要求相应节点必须是本地数据中心
quorum 查询所有节点,一半以上节点,做出相应,返回最新数据,需要则做读修复
local_quorum 与quorum类似,但相应节点必须在数据中心
each_quorum 确保每个数据中心都有一个quorum
all 等待所有的节点返回信息
客户端向协调器发起一个读查询。协调器使用分区器来确定副本,并检查是否有足够的副本满足请求一致性。当涉及多个数据中心时,会在每个数据中心选择一个远程协助器。
如果协调器本身不是一个副本,这个协调器会把读请求发送到最快的副本(由snitch 决定)。协调器还会向其他副本发送请求摘要,然后副本会返回请求数据的摘要或者哈希
协调器会从最快返回的数据计算摘要哈希,将它从其他副本返回摘要比较。如果摘要一致,且满足一致性哈希,就从最快的副本得到数据。
副本节点收到请求的内部交互
1 首先检查行缓存(如果启用了行缓存),若无,则检查键缓存查找索引,检查memetables
然后检查sstables
对应的一个表只有一个memtable 但是可能会有多个sstable,每个sstable 可能会包含请求的一部分。
cassandra 优化sstable搜索 : 键缓存,布隆过滤器,sstable 索引和摘要索引
在磁盘中搜索的第一步,布隆过滤器判断是不是可能存在,
布隆过滤器存在不同于sstable 文件的另一个文件,这样节点重启不用重新计算。
通过布隆检查,接下来检查键缓存,擦好看是否包含分区键在sstable中偏移的位置。键缓存实际是一个映射结构,其中键是sstable文件描述符和分区键组合,值是sstabel文件中的偏移位置。利用键缓存,可以避免sstable文件中查找频繁访问的数据,可以直接读取。
如果没能从键缓存得到偏移位置,cassandra会使用磁盘上存储的一个二级索引找到这个偏移位置。第一级索引为分区摘要,用来得到二级索引的偏移位置,从而在第二集索引中搜索分区键。分区键在sstable 中的偏移位置就存储在分区索引中。
找到分区键的偏移位置,cassandra 会在指定的偏移位置访问sstable,并开始读取数据。
一旦所有的sstable 得到数据了,cassandra会利用所请求的各个列的最新时间戳来选择值,来合并sstable和memtable数据。遇到的所有墓碑都会被忽略。
最后可以将合并后的数据增加到行缓存(如果启用),并返回给请求客户端或协调器。
摘要请求和常规请求步骤一致,只不过还有额外的一步,要对数据计算一个摘要,并只返回摘要
读修复: 协调器从所有的副本节点,发出一个完全读请求。协调器要为所请求的各个列选择一个值来合并数据。它会返回副本返回的值,并返回最新时间戳的值。如果cassandra 发现对应一个时间戳存了不同 的值,会按字典顺序比较值,并选择较大的值。这种情况少见
协调器确定了过期数据的副本,并向副本发送一个读修复。
读修复可以在返回客户端之前完成,也可能返回之后完成。由一致性级别影响
cassandra 可以加载csv 逗号分隔的数据 使用copy 命令
primary key (hotel_id, data, room_number) hotel_id 是分区键,data 和 room_number是集群列
类似与 primary key((hotel_id),data, room_number)
Cassandra 中的主键由一个或多个分区键和零个或多个集群键组件组成。这些组件的顺序始终将分区键放在第一位,然后是集群键。
where 字句必须包含分区键中的所有元素。
要限制一个给定的集群键,必须限制了它之前的所有集群键。
cassandra 支持min max count avg sum 等函数
支持分页limit
cassandra中删除数据与关系型数据库中不相同。在一个rdms 中,只需要执行一个delete语句指定想要的。cassandra 使用墓碑标志,当副本没有收到删除数据操作时,当这个副本恢复,会把墓碑传播到那些副本中。墓碑年龄到达配置时间(默认10天) 就会运行合并,将墓碑垃圾回收。由于sstable 是不可变的,所以并不是从sstable删除数据。合并时,会统计墓碑,对合并的数据排序,
后面基本是运维相关的,有空再记录