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去掉关系数据库的关系型特性,数据之间无关系,非常容易扩展。
Cassandra是具有最终一致语义的分区宽列存储模型,最初是由Facebook设计的,它使用了一种分阶段事件驱动架构(SEDA)来实现Amazon的Dynamo分布式存储和复制技术以及谷歌的Bigtable数据和存储引擎模型的组合。
Cassandra提供了Cassandra查询语言(CQL),这是一种类似sql的语言,用于创建和更新数据库模式以及访问数据。
CQL在分区数据集上支持许多高级特性,例如:
Apache Cassandra依赖于Amazon的Dynamo分布式存储键值系统的许多技术。Dynamo系统中的每个节点都有三个主要组件
Cassandra主要利用前两个集群组件,同时使用基于日志结构化合并树(Log Structured Merge Tree, LSM)的存储引擎。特别是Cassandra依赖于Dynamo风格:
Cassandra满足大规模(PiB+)业务关键型存储需求。特别是由于应用程序要求对pb级数据集进行完整的全球复制,同时还需要始终可用的低延迟读写。
使用令牌环的一致性哈希:Cassandra使用一种称为一致散列的特殊散列形式在存储节点上划分数据。在朴素数据哈希中,通常通过对键对桶数取模的哈希来将键分配给桶。例如,如果您希望使用朴素哈希将数据分布到100个节点,您可以将每个节点分配到0到100之间的存储桶,对输入键取模100进行哈希,并将数据存储在相关的存储桶中。然而,在这个简单的方案中,添加一个节点可能会使几乎所有映射失效。
相反,Cassandra将每个节点映射到一个连续哈希环上的一个或多个令牌,并通过将一个键哈希到环上,然后沿一个方向“行走”环来定义所有权,类似于Chord算法。一致哈希与普通数据哈希的主要区别在于,当要哈希的节点(桶)数量发生变化时,一致哈希只需要移动一小部分键。
# 通过官网下载下载最新的版本
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 -R
bin/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.100
rpc_address: 192.168.2.100
# 下面文件路径按需修改,建议多个盘分开提高读写性能
# 数据文件(如sstable)所在的一个或多个目录,默认$CASSANDRA_HOME/data/data
data_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
Cassandra Query Language(CQL),CQL提供了一个类似于SQL的模型;数据存储在包含行和列的表中。因此在本文档中使用时,这些术语(表、行和列)具有与SQL中相同的定义。
CQL是一种类型化语言,支持丰富的数据类型集,包括Native类型、集合类型、用户定义类型、元组类型和自定义类型
# CQL Shell 简称cqlsh,是一个可以和Cassandra数据库通信的客户端,使用这个cqlsh客户端可以执行Cassandra查询语言(CQL)。指定IP和端口连接cql
./bin/cqlsh 192.168.2.100 9042
describe 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;
create table test1 ( id int PRIMARY KEY, name text);
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));
create table test3 ( key_one int, key_two int, name text, PRIMARY KEY(key_one, key_two));
# 为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 '电影';
# 设置数据的ttl
INSERT INTO student (id,address,age,gender,name,interest, phone,education) VALUES (1030,'朝阳路30号',20,1,'Cary',{'运动', '游戏'},['020-7777888','139876667556'],{'小学' :'第30小学','中学':'第30中学'}) USING TTL 20;