1 理论基础
1.1 简介
Apache Cassandra是一套开源分布式NoSQL数据库系统。它最初由Facebook开发,用于储存收件箱等简单格式数据,集Google BigTable的数据模型与Amazon Dynamo的完全分布式架构于一身。Facebook于2008将Cassandra开源,此后,由于Cassandra良好的可扩展性和性能,被Apple Comcast Instagram Spotify eBay Rackspace Netflix等知名网站所采用,成为了一种流行的分布式结构化数据存储方案。
在数据库排行榜“DB-Engines Ranking”中,Cassandra排在第七位,是非关系型数据库中排名第二高的(仅次于MongoDB)。
- 可弹性扩展性,允许根据需求增加节点满足更多的客户端请求
- 业务高可用性,架构具有容灾设计避免单点故障造成业务中断
- 线性规模性能,吞吐量随着节点数量的增加而呈线性增长
- 灵活数据存储,可满足所有数据格式,包括结构化,半结构化和非结构化且可动态调整数据结构
- 轻松数据分发,通过在多个数据中心复制数据,提供灵活的分布数据
1.2 系统架构
1.2.1 架构目标
- 分担多个节点之间的大数据负载
- 避免单点故障
1.2.2 架构特点
- 群集中的角色都相同,每个节点相互独立但同时与其他节点互连
- 群集中的每个节点都可以接受读取和写入请求,而无需理会数据在群集中的实际位置
- 当单点故障发生时,客户端可以从群集中的其他非故障节点中提取或写入数据
1.3.3 数据复制
- Cassandra群集使用Gossip协议在节点间相互通讯和检测群集中的故障节点
- 群集中一或多个节点充当数据供给,如有过期节点Cassandra将最新数据返回给客户端并修复过期节点
1.3.4 关键部件介绍
- Node,指构成群集的成员服务器
- Data Center,群集中相关可用节点的集合
- Cluster,群集包含一个或多个数据中心
- Commit Lot,写入操作之前的记录日志,群集依赖日志做崩溃恢复。
- MemTable,驻留在内存中的数据结构,Commit Log后数据将写入到MemTable
- SSTable,当达到设定阈值,数据将从MemTable批量刷新到磁盘中存为SSTable
- Bloom filter,
-- 二进制向量数据结构,它具有很好的空间和时间效率,
-- 被用来检测一个元素是不是集合中的一个成员。
-- 如果检测结果为是,该元素不一定在集合中;
-- 但如果检测结果为否,该元素一定不在集合中。
1.3.5 数据写入流程
- 先记录日志(CommitLog)后写入数据
- 数据先写入到Column Family对应的Memtable中
- Memtable达到一定量时再批量刷新磁盘中存为SSTable
注:相当于缓存写回机制,它将随机IO转成顺序IO(降低存储压力)
1.4 数据模型
1.4.1 Colume
列是Cassandra中最小的数据单元,由以下元素组成:
- Name,唯一名称,用于引用列
- Value,列的内容,可以是不同的类型,如AsciiType,LongType,TimeUUIDType,UTF8Type等。
- TimeStamp,时间戳记,用于确定有效内容的系统时间戳
范例如下:
Name | Value | TimeStamp |
"age" | "18" | 1270694041669000 |
"height" | "172cm" | 1270694041669000 |
注:一行为一个Colume
1.4.2 Super Column
超级列相当于Column的数组或集合,由Super Column name和一个或多个的Column构成。
Super Column Name | Columns |
||
StudentA |
Name | Value | TimeStamp |
"age" | "20" | 1270694041669000 | |
"height" | "172cm" | 1270694041669000 |
1.4.3 Column Family
列族是一个NoSQL的对象(相当于关系型数据库的表),它包含描述对象属性的相关Column或Super Column。
列族分类:
- 普通列族,以列来描述族的属性
- 超级列族,以超级列来描述族的属性
Column Family Key | Columns |
||
StudentA |
Name | Value | TimeStamp |
"age" | "20" | 1270694041669000 | |
"height" | "172cm" | 1270694041669000 |
1.4.4 KeySpace
键空间是Cassandra中数据的最外层容器,其基本属性有,
- Replication factor,集群中将接收相同数据副本的计算技术
- Replica placement strategy,定义环中的复制策略
-- simple strategy,简单策略
-- old network topology strategy,旧网络拓扑策略
-- network topology strategy,网络拓扑策略
- Column families,列族(包含一个或多个列族)
1.4.5 总数据模型图
2 实践部分
2.1 环境信息
HostName = cassandra0[1-2].cmdschool.org
ipAddress = 10.168.0.5[1-2]
OS = CentOS 7.3 x86_64
2.2 JDK安装
2.2.1 下载JDK包
In cassandra0[1-2]:
1
2
|
cd
~
wget http:
//download
.oracle.com
/otn/java/jdk/8u121-b13/e9e7ea248e2c4826b92b3f075a80e441/jdk-8u121-linux-x64
.
tar
.gz?AuthParam=1495873209_eea482e2b59774918c970cf5dc383fdb
|
注:如需其他版本请参阅,http://www.oracle.com/technetwork/java/javase/archive-139210.html
2.2.2 创建java目录
In cassandra0[1-2]:
1
|
mkdir
/usr/java
|
2.2.3 解压
In cassandra0[1-2]:
1
2
|
tar
xf jdk-8u121-linux-x64.
tar
.gz
mv
jdk1.8.0_121/
/usr/java/
|
2.2.4 配置环境变量
In cassandra0[1-2]:
1
|
vim
/etc/profile
.d
/java
.sh
|
加入如下内容:
1
2
3
4
|
export
JAVA_HOME=
/usr/java/jdk1
.8.0_121
export
JRE_HOME=${JAVA_HOME}
/jre
export
CLASSPATH=.:${JAVA_HOME}
/lib
:${JRE_HOME}
/lib
export
PATH=${JAVA_HOME}
/bin
:$PATH
|
2.2.5 配置生效
In cassandra0[1-2]:
1
|
source
/etc/profile
|
2.2.6 环境变量测试
In cassandra0[1-2]:
1
|
java -version
|
2.3 安装Cassandra
2.3.1 先决条件检查
In cassandra0[1-2]:
1)JAVA检查
java -version
显示如下:
1
2
3
|
java version
"1.8.0_121"
Java(TM) SE Runtime Environment (build 1.8.0_121-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.121-b13, mixed mode)
|
2)python检查:
1
|
python --version
|
显示如下:
1
|
Python 2.7.5
|
2.3.2 下载安装包
In cassandra0[1-2]:
1
2
|
cd
~
wget https:
//mirrors
.tuna.tsinghua.edu.cn
/apache/cassandra/3
.10
/apache-cassandra-3
.10-bin.
tar
.gz
|
2.3.3 解压安装包
In cassandra0[1-2]:
1
|
tar
-xf apache-cassandra-3.10-bin.
tar
.gz
|
2.3.4 部署到程序目录
In cassandra0[1-2]:
1
2
|
mkdir
/usr/cassandra
mv
apache-cassandra-3.10
/usr/cassandra/
|
2.3.5 配置运行用户
In cassandra0[1-2]:
1
2
3
|
useradd
-s
/sbin/nologin
-b
/var/lib
cassandra
chown
-R cassandra:cassandra
/usr/cassandra/apache-cassandra-3
.10
chmod
-R 770
/usr/cassandra/apache-cassandra-3
.10
|
确认用户数据目录存在:
1
|
ls
-ld
/var/lib/cassandra/
|
显示如下:
1
|
drwx------. 6 cassandra cassandra 136 Jun 1 09:42
/var/lib/cassandra/
|
2.3.6 配置环境变量
In cassandra0[1-2]:
1)环境变量配置
1
|
vim
/etc/profile
.d
/cassandra
.sh
|
加入如下配置:
1
2
3
|
export
CASSANDRA_HOME=
/usr/cassandra/apache-cassandra-3
.10
export
CASSANDRA_PATH=${CASSANDRA_HOME}
/bin
export
PATH=${CASSANDRA_PATH}:$PATH
|
2)使环境变量生效
1
|
source
/etc/profile
|
3)测试环境变量
1
|
cassandra -
v
|
显示如下:
1
|
3.10
|
2.3.7 配置Cassandra的环境变量
In cassandra0[1-2]:
1)环境变量配置
1
2
|
cp
-a
/usr/cassandra/apache-cassandra-3
.10
/bin/cassandra
.
in
.sh
/usr/cassandra/apache-cassandra-3
.10
/bin/cassandra
.
in
.sh.default
vim
/usr/cassandra/apache-cassandra-3
.10
/bin/cassandra
.
in
.sh
|
启用并修改如下配置:
1
2
|
# JAVA_HOME can optionally be set here
JAVA_HOME=
/usr/java/jdk1
.8.0_121
|
注:提示“Cassandra 3.0 and later require Java 8u40 or later.”时需要配置
2.4 配置Cassandra群集
2.4.1 环境变量配置
1
2
|
cp
-a
/usr/cassandra/apache-cassandra-3
.10
/conf/cassandra
.yaml
/usr/cassandra/apache-cassandra-3
.10
/conf/cassandra
.yaml.default
vim
/usr/cassandra/apache-cassandra-3
.10
/conf/cassandra
.yaml
|
修改如下配置:
In cassandra01:
1
2
3
4
5
6
7
8
9
10
11
|
cluster_name:
'Cassandra Cluster'
seed_provider:
- seeds:
"10.168.0.51,10.168.0.52"
listen_address: 10.168.0.51
rpc_address: 10.168.0.51
start_rpc:
true
data_file_directories:
-
/var/lib/cassandra/data
commitlog_directory:
/var/lib/cassandra/commitlog
saved_caches_directory:
/var/lib/cassandra/saved_caches
|
In cassandra02:
1
2
3
4
5
6
7
8
9
10
11
|
cluster_name:
'Cassandra Cluster'
seed_provider:
- seeds:
"10.168.0.51,10.168.0.52"
listen_address: 10.168.0.52
rpc_address: 10.168.0.52
start_rpc:
true
data_file_directories:
-
/var/lib/cassandra/data
commitlog_directory:
/var/lib/cassandra/commitlog
saved_caches_directory:
/var/lib/cassandra/saved_caches
|
注:seeds的配置允许只写其他节点的IP,不写本机IP。
2.4.2 配置cassandra-env环境脚本
1
2
|
cp
-a
/usr/cassandra/apache-cassandra-3
.10
/conf/cassandra-env
.sh
/usr/cassandra/apache-cassandra-3
.10
/conf/cassandra-env
.sh.default
vim
/usr/cassandra/apache-cassandra-3
.10
/conf/cassandra-env
.sh
|
修改配置如下:
In cassandra0[1-2]:
1
2
|
MAX_HEAP_SIZE=
"1G"
HEAP_NEWSIZE=
"256M"
|
2.5 防火墙配置
In cassandra0[1-2]:
1
2
3
4
|
firewall-cmd --permanent --add-port 7000
/tcp
firewall-cmd --permanent --add-port 9042
/tcp
firewall-cmd --reload
firewall-cmd --list-all
|
2.6 服务的控制
2.6.1 测试服务启动
In cassandra0[1-2]:
1
|
sudo
-u cassandra
/usr/cassandra/apache-cassandra-3
.10
/bin/cassandra
-f
|
看到如下信息则服务正常启动:
1
|
INFO [Thread-2] 2017-06-01 10:51:47,640 ThriftServer.java:133 - Listening
for
thrift clients...
|
注:按下[Ctrl+C]可结束进程
2.6.2 确认服务正常启动
In cassandra0[1-2]:
1
|
pgrep -u cassandra -f cassandra
|
显示PID如下:
1
|
2596
|
2.6.3 检查群集的状态
In cassandra0[1-2]:
1
|
nodetool status
|
信息显示如下:
1
2
3
4
5
6
7
|
Datacenter: datacenter1
=======================
Status=Up
/Down
|/ State=Normal
/Leaving/Joining/Moving
-- Address Load Tokens Owns (effective) Host ID Rack
UN 10.168.0.51 213.63 KiB 256 100.0% 6faefd3b-e2cf-4477-a1c1-922d4f10b7a5 rack1
UN 10.168.0.52 103.69 KiB 256 100.0% 3cc4fdd7-53a0-4a67-be7f-fbe1cd8d0571 rack1
|
2.6.4 测试连接
In cassandra02:
1
2
|
cqlsh -ucassandra -pcassandra 10.168.0.51
cqlsh -ucassandra -pcassandra 10.168.0.52
|
2.6.5 结束进程
In cassandra0[1-2]:
1
|
pkill -f cassandra
|
2.6.6 配置服务控制脚本
In cassandra0[1-2]:
1
|
vim
/etc/init
.d
/cassandrad
|
输入如下内容:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
|
#!/bin/bash
# chkconfig: 2345 55 25
user=
"cassandra"
status() {
if
[ ! `pgrep -u $user -f cassandra |
wc
-l` -
eq
0 ];
then
echo
"statusChecking for service cassandra running"
exit
0
else
echo
"statusChecking for service cassandra not running"
exit
1
fi
}
start() {
if
[ `pgrep -u $user -f cassandra |
wc
-l` -
eq
0 ];
then
sudo
-u $user
/usr/cassandra/apache-cassandra-3
.10
/bin/cassandra
>
/dev/null
for
((i=60; i>=0; i--))
do
sleep
1s
if
[ ! `pgrep -u $user -f cassandra |
wc
-l` -
eq
0 ];
then
echo
"start service cassandra finish"
break
&
exit
0
fi
if
[ $i -
eq
0 ];
then
echo
"start service cassandra failed"
exit
1
fi
done
fi
}
stop() {
if
[ ! `pgrep -u $user -f cassandra |
wc
-l` -
eq
0 ];
then
pgrep -u $user -f cassandra |
xargs
kill
-9
for
((i=60; i>=0; i--))
do
sleep
1s
if
[ `pgrep -u $user -f cassandra |
wc
-l` -
eq
0 ];
then
echo
"stop service cassandra finish"
break
&
exit
0
fi
if
[ $i -
eq
0 ];
then
echo
"stop service cassandra failed"
exit
1
fi
done
fi
}
case
"$1"
in
start)
start
;;
stop)
stop
;;
restart)
stop
start
;;
status)
status
;;
*)
echo
"Usage: $0 {start|stop|restart|status}"
exit
1
esac
|
2.6.7 配服务自动启动和启动服务
In cassandra0[1-2]:
1
2
|
chkconfig cassandrad on
/etc/init
.d
/cassandrad
start
|
=====================================