写点什么

基于列存储的开源分布式 NoSQL 数据库 Apache Cassandra 入门分享

  • 2023-07-13
    福建
  • 本文字数:8316 字

    阅读完需:约 27 分钟

概述


定义


Apache Cassandra 官网地址 https://cassandra.apache.org/ 最新版本 4.1.1

Apache Cassandra 官网文档地址 https://cassandra.apache.org/doc/latest/

Apache Cassandra 源码地址 https://github.com/apache/cassandra

Apache Cassandra 是一个开源的分布式、高可用、最终一致性的 NoSQL 数据库,可以快速、可扩展可靠的管理海量数据,无单点故障。


NoSQL,泛指非关系型的数据库,NoSQL 去掉关系数据库的关系型特性,数据之间无关系,非常容易扩展。体验地址:http://www.jnpfsoft.com/?from=infoq


  • 易扩展:NoSQL 数据库种类繁多,但是一个共同的特点都是去掉关系数据库的关系型特性。数据之间无关系,这样就非常容易扩展,在架构的层面上带来了可扩展的能力。


  • 大数据量,高性能:NoSQL 数据库都具有非常高的读写性能,尤其在大数据量下。一般 MySQL 使用 Query Cache。NoSQL 的 Cache 是记录级的,是一种细粒度的 Cache,所以 NoSQL 在这个层面上来说性能就要高很多。


  • 灵活的数据模型:NoSQL 无须事先为要存储的数据建立字段,随时可以存储自定义的数据格式。而在关系数据库里,增删字段是一件非常麻烦的事情。


  • 高可用:NoSQL 在不太影响性能的情况,就可以方便地实现高可用的架构。比如 Cassandra、HBase 模型,通过复制模型也能实现高可用。


特性


  • 弹性可扩展性:允许添加更多的硬件以适应更多的客户和更多的数据根据要求。


  • 无中心化架构:没有单点故障,它可以连续用于不能承担故障的关键业务应用程序。


  • 快速线性性能:增加集群中的节点数量增加你的吞吐量。因此,保持一个快速的响应时间。


  • 灵活的数据存储:包括:结构化,半结构化和非结构化。它可以根据您的需要动态地适应变化的数据结构。


  • 便捷的数据分发:通过在多个数据中心之间复制数据,可以灵活地在需要时分发数据。


  • 事务支持:支持属性,如原子性,一致性,隔离和持久性(ACID)。


  • 快速写入


与 Hbase 对比


  • 架构:


HBASE 起源于 Google BigTable,几乎遵从了 BigTable 论文的大多数架构设计。Cassandra 则是采纳了 BigTable 的数据模型,同时吸收了 Amazon Dynamo 的分布式设计。从存储结构模型的微观上看,HBASE 和 Cassandra 在单点存储数据的机理是类似的,但是从分布式架构的宏观上看,两者则大相径庭。、从单点存储模型上看起来两者较为相似,有日志追加(WAL VS CommitLog),有内存写入缓冲区(MemStore VS MemTable),也都刷盘(flush)到 LSM-Tree 结构的持久化文件(StoreFile VS SSTable File),都用 Bloomfilter 和 Row Index 的组合模式进行行键的索引,它们也都是利用 BigTable 的数据模型结构实现高速的写入和热点数据的查找。从分布式架构上 HBASE 是中心化架构并满足分布式 CAP 定理中的 CP(分布式一致性),强调数据写入的强一致性;Cassandra 是去中心化架构并满足分布式 CAP 定理中的 AP(分布式高可用),适应数据在读取过程中完成最终一致性。


  • 关键特性由内看结构:


在查询方面 Cassandra 还支持二级索引,内置 CQL(MySQL 的 SQL 语法接近),SSTable 分层结构也侧重定位与查找;但 HBase 没有二级索引,只强调列簇的行键 scan,Region 中的 Store 与 HDFS 密切配合,StoreFile 中 KV 以顺序排列,存储强调整体的时间写入顺序。因此 Cassandra 就非常适合通过列字段为条件来查找,而 HBase 更擅长通过行扫描做列集分析。本质原因在于 Cassandra 的数据是基于一致性哈希算法,按照 HASH 范围划分,实现记录根据哈希值在整个集群节点的随机分布以及复本冗余,那么查找起来更适合在整个集群中对任何记录进行大范围的定位和查询,充分利用集群的整体算力;但是 HBase 是顺序的写入同一个 Region,在数据量足够大后再分裂,那么 HBase 就不适合频繁大范围的对数据定位与查找,更适合按行键做顺序扫描的集合分析。查询主要体现在就近和热点数据上的高性能。由外看分布式: Cassandra 的集群去中心化主要利用一致性哈希环机制实现数据的分布和扩容缩容的数据迁移,利用 gossip 协议在对等节点的网络传播下保存集群状态一致性,利用 anti-entropy(反熵)机制实现数据读取过程中节点之间的比对,保证数据一致性,这些都是集群在对等条件下基于机制而达成状态上的共识,那么 Cassandra 的这些特性,就使得集群不能太大,太大就不好管理,也容易导致网络通讯过于密集。Cassandra 这种去中心化架构表现出来的优点就是集群无单点故障隐患,集群健壮性高,可用性极高,运维很省事。HBASE 以及所依赖的 Hadoop HDFS 都是基于中心化集中式管理,存在 HMaster 的集群单点故障风险,因此一般 HBASE 的 HMaster 可以有一个或多个 HA 热备,引入 HA 后的 HBASE 集群依然很健壮,只是必然引入更高的部署复杂度,底层依赖的 HDFS NameNode HA 在服务部署复杂性方面则更甚之。


  • 适用场景:


HBASE 更侧重分析,Cassandra 则胜于查询 Cassandra 更适合在数据大吞吐的情况下,借助数据分布优势,高速写入,并通过二级索引实现 SQL 语法丰富的字段级查找,以及支持在线应用实时产生的超大规模数据的存储,可以在大规模数据写入与查询的都比较适合的场景下替代 MySQL,在事务和一致性要求不严格的环境下,为每天并发与写入量惊人的在线业务系统,提供数据库支撑。因此其面向服务的领域偏重 oltp。HBASE 更适合管理着大规模集群,并在超大规模数据之上进行实时的,结构化的海量数据支撑,而且满足强一致性要求,达到行级事务要求,可以使其对接一些关键性业务在可靠性要求高的环境下支撑在线实时分析,例如电子商务交易,金融交易等等。但并不适合随机性很强的查询,更适合大吞吐的数据写入,热点数据的行级查找以及大规模的扫描分析。并且具有 Hadoop 生态的数仓工具支撑。因此 HBASE 更面向 olap。


Cassandra 使用场景


  • 特征数据写入操作密集数据修改操作很少通过主键查询需要对数据进行分区存储


  • 场景举例存储日志型数据类似物联网的海量数据对数据进行跟踪


术语


  • cluster:使用 gossip 协议交换消息的两个或多个数据库实例。


  • commitlog:数据库将更改后的数据追加到文件,以便在故障后恢复。


  • datacenter:在集群中一起配置的一组相关节点,用于复制和工作负载隔离。不一定是单独的位置或物理数据中心。数据中心名称区分大小写,不能修改。


  • gossip:用于在节点之间交换位置和状态信息的点对点通信协议。


  • hint:除了 read-repair 和 full/incremental anti-entropy repair 之外,Cassandra 实现的三种方法之一,也是最终一致性保证,最终确认所有更新最终被所有副本接收。


  • listen address:要绑定到的地址或接口,并告诉要连接到的其他 Cassandra 节点。


  • seed node:种子节点用于引导加入集群的新节点。


  • snitch:节点 IP 地址到物理位置和虚拟位置(如机架和数据中心)的映射。


  • SSTable:提供了从键到值的持久的、有序的不可变映射,其中键和值都是任意的字节字符串。


架构


概览


Cassandra 是具有最终一致语义的分区宽列存储模型,最初是由 Facebook 设计的,它使用了一种分阶段事件驱动架构(SEDA)来实现 Amazon 的 Dynamo 分布式存储和复制技术以及谷歌的 Bigtable 数据和存储引擎模型的组合。


Cassandra 提供了 Cassandra 查询语言(CQL),这是一种类似 sql 的语言,用于创建和更新数据库模式以及访问数据。


  • Keyspace:定义每个数据中心如何复制数据集。复制是指每个集群保存的副本数量。键空间包含表。


  • Table:定义分区集合的类型化模式。表包含分区,分区包含行,行包含列。Cassandra 表可以灵活地向表中添加新列,并且零停机时间。


  • Partition:定义主键的强制部分,Cassandra 中的所有行都必须识别存储该行的集群中的节点。所有性能查询都在查询中提供分区键。


  • Row:包含由唯一主键标识的列集合,该主键由分区键和可选的其他集群键组成。


  • Column:具有属于行类型的单个数据。


CQL 在分区数据集上支持许多高级特性,例如:


  • 具有原子比较和设置语义的单分区轻量级事务。


  • 用户定义的类型、函数和聚合


  • 集合类型包括集合、映射和列表。


  • 本地二级索引


  • 物化视图(实验阶段)


Dynamo


Apache Cassandra 依赖于 Amazon 的 Dynamo 分布式存储键值系统的许多技术。Dynamo 系统中的每个节点都有三个主要组件


  • 请求分区数据集上的协调


  • 环成员和故障检测


  • 本地持久性(存储)引擎


Cassandra 主要利用前两个集群组件,同时使用基于日志结构化合并树(Log Structured Merge Tree, LSM)的存储引擎。特别是 Cassandra 依赖于 Dynamo 风格:


  • 使用一致哈希进行数据集分区


  • 使用版本化数据和可调一致性的多主复制


  • 通过 gossip 协议进行分布式集群成员和故障检测


  • 在商用硬件上的增量扩展


Cassandra 满足大规模(PiB+)业务关键型存储需求。特别是由于应用程序要求对 pb 级数据集进行完整的全球复制,同时还需要始终可用的低延迟读写。


数据集分区使用令牌环的一致性哈希


使用令牌环的一致性哈希:Cassandra 使用一种称为一致散列的特殊散列形式在存储节点上划分数据。在朴素数据哈希中,通常通过对键对桶数取模的哈希来将键分配给桶。例如,如果您希望使用朴素哈希将数据分布到 100 个节点,您可以将每个节点分配到 0 到 100 之间的存储桶,对输入键取模 100 进行哈希,并将数据存储在相关的存储桶中。然而,在这个简单的方案中,添加一个节点可能会使几乎所有映射失效。


相反,Cassandra 将每个节点映射到一个连续哈希环上的一个或多个令牌,并通过将一个键哈希到环上,然后沿一个方向“行走”环来定义所有权,类似于 Chord 算法。一致哈希与普通数据哈希的主要区别在于,当要哈希的节点(桶)数量发生变化时,一致哈希只需要移动一小部分键。



  • 令牌:发电机样式哈希环上的单个位置。


  • 端点:网络上的单个物理 IP 和端口。


  • 主机 ID:单个“物理”节点的唯一标识符,通常出现在一个 gEndpoint 上,并包含一个或多个 gtoken。


  • 虚拟节点(或 vnode):由相同物理节点拥有的哈希环上的 gToken,具有相同的 gHost ID。



存储引擎


  • CommitLog:提交日志是 Cassandra 节点本地所有突变的附加日志。写入 Cassandra 的任何数据都将首先写入提交日志,然后再写入记忆表。这在意外停机的情况下提供了持久性。在启动时,提交日志中的任何变化都将应用于 memtables。


  • Memtables:memtable 是 Cassandra 缓冲写入的内存结构;通常,每个表都有一个活动的 memtable;最终 memtable 被刷新到磁盘上,成为不可变的 sstable。


  • SSTables :SSTables 是 Cassandra 用于在磁盘上持久化数据的不可变数据文件。当 SSTables 从 memtable 被刷新到磁盘或从其他节点被流式传输时,Cassandra 触发压缩,将多个 SSTables 合并为一个。一旦编写了新的 SSTables ,就可以删除旧的 SSTables 。


部署


单实例部署


# 通过官网下载下载最新的版本wget https://dlcdn.apache.org/cassandra/4.1.1/apache-cassandra-4.1.1-bin.tar.gz# 解压tar -xvf apache-cassandra-4.1.1-bin.tar.gz# 进入目录cd apache-cassandra-4.1.1# 启动,如果是root用户启动bin/cassandra -Rbin/cassandra# 查看日志tail -f logs/system.log# 检查Cassandra的状态bin/nodetool status
复制代码



集群部署


准备三台 192.168.2.100、192.168.2.101、192.168.2.102,选择两台作为种子节点,分别在每台上修改配置文件 vim conf/cassandra.yaml


# 同一个集群名称一样cluster_name: 'Test Cluster'# 种子地址,配置多个示例,用逗号隔开seed_provider:  - class_name: org.apache.cassandra.locator.SimpleSeedProvider    parameters:      - seeds: "192.168.2.100,192.168.2.101"listen_address: 192.168.2.100rpc_address: 192.168.2.100# 下面文件路径按需修改,建议多个盘分开提高读写性能# 数据文件(如sstable)所在的一个或多个目录,默认$CASSANDRA_HOME/data/datadata_file_directories: /data1/cassandra/data# commitlog文件所在的目录commitlog_directory: /data2/cassandra/commitlog# 保存缓存的目录saved_caches_directory: /data3/cassandra/saved_caches# hints所在的目录hints_directory: /data4/cassandra/hints
复制代码


每台的 listen_address 和 rpc_address 修改为本机对应的,修改配置分别启动 cassandra


# 需要先杀死原来的cassandra进程,也可以自己准备脚本ps -ef | grep cassandra# 检查Cassandra的状态bin/nodetool status# 查询关于令牌环的信息bin/nodetool ring
复制代码


CQL


概述


Cassandra Query Language(CQL),CQL 提供了一个类似于 SQL 的模型;数据存储在包含行和列的表中。因此在本文档中使用时,这些术语(表、行和列)具有与 SQL 中相同的定义。


  • Data types

  • Data definition language

  • Data manipulation language

  • Operators

  • Secondary indexes

  • Materialized views

  • Functions

  • JSON

  • CQL security

  • Triggers

  • Appendices

  • Changes


数据模型



  • 列(Column):列是 Cassandra 的基本数据结构单元,具有三个值:名称,值、时间戳。在 Cassandra 中不需要预先定义列(Column),只需要在 KeySpace 里定义列族,然后就可以开始写数据了。


  • 列族( Column Family):列族不严谨来说相当于关系数据库的表(Table),是包含了多行(Row)的容器。

类型


静态 column family(static column family):字段名是固定的,比较适合对于这些 column 都有预定义的元数据。


动态 column family(dynamic column family):字段名是应用程序计算出来并且提供的,所以 column family 只能定义这些字段的类型,无法不可以指定这些字段的名字和值,这些名字和值是由应用程序插入某字段才得出的。


Row key:ColumnFamily 中的每一行都用 Row Key(行键)来标识,这个相当于关系数据库表中的主键,并且总是被索引的


主键:Cassandra 可以使用 PRIMARY KEY 关键字创建主键,分为 2 种


Single column Primary Key:如果 Primary Key 由一列组成称为 Single column Primary Key。


Composite Primary Key:如果 Primary Key 由多列组成,那么这种情况称为 Compound Primary Key 或 Composite Primary Key。


列族具有的属性


keys_cached - 它表示每个 SSTable 保持缓存的位置数。


rows_cached - 它表示其整个内容将在内存中缓存的行数。


preload_row_cache -它指定是否要预先填充行缓存。


  • 键空间 (KeySpace)


Cassandra 的键空间(KeySpace)不严谨相当于关系型数据库的数据库,创建一个键空间就是创建了一个数据库。键空间包含一个或多个列族(Column Family)。一般将有关联的数据放到同一个 KeySpace 下面,键空间 (KeySpace) 创建的时候可以指定一些属性:副本因子,副本策略,Durable_writes(是否启用 CommitLog 机制)


所有的副本都同样重要,没有主从之分。可以为每个数据中心定义副本因子。副本策略设置应大于 1,但是不能超过集群中的节点数。


  • 副本 (Replication):副本就是把数据存储到多个节点,来提高容错性。


  • 节点(Node):存储数据的机器。


  • 数据中心(DateCenter):数据中心指集群中所有的机器,组成了一个数据中心。


  • 集群(Cluster):Cassandra 数据库是为跨越多条主机共同工作,对用户呈现为一个整体的分布式系统设计的。Cassandra 最外层容器被称为群集。Cassandra 将集群中的节点组织成一个环(ring),然后把数据分配到集群中的节点(Node)上。


  • 超级列:超级列是一个特殊列,因此它也是一个键值对。但是超级列存储了子列的地图。


数据类型


CQL 是一种类型化语言,支持丰富的数据类型集,包括 Native 类型、集合类型、用户定义类型、元组类型和自定义类型


  • Native 类型:ASCII | BIGINT | BLOB | BOOLEAN | COUNTER | DATE | DECIMAL | DOUBLE | DURATION | FLOAT | INET | INT | SMALLINT | TEXT | TIME | TIMESTAMP | TIMEUUID | TINYINT | UUID | VARCHAR | VARINT


  • 集合类型:maps(使用大括号+键值)、sets(使用大括号)、lists(使用中括号)


  • 用户定义类型:CQL 支持定义用户定义类型(udt)。可以使用 create_type_statement、alter_type_statement 和 drop_type_statement 来创建、修改和删除这样的类型。


  • 元组类型:CQL 还支持元组和元组类型(其中元素可以是不同的类型)。从功能上讲,元组可以作为具有匿名字段的匿名 UDT。


# CQL Shell 简称cqlsh,是一个可以和Cassandra数据库通信的客户端,使用这个cqlsh客户端可以执行Cassandra查询语言(CQL)。指定IP和端口连接cql./bin/cqlsh 192.168.2.100 9042describe cluster;describe keyspaces;describe tables;
复制代码



基础操作


键空间


# 将输出内容捕获到名为outputfile的文件capture 'outputfile';# 创建键空间CREATE KEYSPACE school WITH replication = {'class':'SimpleStrategy', 'replication_factor' : 3};# 查看捕获内容cat outputfile
复制代码



# 查看键空间DESCRIBE school;# 使用键空间use school;# 修改键空间ALTER KEYSPACE school WITH replication = {'class':'SimpleStrategy', 'replication_factor' : 1};DESCRIBE school;# 删除键空间DROP KEYSPACE school;
复制代码




CREATE TABLE student(   id int PRIMARY KEY,     name text,     age int,     gender tinyint,     address text ,   interest set<text>,   phone list<text>,   education map<text, text>);# 列出当前键空间下所有表DESCRIBE Tables;# 查看表信息DESCRIBE TABLE student; 
复制代码



# 添加字段ALTER TABLE student ADD email text;select * from student;# 删除字段ALTER table student DROP email;select * from student# 删除表DROP TABLE student;# 清空表TRUNCATE student;
复制代码



key 索引


  • Primary Key 主键:是用来获取某一行的数据, 可以是单一列(Single column Primary Key)或者多列(Composite Primary Key)。在 Single column Primary Key 决定这一条记录放在哪个节点。


create table test1 (  id int PRIMARY KEY,  name text);
复制代码


  • Partition Key 分区 Key:在组合主键的情况下(上面的例子),第一部分称作 Partition Key(key_one 就是 partition key),第二部分是 CLUSTERING KEY(key_two)Cassandra 会对 Partition key 做一个 hash 计算,并自己决定将这一条记录放在哪个节点。如果 Partition key 由多个字段组成,称之为 Composite Partition key


create table test2 (  key_part_one int,  key_part_two int,  key_clust_one int,  key_clust_two int,  key_clust_three uuid,  name text,  PRIMARY KEY((key_part_one,key_part_two), key_clust_one, key_clust_two, key_clust_three));
复制代码


  • Composite Primary Key 复合 Key:如果 Primary Key 由多列组成,那么这种情况称为 Compound Primary Key 或 Composite Primary Key。执行创建表后,查询 testTab,会发现 key_one 和 key_two 的颜色与其他列不一样


create table test3 (  key_one int,  key_two int,  name text,  PRIMARY KEY(key_one, key_two));
复制代码


  • Clustering Key 集群:决定同一个分区内相同 Partition Key 数据的排序,默认为升序,可以在建表语句里面手动设置排序的方式。


索引


  • 普通列创建索引


# 为student的 name 添加索引,索引的名字为:sname, 命令:CREATE INDEX sname ON student (name);# 为student 的age添加索引,不设置索引名字,命令:CREATE INDEX ON student (age);DESCRIBE student;
复制代码



可以发现 对 age 创建索引,没有指定索引名字,会提供一个默认的索引名:student_age_idx。


索引原理:Cassandra 之中的索引的实现相对 MySQL 的索引来说就要简单粗暴很多了。Cassandra 自动新创建了一张表格,同时将原始表格之中的索引字段作为新索引表的 Primary Key!并且存储的值为原始数据的 Primary Key。


  • 集合列创建索引


#  set集合添加索引CREATE INDEX ON student(interest);    #  map映射添加索引CREATE INDEX mymap ON student(KEYS(education));   # 删除索引drop index sname;
复制代码



操作数据


# 插入数据INSERT INTO student (id,address,age,gender,name) VALUES (1011,'南京路',10,2,'mike') ;# 修改数据UPDATE student set age = 11 where id= 1011;# 批量操作BEGIN BATCH    INSERT INTO student (id,address,age,gender,name) VALUES (1012,'长沙路',12,1,'joo') ;    INSERT INTO student (id,address,age,gender,name) VALUES (1015,'上海路',20,1,'Jack') ;    UPDATE student set age = 15 where id= 1012;    DELETE FROM student WHERE id=1011;APPLY BATCH;# 删除数据DELETE FROM student WHERE student_id=1011;
复制代码



# 更新map类型数据UPDATE student SET education={'中学': '城市第五中学', '小学': '城市第五小学'} WHERE id = 1012;# 更新list类型数据UPDATE student SET phone = ['020-66666666', '13666666666'] WHERE id = 1012;# 更新set类型数据UPDATE student SET interest = interest + {'游戏'} WHERE id = 1012;
复制代码



# 查询条件select * from student where interest CONTAINS '电影';
复制代码



# 设置数据的ttlINSERT INTO student (id,address,age,gender,name,interest, phone,education) VALUES (1030,'朝阳路30号',20,1,'Cary',{'运动', '游戏'},['020-7777888','139876667556'],{'小学' :'第30小学','中学':'第30中学'}) USING TTL 20;
复制代码



文章转载自:itxiaoshen

原文链接:https://www.cnblogs.com/itxiaoshen/p/17270966.html


用户头像

还未添加个人签名 2023-06-19 加入

还未添加个人简介

评论

发布
暂无评论
基于列存储的开源分布式NoSQL数据库Apache Cassandra入门分享_开源_快乐非自愿限量之名_InfoQ写作社区