作为一个 NoSQL 存储系统,它不支持多表连接,不支持外键约束,所以也不需要遵循数据库的经典范式。
虽然 CQL 看起来很象 SQL,其实还是有点差别的,它的 Insert/Update 其实都是 Set, 它也不支持行级锁,不支持事务(它也有一种轻量级的事务,但由于它的分布系统特点,与传统的事务大相迥异)。
它的客户端驱动是很丰富的, 下面我们以 Java 举一个实际应用实例:
创建 Keyspace 和 Tables
- 创建一个 key space: walter_apjc 采用网络拓扑策略,两个DC: HF1 和 SZ1
整理了一份面试笔记包括了:Java面试、Spring、JVM、MyBatis、Redis、MySQL、并发编程、微服务、Linux、Springboot、SpringCloud、MQ、Kafka 面试专题
需要全套面试笔记的【点击此处即可】即可免费获取
java
复制代码
CREATE KEYSPACE walter_apjc WITH replication = {'class': 'NetworkTopologyStrategy', 'HF1': '3', 'SZ1': '3'} AND durable_writes = true;
- 创建两张表 inventory 和 person
sql
复制代码
CREATE TABLE inventory ( user_id uuid, inventory_id uuid, inventory_name text, name text, tags text, create_time timestamp, last_modified_time timestamp, PRIMARY KEY(user_id,inventory_id)); CREATE TABLE person ( id text PRIMARY KEY, name text, age int);
- 创建一个索引
csharp
复制代码
create index on inventory(name);
使用 Cassandra 的 Java Driver 来存取数据
创建一个基础类CassandraClient 来连接 Cassandra Cluster, 这里对于 Cluster 有很多关键属性需要设置,在 Cassandra Java Driver 4.x 版本中包装成 CqlSession
java
复制代码
package com.github.walterfan.hellocassandra; import com.datastax.driver.core.Cluster; import com.datastax.driver.core.HostDistance; import com.datastax.driver.core.PoolingOptions; import com.datastax.driver.core.Session; import com.datastax.driver.core.policies.*; import lombok.Builder; import lombok.Data; import org.apache.commons.lang3.StringUtils; @Data @Builder public class CassandraClient { private String contactPoints; private int port; private String localDC; private String username; private String password; private int maxConnectionsPerHost ; private int usedHostsPerRemote ; private long reconnectBaseDelayMs ; private long reconnectMaxDelayMs ; private volatile Cluster cluster; public synchronized void init() { DCAwareRoundRobinPolicy loadBanalcePolicy = DCAwareRoundRobinPolicy.builder() .withLocalDc(localDC) .withUsedHostsPerRemoteDc(usedHostsPerRemote) .allowRemoteDCsForLocalConsistencyLevel() .build(); PoolingOptions poolingOptions =new PoolingOptions(); poolingOptions.setMaxConnectionsPerHost(HostDistance.LOCAL, maxConnectionsPerHost); poolingOptions.setMaxConnectionsPerHost(HostDistance.REMOTE, maxConnectionsPerHost); Cluster.Builder clusterBuilder = Cluster.builder() .withReconnectionPolicy(new ExponentialReconnectionPolicy(reconnectBaseDelayMs,reconnectMaxDelayMs)) .withRetryPolicy(new LoggingRetryPolicy(DefaultRetryPolicy.INSTANCE)) .withPoolingOptions(poolingOptions) .withLoadBalancingPolicy(new TokenAwarePolicy(loadBanalcePolicy)) .withPort(port) .addContactPoints(contactPoints.split(",")) .withoutJMXReporting(); if(StringUtils.isNotEmpty(username) && StringUtils.isNotEmpty(password) ) { clusterBuilder.withCredentials(username, password); } cluster = clusterBuilder.build(); } public Session connect(String keyspace) { if(null == cluster) { init(); } return this.cluster.connect(keyspace); } public void close() { cluster.close(); } }
利用 Spring 提供的 CassandraTemplate 可以很方便来存取数据
在读写数据时,有几个很重要的选项需要设置
- ConsistentLevel
- RetryPolicy
- FetchSize
- ReadTimeout
一致性水平是 Cassandra 所特有的,多数情况下我们会选择 LOCAL_QUORUM, 也就是在本地的 DC 要符合 Quorum 法定节点数有成功响应才可以。