安装Cassandra
安装方式参考官网,环境Ubuntu18.04
1. 写入Cassandra
仓库
echo "deb http://www.apache.org/dist/cassandra/debian 311x main" | sudo tee -a /etc/apt/sources.list.d/cassandra.sources.list
2. 添加仓库公钥
curl https://www.apache.org/dist/cassandra/KEYS | sudo apt-key add -
3. 更新仓库源
sudo apt-get update
若是出现错误:
GPG error: http://www.apache.org 311x InRelease: The following signatures couldn't be verified because the public key is not available: NO_PUBKEY A278B781FE4B2BDA
执行操作:
sudo apt-key adv --keyserver pool.sks-keyservers.net --recv-key A278B781FE4B2BDA
4. 通过apt
安装
sudo apt install cassandra
等待安装完成后,Cassandra
默认即已启动,通过cql
命令即可进入交互环境:
cqlsh localhost
若成功进入,证明安装成功。Cassandra
相关命令:
sudo service cassandra start #启动
sudo service cassandra stop #停止
nodetool status #查看Cassandra状态,nodetool是Cassandra自带的管理工具
Cassandra
相关文件和目录:
配置文件目录:/etc/cassandra/
日志存储目录:/var/log/cassandra/
数据存储目录:/var/lib/cassandra/
启动配置文件(配置Cassandra启动时的堆大小等):/etc/default/cassandra
为Cassandra
配置用户名和密码
默认情况下,Cassandra
是不需要授权即可登录的,下面配置Cassandra
为用户名和密码授权并添加用户。
1. 修改授权方式
修改Cassandra
的配置文件/etc/cassandra/cassandra.yaml
:
sudo vi /etc/cassandra/cassandra.yaml
找到authenticator
与CassandraAuthorizer
字段配置如下:
authenticator: PasswordAuthenticator
authorizer: CassandraAuthorizer
然后重启Cassandra
:
service cassandra restart
2. 添加新用户
Cassandra
默认有一个用户名和密码都为cassandra
的超级用户,以该用户身份登录Cassandra
:
cqlsh localhost -ucassandra -pcassandra
然后创建一个新的超级用户:
cassandra@cqlsh> create user wt with password 'ceshi' superuser;
若无错误提示,即创建成功。
3. 删除默认用户
为更好的保证安全性,可以将默认的cassandra
用户删除,通过exit
命令退出Cassandra
后,用新创建的超级用户身份登入:
cqlsh localhost -uwt -pceshi
然后删除默认的cassandra
用户:
wt@cqlsh> drop user cassandra;
若无任何错误提示,即删除成功。
在所有服务器上安装Cassandra
在要搭建集群的所有服务器上依次安装好Cassandra
,这里用虚拟机创建了3个服务器,系统均为Ubuntu18.04
,ip
信息如下:
服务器名称 | ip |
---|---|
服务器1 | 192.168.22.130 |
服务器2 | 192.168.22.131 |
服务器3 | 192.168.22.132 |
分布式集群配置
这里选定服务器1与服务器2为seed
(种子)节点,服务器3为普通节点,首先配置服务器1,编辑/etc/cassandra/cassandra.yaml
配置文件:
sudo vi /etc/cassandra/cassandra.yaml
找到并配置以下字段:
seed_provider:
# Addresses of hosts that are deemed contact points.
# Cassandra nodes use this list of hosts to find each other and learn
# the topology of the ring. You must change this if you are running
# multiple nodes!
- class_name: org.apache.cassandra.locator.SimpleSeedProvider
parameters:
# seeds is actually a comma-delimited list of addresses.
# Ex: "<ip1>,<ip2>,<ip3>"
- seeds: "192.168.22.130,192.168.22.131" #填入所有种子节点的ip,逗号隔开,约在425行位置
listen_address: 192.168.22.130 #将默认的localhost修改为服务器自己的实际ip地址,约在599行位置
rpc_address: 192.168.22.130 #将默认的localhost修改为服务器自己的实际ip地址,约在676行位置
服务器2
和3
的配置同服务器1
,只是将listen_address
与rpc_address
配置为各自的ip
即可。
全都配置完成后,将所有服务器的cassandra
关闭,然后先启动所有seed
节点,再启动普通节点。当所有服务器启动完成后,在任一服务器上查看cassandra
状态:
nodetool status
若想访问数据库,连接至集群的任一节点即可。
cassandra
集群的数据存储
复制因子
简单的说就是当写入一条记录到cassandra
时,要为其保留几个副本,默认情况下复制因子是1
,即只保留一份,若当前节点挂掉,则可能导致该部分数据无法访问的情况。复制因子的设置不能超过集群的节点数量,否则无法进行写入。复制因子的设定是在建立keyspace
时确定的,如我们上边的集群中节点数量为3
,建立一个复制因子为2
的keyspace
:
create keyspace test with replication = {'class': 'SimpleStrategy', 'replication_factor': 2}
其中class
是复制策略,对于单数据中心而言(一个数据中心一般为一个集群),采用SimpleStrategy
,对于多数据中心而言,采用NetworkTopologyStrategy
,replication_factor
指明了复制因子大小。若要更改已存在命名空间的复制因子大小,cql
语句为:
alert keyspace "test" with replication = {'class': 'SimpleStrategy', 'replication_factor': 1}
数据存储和复制策略
当设置了复制因子后,若插入一条数据,这条数据应该插入到哪个节点呢?并且根据复制因子的设定,哪些节点应复制数据的备份呢?可以对要插入记录的的key
值进行hash
计算,根据hash
值确定插入或复制的节点,比如节点数量为n
,则将主键为key
的记录插入到第hash(key) % n
个节点上,但当节点数量发生变动时,比如增加了一个节点,则每个节点上的数据都会变动,因为对于同样的key
,记录要放在第hash(key) % (n + 1)
个节点上,相当于每个节点上对应的key
值都要变动。因此cassandra
采用了一致性哈希的策略。所谓一致性hash
,即设置对所有key
取hash
,使hash
值都能落到一个区间,这个区间叫做一致性hash
环。如设置一个0~232的hash
环,对任一key
取hash
,使之在0~232内有唯一对应的值,即在hash
环内有一个对应的位置,对于节点,也采取同样操作(如对节点的ip
取hash
),来确定节点在hash
环上的位置,将该key
的记录存储在顺时针方向距离最近的节点上,将该key
的记录的副本复制到顺时针方向相邻的数量为复制因子个数的节点上,如对于4
个节点复制因子为3
的命名空间中,存储一条记录时,示意图如下:
这样,当节点数量改变时,如在节点3和4间有了一个新节点,则只有其相邻节点的数据会发生变动,其它节点可以不受影响。但这种方式也存在一个问题,当集群中节点数量较少时,可能存在数据插入偏向某一节点的情况,因此,cassandra
中拥有虚拟节点的概念,即在hash
环中插入若干虚拟节点,一个真实节点对应若干虚拟节点,当一条数据想要插入时,会在包括虚拟节点内的所有节点中选择节点插入,若选择到了一个虚拟节点,虽然对数据来说是插入到了该虚拟节点中,但实际上数据是存储在该虚拟节点所对应的真实节点中,这样,通过在hash
环中遍布虚拟节点,便有效解决了偏向问题。
这种策略也决定了cassandra
集群只能保证数据的最终一致性,因为从一个节点到其它节点的数据拷贝是需要时间的,若节点在备份还未完成时挂掉,则可能导致数据不是最新,只有经过一定时间,备份全都完成,才会保证数据的最终一致。根据CAP
(分别代表一致性、可用性、分区容错性)定理,任何共享数据中心只能保证一致性、可用性、分区容错性中的两个,虽然cassandra
牺牲了强一致性,但很好的保证了可用性和分区容错性,在专注于可用和容错,不要求实时一致性的场景中,cassandra
是极好的选择。
Gossip协议
提到cassandra
,不得不提一下gossip
协议,cassandra
天生就是分布式的,其拥有去中心化的特点,即集群中的任何节点都是平等的,没有中心节点,各节点没有主次之分,像Mongodb
等分布式数据库大多拥有中心节点的概念,即数据读写请求都是通过中心节点进行协调的,若所有中心节点崩溃,则整个集群也将瘫痪,但cassandra
集群中的各个节点都可以独立进行读写操作的协调,也即要访问集群,连接至任一节点即可,虽然cassandra
存在种子节点,但种子节点只是为了集群能自发发现其它节点,没有任何特殊地位。之所以能有这个特点,正是因为cassandra
集群采用了Gossip
协议。cassandra
的节点发现、信息传送都是基于Gossip
协议的。
Gossip
协议又称八卦协议,集群中的任何节点都是平等的,都可以向其它节点随意发送消息,就像八卦聊天一样,我可以和任何人发起聊天,共享消息,这样一传十,十传百,对于某一消息,集群中的所有节点最终都将会收到。对于某一节点,其发送消息时,会随机选择一台活着的节点和不可达的节点发送同步请求,若发送到的节点不是种子节点,还会随机向一台种子节点发送请求,每个消息中都有一个版本号,其它节点收到消息后,会拿消息的版本号与自身版本号做对比,以确定哪些内容是需要我更新的,或者哪些数据是已经过时,需要你更新的,然后收到消息的节点又会以同样的方式将消息传递给其它节点或者返回更新消息给发送者,这样最终一条消息会传遍集群中所有节点,实现节点状态的最终一致。因活着的节点也会向已不可达的节点发送消息,因此若死亡节点复活或新增节点,则节点有机会收到消息,加入集群聊天队伍,这也就实现了集群中节点的自发管理与发现。