第八章:Cassandra客戶端--Cassandra:The Definitive Guide 2nd Edition

我們習慣使用驅動程序連接到關係數據庫。例如,在Java中,JDBC是一種API,它抽象關係數據庫的供應商實現,以呈現使用語句,PreparedStatements,ResultSet等存儲和檢索數據的一致方法。要與數據庫進行交互,您將獲得一個與您正在使用的特定數據庫一起使用的驅動程序,例如Oracle,SQL Server或MySQL;這種交互的實現細節對開發人員是隱藏的。通常爲各種編程語言提供驅動程序以連接到各種各樣的數據庫。

Cassandra還有許多客戶端驅動程序,包括對大多數流行語言的支持。這些客戶端的好處在於,您可以輕鬆地將它們嵌入到您自己的應用程序中(我們將看到如何操作),並且它們經常提供比CQL本機接口更多的功能,包括連接池和JMX集成和監視。在以下部分中,我們將瞭解可用的各種客戶端及其提供的功能。

Hector,Astyanax和其他傳統客戶端

在Cassandra的早期,社區爲不同語言製作了許多客戶端驅動程序。這些貢獻是Cassandra採用的關鍵推動因素。一些最着名的早期車手包括Hector和Astyanax。

赫克托爾以希臘神話中的特洛伊戰士卡桑德拉的兄弟命名,是卡桑德拉最早的客戶之一。 Hector提供了一個簡單的Java接口,幫助許多早期開發人員避免了寫入Thrift API的挑戰,併成爲其他幾個驅動程序的靈感來源。該項目不再處於活動狀態,但您可以通過https://github.com/hector-client/hector訪問該項目。

Astyanax是一個Java客戶端,最初由Netflix在Thrift API之上構建,作爲Hector驅動程序的合理繼承者(Astyanax是Hector的兒子)。一旦引入了DataStax Java驅動程序,除了原始的Thrift實現之外,Netflix還使用Astyanax來支持Java驅動程序。這有助於許多用戶從Thrift過渡到CQL。然而,隨着Java驅動程序的突出,Astyanax上的活動大大減緩,該項目於2016年2月退役。您仍然可以通過https://github.com/Netflix/astyanax訪問該項目。

其他客戶包括用於Python的Pycassa,用於Perl的Perlcassa,用於Node.js的Helenus,以及用於Microsoft .NET框架和C#的Cassandra-Sharp。大多數這些客戶端不再主動維護,因爲它們基於現已棄用的Thrift接口。您可以在http://www.planetcassandra.org/client-drivers-tools找到當前和舊版驅動程序的完整列表。

DataStax Java驅動程序

CQL的引入推動了Cassandra客戶驅動程序的重大轉變。 CQL的簡單和熟悉的語法使得客戶端程序的開發類似於傳統的關係數據庫驅動程序。 DataStax對Java和其他幾種語言的開源驅動程序進行了戰略投資,以繼續推動Cassandra的採用。這些驅動因素很快成爲新開發項目的事實標準。您可以訪問https://github.com/datastax以訪問驅動程序以及其他連接器和工具。

有關DataStax驅動程序的更多信息

訪問驅動程序矩陣頁面以訪問文檔並確定與您的服務器版本兼容的驅動程序版本。

DataStax Java驅動程序是這些驅動程序中最古老,最成熟的驅動程序。出於這個原因,我們將專注於使用Java驅動程序,並以此爲契機,瞭解DataStax驅動程序跨多種語言提供的功能。

開發環境配置

首先,我們需要在開發環境中訪問驅動程序。我們可以直接從之前列出的URL下載驅動程序並手動管理依賴項,但在現代Java開發中使用Maven等工具來管理依賴項更爲常見。如果您正在使用Maven,則需要在項目pom.xml文件中添加以下內容:


 <dependency>
   <groupId>com.datastax.cassandra</groupId>
   <artifactId>cassandra-driver-core</artifactId>
   <version>3.0.0</version>
 </dependency>

您可以在http://docs.datastax.com/en/drivers/java/3.0/index.html找到Java驅動程序的Javadoc。 或者,Javadoc也是源代碼分發的一部分。

所有DataStax驅動程序都作爲GitHub上的開源項目進行管理。 如果您對查看Java驅動程序源感興趣,可以使用以下命令獲取只讀中繼版本:

 $ git clone https://github.com/datastax/java-driver.git


集羣和聯絡點

一旦我們配置了環境,我們就可以開始編碼了。 我們將根據我們在第5章中創建的酒店數據模型創建一個客戶端應用程序。本章和本書其餘部分中使用的所有源代碼都可以在https://github.com/jeffreyscarpenter/cassandra-上找到。 指南。

要開始構建我們的應用程序,我們將使用驅動程序的API連接到我們的集羣。 在Java驅動程序中,它由com.datastax.driver.core.Cluster和Session類表示。

Cluster類是驅動程序的主要入口點。 它使用構建器模式支持流暢的API。 例如,以下行創建與本地主機上運行的節點的連接:


Cluster cluster = Cluster.builder().
  addContactPoint("127.0.0.1").build();

這一個語句表示創建集羣所需的最少信息:單個聯繫點。我們還可以指定多個聯繫點。接觸點類似於Cassandra節點用於連接到同一羣集中的其他節點的概念種子節點。

創建自定義羣集初始化程序

Cluster.Builder類實現了一個名爲Cluster.Initializer的接口。這允許我們使用靜態方法Cluster.buildFrom(Initializer initializer)插入一個不同的機制來初始化Cluster。例如,如果我們想要從配置文件加載連接信息,這可能很有用。

我們可以在羣集上配置其他幾個選項,例如度量標準,默認查詢選項以及重新連接,重試和推測執行的策略。在我們看一些其他與連接相關的選項後,我們將在後面的章節中研究這些選項中的每一個:協議版本,壓縮和身份驗證。

協議版本

該驅動程序支持多個版本的CQL本機協議。 Cassandra 3.0支持第4版,正如我們在第2章中對Cassandra發佈歷史的概述中所學到的。

默認情況下,驅動程序使用其連接的第一個節點支持的協議版本。雖然在大多數情況下這已足夠,但如果您正在使用基於舊版Cassandra的羣集,則可能需要覆蓋此行爲。您可以通過將com.datastax.driver.core.ProtocolVersion枚舉中的所需值傳遞給Cluster.Builder。withProtocolVersion()操作來選擇協議版本。

壓縮

該驅動程序提供了在客戶端和Cassandra節點之間壓縮消息的選項,利用CQL本機協議支持的壓縮選項。啓用壓縮可以減少驅動程序消耗的網絡帶寬,但代價是客戶端和服務器的CPU使用量會增加。

目前有兩種壓縮算法,LZ4和SNAPPY,由com.datastax.driver.core.ProtocolOptions.Compression枚舉定義。壓縮默認爲NONE,但可以通過調用Cluster.Builder .withCompression()操作來覆蓋。

身份驗證和加密

該驅動程序提供可插入的身份驗證機制,可用於支持簡單的用戶名/密碼登錄,或與其他身份驗證系統集成。默認情況下,不執行身份驗證。您可以通過將com.datastax。驅動程序.core.AuthProvider接口(如PlainTextAuthProvider)的實現傳遞給Cluster.Builder.withAuthProvider()操作來選擇身份驗證提供程序。

驅動程序還可以加密與服務器的通信以確保隱私。客戶端 - 服務器加密選項由其cassandra.yaml文件中的每個節點指定。驅動程序符合每個節點指定的加密設置。

我們將在第13章中更詳細地從客戶端和服務器角度檢查身份驗證,授權和加密。

會話和連接池

在我們創建Cluster實例之後,在我們通過調用init()方法初始化它之前,它沒有連接到任何Cassandra節點:


cluster.init();

調用此方法時,驅動程序將連接到其中一個已配置的聯繫點,以獲取有關羣集的元數據。 如果沒有可用的聯繫點,此操作將拋出NoHostAvailableException,如果驗證失敗,則拋出Authentication Exception。 我們將在第13章中更詳細地討論身份驗證。

一旦我們初始化了Cluster對象,我們就需要建立一個會話來制定我們的查詢。 我們可以通過調用Cluster.connect()操作之一來獲取com.datastax.driver.core.Session對象。 您可以選擇提供要連接的鍵空間的名稱,就像我們在此示例中連接到酒店鍵空間一樣:

Session session = cluster.connect("hotel");


還有一個沒有參數的connect()操作,它創建了一個可以與多個鍵空間一起使用的Session。如果選擇此選項,則必須使用適當的鍵空間名稱限定查詢中的每個表引用。請注意,並不嚴格要求顯式調用Cluster.init(),因爲當我們調用connect()時也會在後臺調用它。

每個會話管理與Cassandra集羣的連接,這些集羣用於使用Cassandra本機協議執行查詢和控制操作。會話包含每個主機的TCP連接池。

會話很貴

由於會話維護多個節點的連接池,因此它是一個相對重量級的對象。在大多數情況下,您需要創建一個會話並在整個應用程序中重複使用它,而不是不斷地構建和拆除Sessions。另一個可接受的選擇是,如果您的應用程序正在訪問多個鍵空間,則爲每個鍵空間創建一個Session。

由於CQL本機協議是異步的,因此每個連接允許多個同時請求;協議v2中最多爲128個併發請求,而v3和v4允許最多32,768個同時請求。由於同時發出的請求數量較多,因此每個節點的連接數量較少。實際上,默認值是每個節點一個連接。

該驅動程序支持根據每個連接的請求數量向上或向下擴展連接數的功能。這些連接池設置可通過PoolingOptions類進行配置,該類設置用於本地和遠程主機的最大和最小(或“核心”)連接數。如果核心值和最大值不同,則驅動程序會根據客戶端發出的請求數量向上或向下擴展每個節點的連接池大小。每個連接的最小和最大請求閾值的設置用於確定何時創建新連接,以及何時可以回收未充分利用的連接。還有一個緩衝期可以防止連續建立和拆除連接。

使用ClusterBuilder創建集羣時可以設置PoolingOptions。withPoolingOptions(),或者在使用Cluster創建集羣后進行操作.getConfiguration()。getPoolingOptions()。 以下是創建羣集的示例,該羣集將遠程節點的最大連接數限制爲一個:

PoolingOptions poolingOptions = new PoolingOptions().
  setMaxConnectionsPerHost(HostDistance.REMOTE, 1);

Cluster cluster = Cluster.builder(). 
  addContactPoint("127.0.0.1").
  withPoolingOptions(poolingOptions).build();


驅動程序提供連接心跳,用於確保通過介入網絡設備不會過早關閉連接。默認爲30秒,但可以使用PoolingOptions.setHeartbeat IntervalSeconds()操作覆蓋。但是,這僅適用於設置值後建立的連接,因此您很可能希望在創建羣集時對其進行配置。

聲明

到目前爲止,我們只配置了與集羣的連接,並且尚未執行任何讀取或寫入操作。要開始做一些真正的應用程序工作,我們將使用com.datastax.driver.core.Statement類及其各種子類創建和執行語句。 Statement是一個具有多個實現的抽象類,包括SimpleStatement,PreparedStatement,BoundStatement,BatchStatement和BuiltStatement。

創建和執行語句的最簡單方法是使用表示語句的字符串調用Session.execute()操作。這是一個聲明的示例,它將返回酒店表的全部內容:

session.execute("SELECT * from hotel.hotels");


此語句在單個方法調用中創建並執行查詢。實際上,這可能會成爲在大型數據庫中執行的非常昂貴的查詢,但它確實是一個非常簡單的查詢的有用示例。我們需要構建的大多數查詢都會更復雜,因爲我們將有指定的搜索條件或要插入的特定值。我們當然可以使用Java的各種字符串實用程序來手動構建查詢的語法,但這當然容易出錯。如果我們不小心清理來自最終用戶的字符串,它甚至可能會將我們的應用程序暴露給注入攻擊。

簡單陳述

值得慶幸的是,我們不需要對自己如此努力。 Java驅動程序提供SimpleStatement類以幫助構造參數化語句。事實證明,我們之前看到的execute()操作實際上是一種創建SimpleStatement的便捷方法。

讓我們嘗試通過詢問Session對象來創建SimpleStatement來構建查詢。這是一個語句的示例,它將在我們的hotels表中插入一行,然後我們可以執行:


SimpleStatement hotelInsert = session.newSimpleStatement(
  "INSERT INTO hotels (hotel_id, name, phone) VALUES (?, ?, ?)",
  "AZ123", "Super Hotel at WestWorld", "1-888-999-9999");
session.execute(hotelInsert);

調用的第一個參數是查詢的基本語法,指示我們感興趣的表和列。問號用於指示我們將在其他參數中提供的值。 我們使用簡單的字符串來保存酒店ID,姓名和電話號碼的值。

如果我們正確創建了語句,插入將成功執行(並且靜默)。 現在讓我們創建另一個語句來回讀剛剛插入的行:

SimpleStatement hotelSelect = session.newSimpleStatement(
  "SELECT * FROM hotels WHERE id=?", "AZ123");       
ResultSet hotelSelectResult = session.execute(hotelSelect);


同樣,我們使用參數化來爲我們的搜索提供ID。 這次,當我們執行查詢時,我們確保接收從execute()方法返回的ResultSet。 我們可以迭代ResultSet返回的行,如下所示:

for (Row row : hotelSelectResult) {
  System.out.format("hotel_id: %s, name: %s, phone: %s\n",
  row.getString("hotel_id"), row.getString("name"), row.getString("phone"));
}


此代碼使用ResultSet.iterator()選項在結果集中的行上獲取迭代器,並在每行上循環,打印出所需的列值。 請注意,我們使用特殊訪問器來獲取每列的值,具體取決於所需的類型 - 在本例中爲Row.getString()。 正如我們所料,這將打印出如下結果:


hotel_id: AZ123, name: Super Hotel at WestWorld, phone: 1-888-999-9999

使用自定義編解碼器

正如我們已經指出的那樣,我們需要知道在與ResultSet中的Rows交互時我們請求的列的類型。如果我們使用Row.getString()請求id列,我們將收到CodecNotFoundException,表明驅動程序不知道如何將CQL類型uuid映射到java.lang。字符串。

這裏發生的是驅動程序維護Java和CQL類型之間的默認映射列表,稱爲編解碼器,它用於在應用程序和Cassandra之間來回轉換。驅動程序通過擴展類com.datastax.driver.core.TypeCodec 並使用Cluster管理的CodecRegistry註冊它來提供添加其他映射的方法:

cluster.getConfiguration().getCodecRegistry().
  register(myCustomCodec)


自定義編解碼器機制非常靈活,如以下用例所示:

  • 映射到備用日期/時間格式(例如,Java 8之前用戶的Joda時間)
  • 將字符串數據映射到XML和JSON等格式
  • 將列表,集和映射映射到各種Java集合類型

您可以在示例com.cassandraguide.clients.SimpleStatementExample中找到用於處理SimpleStatements的代碼示例。
異步執行

Session.execute()操作是同步的,這意味着它會一直阻塞,直到獲得結果或發生錯誤,例如網絡超時。 該驅動程序還提供異步executeAsync()操作以支持與Cassandra的非阻塞交互。 這些非阻塞請求可以使並行發送多個查詢更加簡單,從而提高客戶端應用程序的性能。

讓我們從之前進行操作並修改它以使用異步操作:

ResultSetFuture result =  session.executeAsync(statement);


結果是ResultSetFuture類型,它是java.util.concurrent.Future接口的實現。 Future是一種Java泛型類型,用於捕獲異步操作的結果。可以檢查每個Future以查看操作是否已完成,然後根據綁定類型查詢操作結果。還有阻塞等待結果的wait()操作。如果調用者不再對操作結果感興趣,也可以取消Future。 Future類是實現異步編程模式的有用工具,但需要阻塞或輪詢才能等待操作完成。

爲了解決這個缺點,Java驅動程序利用了Google的Guava框架中的ListenableFuture接口。 ListenableFuture接口擴展了Future,並添加了一個addListener()操作,允許客戶端註冊Future完成時調用的回調方法。回調方法在由驅動程序管理的線程中調用,因此重要的是該方法快速完成以避免佔用驅動程序資源。 ResultSetFuture綁定到ResultSet類型。

額外的異步操作

除了Session.executeAsync()操作之外,驅動程序還支持其他幾個異步操作,包括Cluster.closeAsync(),Session.prepareAsync()和對象映射器上的幾個操作。

準備好的聲明

雖然SimpleStatements對於創建即席查詢非常有用,但大多數應用程序傾向於重複執行同一組查詢。 PreparedStatement旨在更有效地處理這些查詢。語句的結構一次性發送到節點進行準備,並返回該語句的句柄。要使用預準備語句,只需要發送句柄和參數。

在構建應用程序時,通常會創建PreparedStatements以讀取數據,這些數據對應於您在數據模型中派生的每種訪問模式,以及其他用於將數據寫入表以支持這些訪問模式的數據。

讓我們使用Session.prepare()操作創建一些PreparedStatements來表示與以前相同的酒店查詢:


PreparedStatement hotelInsertPrepared = session.prepare(
  "INSERT INTO hotels (hotel_id, name, phone) VALUES (?, ?, ?)"); 

PreparedStatement hotelSelectPrepared = session.prepare(
  "SELECT * FROM hotels WHERE hotel_id=?");

請注意,PreparedStatement使用我們之前用於SimpleStatement的相同參數化語法。然而,一個關鍵的區別是PreparedStatement不是Statement的子類型。這可以防止嘗試將未綁定的PreparedStatement傳遞給要執行的會話時出錯。

然而,在我們開始之前,讓我們退後一步,討論Session.prepare()操作幕後發生的事情。驅動程序將PreparedStatement的內容傳遞給Cassandra節點,並獲取該語句的唯一標識符。創建BoundStatement時會引用此唯一標識符。如果您很好奇,可以通過調用PreparedStatement.getPreparedID()來實際看到此引用。

您可以將PreparedStatement視爲用於創建查詢的模板。除了指定查詢的形式之外,我們還可以在PreparedStatement上設置其他屬性,這些屬性將用作其用於創建的語句的默認值,包括默認一致性級別,重試策略和跟蹤。

除了提高效率之外,PreparedStatements還通過將CQL的查詢邏輯與數據分離來提高安全性。這提供了針對注入攻擊的保護,其試圖將命令嵌入到數據字段中以便獲得未經授權的訪問。

約束聲明

現在我們的PreparedStatement可供我們用來創建查詢。爲了使用PreparedStatement,我們通過調用bind()操作將它與實際值綁定。例如,我們可以綁定我們之前創建的SELECT語句,如下所示:

BoundStatement hotelSelectBound = hotelSelectPrepared.bind("AZ123");


我們在這裏使用的bind()操作允許我們提供匹配PreparedStatement中每個變量的值。 可以提供前n個綁定值,在這種情況下,必須在執行語句之前單獨綁定其餘值。 還有一個版本的bind(),它不帶參數,在這種情況下,所有參數必須單獨綁定。 BoundStatement提供了幾個set()操作,可用於綁定不同類型的值。 例如,我們可以從上面獲取INSERT預處理語句,並使用setString()操作綁定名稱和電話值:

BoundStatement hotelInsertBound = hotelInsertPrepared.bind("AZ123");
hotelInsertBound.setString("name", "Super Hotel at WestWorld");
hotelInsertBound.setString("phone", "1-888-999-9999");


一旦我們綁定了所有值,我們就使用Session.execute()執行BoundStatement。如果我們未能綁定任何值,如果正在使用協議v4(Cassandra 3.0或更高版本),它們將在服務器端被忽略。舊協議版本的驅動程序行爲是,如果存在任何未綁定的值,則拋出IllegalStateException。

您可以在示例com.cassandraguide.clients.PreparedStatementExample中找到用於處理PreparedStatement和BoundStatement的代碼示例。

內置語句和查詢生成器

該驅動程序還提供了com.datastax.driver.core.querybuilder.QueryBuilder類,該類爲構建查詢提供了流暢的API。這適用於查詢結構存在差異的情況(例如可選參數),這會使PreparedStatements變得困難。與PreparedStatement類似,它還提供一些防止注入攻擊的保護。

我們使用一個帶有Cluster對象的簡單構造函數構造一個QueryBuilder:


QueryBuilder queryBuilder = new QueryBuilder(cluster);

QueryBuilder生成使用BuiltStatement類及其子類表示的查詢。 每個類的方法返回BuiltStatement的實例,這些實例表示在構建時添加到查詢的內容。 在構建查詢時,您可能會發現IDE非常有用,可幫助您識別允許的操作。

讓我們在使用QueryBuilder之前重現查詢,看看它是如何工作的。 首先,我們將構建一個CQL INSERT查詢:

BuiltStatement hotelInsertBuilt =
  queryBuilder.insertInto("hotels")
  .value("hotel_id", "AZ123")
  .value("name", "Super Hotel at WestWorld")
  .value("phone", "1-888-999-9999");


第一個操作調用QueryBuilder.insertInto()操作爲hotels表創建一個Insert語句。 如果需要,我們可以使用Insert.using()向我們的語句添加CQL USING子句,但我們選擇開始向查詢添加值。 在我們添加值時,Insert.value()操作繼續返回Insert語句。 生成的Insert可以像使用Session.execute()或executeAsync()的任何其他Statement一樣執行。

CQL SELECT命令的構造類似於:


BuiltStatement hotelSelectBuilt = queryBuilder.select()
  .all()
  .from("hotels")
  .where(eq("hotel_id", "AZ123"));

對於此查詢,我們調用QueryBuilder.select()來創建Select語句。 我們使用Select.all()操作來選擇所有列,儘管我們也可以使用column()操作來選擇特定的列。 我們通過Select.where()操作添加一個CQL WHERE子句,該操作接受Clause類的一個實例。 我們使用QueryBuilder提供的靜態操作創建Clauses。 在這種情況下,我們使用eq()操作來檢查與ID的相等性。

要訪問這些靜態操作,我們需要在Java源文件中添加其他import語句,例如:

import static com.datastax.driver.core.querybuilder.QueryBuilder.eq;


有關使用QueryBuilder和BuiltStatement的完整代碼示例,請參閱com.cassandraguide.clients.QueryBuilderExample類。

對象映射器

我們已經探索了幾種使用驅動程序創建和執行查詢語句的技術。 我們將看到一種最終技術,它提供了更多的抽象。 Java驅動程序提供了一個對象映射器,使您可以專注於開發域模型(或API上使用的數據類型)並與之交互。 對象映射器使用源代碼中的註釋,用於將Java類映射到表或用戶定義類型(UDT)。

對象映射API作爲與cassandra-driver-mapping.jar文件中驅動程序其餘部分的單獨庫提供,因此您需要包含此額外的Maven依賴項才能在項目中使用Mapper:

<dependency>
  <groupId>com.datastax.cassandra</groupId>
  <artifactId>cassandra-driver-mapping</artifactId>
  <version>3.0.0</version>
</dependency>


例如,讓我們創建並註釋與我們的酒店表對應的酒店域模型類:

import com.datastax.driver.mapping.annotations.Column;
import com.datastax.driver.mapping.annotations.PartitionKey;
import com.datastax.driver.mapping.annotations.Table;

@Table(keyspace = "hotel", name = "hotels")
public class Hotel {

    @PartitionKey
    private String id;

    @Column (name = "name")
    private String name;

    @Column (name = "phone")
    private String phone;

    @Column (name = "address")
    private String address;

    @Column (name = "pois")
    private Set<String> pointsOfInterest;

    // constructors, get/set methods, hashcode, equals
}


現在我們使用com.datastax.driver.mapping.MappingManager附加到Session併爲我們的帶註釋的域模型類創建一個Mapper:

MappingManager mappingManager = new MappingManager(session);
Mapper<Hotel> hotelMapper = MappingManager.mapper(Hotel.class);


我們假設酒店類有一個簡單的構造函數,只需要一個UUID,名稱和電話號碼,我們將使用它來創建一個我們可以使用對象映射器保存的簡單酒店:

Hotel hotel = new Hotel("AZ123", "Super Hotel at WestWorld”,
  "1-888-999-9999");
hotelMapper.save(hotel);


我們需要執行Mapper.save()操作來執行CQL INSERT或UPDATE,因爲這些操作與Cassandra完全相同。 Mapper代表我們構建並執行語句。

要檢索對象,我們使用Mapper.get()操作,傳入一個與分區鍵元素匹配的參數列表:


Hotel retrievedHotel = hotelMapper.get(hotelId);

刪除對象的語法類似:

hotelMapper.delete(hotelId);


與save()操作一樣,get()和delete()完全處理代表我們使用驅動程序執行語句的細節。還有saveAsync(),getAsync()和deleteAsync()操作,它們使用我們前面討論過的ListenableFuture接口支持異步執行。

如果您希望能夠在執行查詢之前配置查詢,Mapper上還會返回返回語句的操作:saveQuery(),getQuery()和deleteQuery()。

對象映射器是一個有用的工具,用於抽象與代碼交互的一些細節,特別是如果您有現有的域模型。如果您的域模型包含引用其他類的類,則可以使用@UDT註釋將引用的類註釋爲用戶定義的類型。對象映射器使用帶註釋的類型遞歸處理對象。

Achilles:高級對象映射器

DuyHai Doan爲Java開發了一種名爲Achilles的高級對象映射器。 Achilles支持更高級的功能,例如複雜的鍵映射,輕量級事務,用戶定義的函數等。您可以訪問https://github.com/doanduyhai/Achilles查看。

政策

Java驅動程序提供了幾個策略接口,可用於調整驅動程序的行爲。其中包括負載平衡,重試請求和管理羣集中節點的連接的策略。

負載均衡策略

正如我們在第6章中學到的,可以對集羣中的任何節點進行查詢,然後將其稱爲該查詢的協調節點。根據查詢的內容,協調器可以與其他節點通信以滿足查詢。如果客戶端要在同一節點上引導其所有查詢,則會在集羣上產生不平衡負載,尤其是在其他客戶端執行相同操作的情況下。

爲了解決這個問題,驅動程序提供了一個可插拔的機制來平衡多個節點之間的查詢負載。通過選擇com.datastax.driver.core.policies.LoadBalancing策略接口的實現來實現負載平衡。

每個LoadBalancingPolicy必須提供distance()操作,以根據HostDistance枚舉將羣集中的每個節點分類爲本地,遠程或忽略。驅動程序更喜歡與本地節點的交互,並且與遠程節點保持與本地節點的更多連接。另一個關鍵操作是newQueryPlan(),它按照應該查詢的順序返回節點列表。 LoadBalancingPolicy接口還包含用於在添加或刪除節點或向上或向下移動節點時通知策略的操作。這些操作有助於策略避免在查詢計劃中包含關閉或刪除的節點。

該驅動程序提供了兩種基本的負載平衡實現:RoundRobin Policy(默認值)和DCAwareRoundRobinPolicy。

RoundRobinPolicy以重複模式跨集羣中的節點分配請求以分散處理負載。 DCAwareRoundRobinPolicy類似,但將其查詢計劃集中在本地數據中心的節點上。此策略可以在遠程數據中心中添加可配置數量的節點來查詢計劃,但遠程節點將始終優先於本地節點。可以顯式標識本地數據中心,也可以允許驅動程序自動發現它。

第二種模式是令牌感知,其使用分區密鑰的令牌值以選擇作爲所需數據的副本的節點,從而最小化必須查詢的節點的數量。這是通過使用TokenAwarePolicy包裝所選策略來實現的。

LoadBalancingPolicy在構建時在羣集上設置。例如,以下語句將初始化羣集以具有令牌感知並優先選擇本地數據中心中的節點:

Cluster.builder().withLoadBalancingPolicy(
  new TokenAwarePolicy(new DCAwareRoundRobinPolicy.Builder().build());


重試政策

當Cassandra節點發生故障或無法訪問時,驅動程序會自動並透明地嘗試其他節點並安排重新連接到後臺中的死節點。由於網絡條件的臨時更改也會使節點顯示爲脫機,因此驅動程序還提供了一種機制來重試因網絡相關錯誤而失敗的查詢。這消除了在客戶端代碼中編寫重試邏輯的需要。

驅動程序根據com.datastax.driver.core.RetryPolicy接口提供的實現重試失敗的查詢。 onReadTimeout(),onWriteTimeout()和onUnavailable()操作定義了查詢失敗時應採取的行爲,分別包含與網絡相關的異常ReadTimeoutException,WriteTimeoutException或UnavailableException。

DataStax Java驅動程序異常

可以由Java驅動程序生成的各種異常和錯誤收集在com.datastax.driver.core.exceptions包中。

RetryPolicy操作返回RetryDecision,它指示是否應該重試查詢,如果是,則指示在什麼一致性級別。如果未重試異常,則可以重新拋出或忽略該異常,在這種情況下,查詢操作將返回空ResultSet。

Java驅動程序提供了幾個RetryPolicy實現:

  • DefaultRetryPolicy是一種保守的實現,僅在一組較窄的條件下重試查詢。
  • FallthroughRetryPolicy從不建議重試,始終建議重新拋出異常。
  • DowngradingConsistencyRetryPolicy是一種更積極的策略,它會降低所需的一致性級別,以嘗試使查詢成功。

關於DowngradingConsistencyRetryPolicy的一個詞

此策略附帶警告:如果您願意在某些情況下接受降級的一致性級別,您是否真的需要更高的一致性級別的一致性級別?

可以在構建時在集羣上設置RetryPolicy,如以下語句所示,該語句選擇DowngradingConsistencyRetryPolicy並使用LoggingRetryPolicy對其進行包裝,以便記錄每次重試嘗試:

Cluster.builder().withRetryPolicy(new LoggingRetryPolicy(
  DowngradingConsistencyRetryPolicy.INSTANCE));


除非通過Statement.setRetryPolicy()操作覆蓋任何單個查詢,否則羣集上的RetryPolicy將用於在該羣集上執行的所有查詢。

投機執行政策

雖然擁有一個自動響應網絡超時的重試機制非常棒,但我們通常無法等待超時甚至長時間的垃圾收集暫停。爲了加快速度,驅動程序提供了一種推測執行機制。如果查詢的原始協調器節點未能以預定間隔響應,則驅動程序搶先地針對不同的協調器節點開始另外執行查詢。當其中一個查詢返回時,驅動程序提供該響應並取消任何其他未完成的查詢。

通過指定com.datastax.driver.core.policies.SpeculativeExecutionPolicy的實現,在集羣上設置推測執行行爲。

默認值爲NoSpeculativeExecutionPolicy,它不會安排任何推測性執行。還有一個ConstantSpeculativeExecutionPolicy,它以最多毫秒的固定延遲計劃最多重試次數。 PercentileSpeculativeExecutionPolicy是一個較新的策略,從3.0驅動程序版本開始仍被視爲Beta。它會根據觀察到的原始協調節點的延遲,在延遲時觸發推測性執行。

使用Cluster.Builder設置策略,例如:


Cluster.builder().withSpeculativeExecutionPolicy(
  new ConstantSpeculativeExecutionPolicy (
    200, // delay in ms
    3    // max number of speculative executions
  );

以後不能更改此策略,也不能在單個語句上覆蓋此策略。

地址翻譯

在我們到目前爲止看到的示例中,每個節點都由在其cassandra.yaml文件中配置爲節點的rpc_address的IP地址標識。在某些部署中,客戶端可能無法訪問該地址。爲了處理這種情況,驅動程序提供了一個可插入的功能,可以通過com.datastax.driver.core.policy.AddressTranslator接口轉換地址(在3.0之前的驅動程序版本中,“translator”在整個過程中拼錯爲“translater”) API)。

例如,Java驅動程序附帶IdentityTranslator,一個保留IP地址不變的默認轉換程序,以及EC2MultiRegionAddressTranslator,它對Amazon EC2環境很有用。在客戶端可能需要通過公共IP地址訪問另一個數據中心中的節點的情況下,此轉換器非常有用。我們將在第14章中更詳細地討論EC2部署。

元數據

要訪問集羣元數據,我們調用Cluster.getMetadata()方法。 com.datastax.driver.core.Metadata類提供有關羣集的信息,包括羣集名稱,包含鍵空間和表的模式以及羣集中的已知主機。我們可以通過以下代碼獲取集羣的名稱:


Metadata metadata = cluster.getMetadata();
System.out.printf("Connected to cluster: %s\n", 
  metadata.getClusterName(), cluster.getClusterName());

分配羣集名稱

有點令人困惑的是,Cluster.Builder類允許我們在構建Cluster實例時爲其分配名稱。此名稱實際上只是客戶端跟蹤多個Cluster對象的一種方式,可以與實際Cassandra集羣中的節點所知的名稱不同。第二個集羣名稱是我們通過Metadata類獲得的名稱。

如果我們在構造時沒有爲Cluster指定名稱,則會爲其分配一個默認名稱,例如“cluster1”,“cluster2”等等(如果創建了多個羣集)。如果從之前修改示例,將metadata.getClusterName()更改爲cluster.getClusterName(),則可以看到此值。
節點發現

Cluster對象維護與其中一個聯繫點的永久連接,它用於維護有關羣集狀態和拓撲的信息。使用此連接,驅動程序將發現當前羣集中的所有節點。驅動程序使用com.datastax.driver.core.Host類來表示每個節點。以下代碼顯示了迭代主機以打印其信息的示例:

for (Host host : cluster.getMetadata.getAllHosts())
{
  System.out.printf("Data Center: %s; Rack: %s; Host: %s\n",
  host.getDatacenter(), host.getRack(), host.getAddress());
}


您可以在com.cassandraguide.clients.Simple類連接示例中找到此代碼。

如果我們使用Cassandra Cluster Manager(ccm)運行多節點集羣(例如我們在第7章中創建的集羣),則此程序的輸出將如下所示:

Connected to cluster: my_cluster
Data Center: datacenter1; Rack: rack1; Host: /127.0.0.1
Data Center: datacenter1; Rack: rack1; Host: /127.0.0.2
Data Center: datacenter1; Rack: rack1; Host: /127.0.0.3


使用該連接,驅動程序還可以發現當前羣集中的所有節點。 驅動程序還可以檢測何時將新節點添加到羣集。 您可以通過實現Host.StateListener接口來註冊偵聽器。 這需要我們實現幾個操作,例如onAdd()和onRemove(),它們在從集羣添加或刪除節點時調用,以及onUp()和onDown(),它們指示節點何時上升或下降。 讓我們看一下在集羣中註冊監聽器的示例類的一部分:

public class ConnectionListenerExample implements Host.StateListener {
          
  public String getHostString(Host host) {
    return new StringBuilder("Data Center: " + host.getDatacenter() +
      " Rack: " + host.getRack() +
      " Host: " + host.getAddress().toString() +
      " Version: " + host.getCassandraVersion() +
      " State: " + host.getState());
  }

  public void onUp(Host host) {
    System.out.printf("Node is up: %s\n", getHostString(host));
  }  

  public void onDown(Host host) {
    System.out.printf("Node is down: %s\n", getHostString(host));
  }

  // other required methods omitted...
  public static void main(String[] args) {

    List<Host.StateListener> list =
      ArrayList<Host.StateListener>();
    list.add(new ConnectionListenerExample());  

    Cluster cluster = Cluster.builder().
      addContactPoint("127.0.0.1").
      withInitialListeners(list).
      build();

    cluster.init();
  }
}


此代碼只是在節點上升或下降時打印出狀態消息。 您將注意到,我們使用了比前一個示例更多的有關每個節點的信息,包括每個節點使用的Cassandra版本。 您可以在com.cassandraguide.clients.ConnectionListenerExample類中找到完整的代碼清單。

我們來運行這個示例程序。 因爲在調用init()之前添加了我們的監聽器,所以我們立即得到以下輸出:

Node added: Data Center: datacenter1 Rack: rack1 
  Host: /127.0.0.1 Version: 3.0.0 State: UP
Node added: Data Center: datacenter1 Rack: rack1 
  Host: /127.0.0.2 Version: 3.0.0 State: UP
Node added: Data Center: datacenter1 Rack: rack1 
  Host: /127.0.0.3 Version: 3.0.0 State: UP


現在讓我們使用ccm stop命令關閉我們的一個節點,我們將看到如下內容:

Node is down: Data Center: datacenter1 Rack: rack1 
  Host: /127.0.0.1 Version: 3.0.0 State: DOWN


同樣,如果我們重新啓動節點,我們會看到節點重新聯機的通知:

Node is up: Data Center: datacenter1 Rack: rack1 
  Host: /127.0.0.1 Version: 3.0.0 State: UP


架構訪問

Metadata類還允許客戶端了解羣集中的架構。 exportSchemaAsString()操作創建一個String,描述集羣中定義的所有鍵空間和表,包括系統鍵空間。 此輸出等同於cqlsh命令DESCRIBE FULL SCHEMA。 其他操作支持瀏覽各個鍵空間和表的內容。

我們之前已經在第2章討論了Cassandra對最終一致性的支持。因爲模式信息本身是使用Cassandra存儲的,所以它最終也是一致的,因此不同節點可能有不同版本的模式。 從3.0版本開始,Java驅動程序不會直接公開架構版本,但您可以通過運行nodetool describecluster命令來查看示例:

$ ccm node1 nodetool describecluster

Cluster Information:
     Name: test_cluster
     Snitch: org.apache.cassandra.locator.DynamicEndpointSnitch
     Partitioner: org.apache.cassandra.dht.Murmur3Partitioner
     Schema versions:
         ea46580a-4ab4-3e70-b68f-5e57da189ac5:
           [127.0.0.1, 127.0.0.2, 127.0.0.3]


這個輸出向我們展示了一些東西。首先,我們看到模式版本是UUID值。該值是基於節點知道的所有鍵空間和表定義的散列計算的。所有三個節點共享相同的模式版本的事實意味着它們都具有定義的相同模式。

當然,在創建,更改和刪除鍵空間和表時,使用的模式版本可能會隨着時間的推移而發生變化。驅動程序爲客戶端提供通知機制,通過向羣集註冊com.datastax.driver.core.SchemaChangeListener來了解這些更改。

您可以通過運行示例com.cassandraguide.clients.SimpleSchemaExample來查找這些調用的示例。

除了我們剛剛在Metadata類中檢查的模式訪問之外,Java驅動程序還提供了一個用於管理com.datastax.driver.core.schemabuilder包中的模式的工具。 SchemaBuilder提供了一種流暢的API,用於創建SchemaStatements,表示對鍵空間,表,索引和用戶定義類型(UDT)的CREATE,ALTER和DROP操作等操作。

例如,以下代碼可用於創建酒店密鑰空間:


 SchemaStatement hotelSchemaStatement = SchemaBuilder.createTable("hotels").
   addPartitionKey("id", DataType.text()).
   addColumn("name", DataType.text()).
   addColumn("phone", DataType.text()).
   addColumn("address", DataType.text()).
   addColumn("pois", DataType.set(DataType.text()));
 
session.execute(hotelSchemaStatement);

我們還導入com.datastax.driver.core.DataType,以便我們可以利用其靜態操作來定義每列的數據類型。

使用程序化架構定義時避免衝突

許多開發人員已經注意到,這種編程模式管理功能可以用作簡化應用程序部署的“延遲初始化”技術:如果我們的應用程序使用的模式不存在,我們可以簡單地以編程方式創建它。但是,在運行多個客戶端時,建議不要使用此技術,即使使用IF NOT EXISTS語義也是如此。來自多個併發客戶端的CREATE TABLE或ALTER TABLE語句可能導致節點之間的狀態不一致,需要手動修復。

調試和監控

該驅動程序提供了用於監視和調試客戶端使用Cassandra的功能,包括用於記錄和度量的工具。還有一個查詢跟蹤功能,我們將在第12章中學習。

記錄

正如我們將在第10章中學到的,Cassandra使用了一個名爲Simple Logging Facade for Java的日誌API(SLF4J)。 Java驅動程序也使用SLF4J API。爲了在Java客戶端應用程序上啓用日誌記錄,您需要在類路徑上提供兼容的SLF4J實現。

下面是我們可以添加到Maven POM文件中的依賴示例,以選擇Logback項目作爲實現:

<dependency>
      <groupId>ch.qos.logback</groupId>
      <artifactId>logback-classic</artifactId>
      <version>1.1.3</version>
</dependency>


您可以在http://logback.qos.ch/上了解有關Logback的更多信息。

默認情況下,Java驅動程序設置爲使用DEBUG日誌記錄級別,這非常詳細。我們可以通過利用Logback的配置機制來配置日誌記錄,該機制支持測試和生產環境的單獨配置。 Logback首先檢查表示測試配置的文件logback-test.xml的類路徑,然後如果沒有找到測試配置,則會搜索文件logback.xml。

有關Logback配置的更多詳細信息,包括測試和生產環境的示例配置文件,請參閱配置頁面。

度量

有時,監視客戶端應用程序的行爲會有所幫助,以便檢測異常情況和調試錯誤。 Java驅動程序收集有關其活動的指標,並使用Dropwizard指標庫使這些指標可用。驅動程序報告連接,任務隊列,查詢和錯誤(如連接錯誤,讀取和寫入超時,重試和推測執行)的度量標準。

您可以通過Cluster.getMetrics()操作在本地訪問Java驅動程序指標。 Metrics庫還與Java Management Extensions(JMX)集成,以允許遠程監控指標。默認情況下啓用JMX報告,但可以在構建羣集時提供的配置中覆蓋此報告。

DataStax Python驅動程序

最受歡迎的早期Python客戶端是Pycassa,它是在Thrift界面上構建的。但是,不再維護Pycassa項目,建議使用DataStax Python驅動程序進行所有新開發。

DataStax Python驅動程序的第一個完整版本於2014年1月推出,提供了會話管理,節點發現,連接池,同步/異步查詢,負載平衡,查詢跟蹤,指標(使用Scales庫),日誌記錄,身份驗證和SSL。 2014年5月的2.0版本中添加了支持Cassandra 2.1及更高版本的分頁,輕量級事務和Python 3支持等功能.Python Driver與Cassandra 1.2及更高版本兼容,並在Python 2.6,2.7,3.3和3.4。該驅動程序在Linux,Mac OS和Windows上運行。

DataStax網站上提供了驅動程序的官方文檔,而GitHub上提供了源驅動程序。 您可以通過運行Python安裝程序pip來安裝驅動程序:

pip install cassandra-driver

安裝Python和PIP

要使用示例代碼,您需要爲您的平臺提供兼容的Python版本(如前所述)和pip。 您可以通過下載腳本https://bootstrap.pypa.io/get-pip.py並運行命令python get-pip.py來安裝pip。 您可能需要在Unix系統上通過sudo運行此命令。

這是一個連接到集羣並在hotels表中插入行的簡單示例:

from cassandra.cluster import Cluster
cluster = Cluster(['127.0.0.1'])
session = cluster.connect('hotel')
session.execute("""
  insert into hotels (id, name, phone)
  values (%s, %s, %s)
  """
  ('AZ123', 'Super Hotel at WestWorld', '1-888-999-9999')
)


Python驅動程序包含一個名爲cqlengine的對象映射器,可通過cassandra.cqlengine.models.Model類訪問。 Python驅動程序還利用第三方庫來提高性能,壓縮和指標。使用Cython的一些C擴展用於加速性能。驅動程序也可以在PyPy上運行,PyPy是一個使用JIT編譯器的備用Python運行時。降低的CPU消耗導致吞吐量提高,比普通Python高出兩倍。壓縮需要安裝lz4或python-snappy庫,具體取決於所需的算法。

DataStax Node.js驅動程序

最初由Node.js提供的基於Thrift的客戶端綁定由Helenus提供,Jorge Bay提供的node-cassandra-cql包隨後提供了一個CQL本機客戶端。

DataStax Node.js驅動程序於2014年10月正式推出,基於node-cassandra-cql,添加了Apache Cassandra的其他DataStax驅動程序中常見的標準功能。您可以訪問https://github.com/datastax/nodejs-driver訪問該驅動程序。

Node.js驅動程序通過節點包管理器(NPM)安裝:


npm install cassandra-driver

安裝Node.js運行時和程序包管理器

如果您沒有使用Node的經驗,可以在https://nodejs.org上獲得包含Node.js和NPM的平臺安裝。 這些通常安裝在Unix系統上的/ usr / local / bin / node和/ usr / local / bin / npm中。

語法有點不同,因爲您在其他語言驅動程序中訪問Client對象而不是Cluster。 其他結構非常相似:

var cassandra = require('cassandra-driver');
var client = new cassandra.Client({ contactPoints: ['127.0.0.1'], 
  keyspace: 'hotel'});


構建和執行參數化查詢如下所示:

var query = 'SELECT * FROM hotels WHERE id=?';
client.execute(query, ['AZ123'], function(err, result) {
  assert.ifError(err);
  console.log('got hotel with name ' + result.rows[0].name);
});


DataStax Ruby驅動程序

Fauna是一個早期基於Thrift的Ruby客戶端,由Twitter爲Cassandra創建。 從2013年初開始,Theo Hultberg領導了cql-rb gem的開發,它成爲2014年11月發佈的DataStax Ruby Driver的基礎。您可以訪問https://github.com/datastax/ruby-driver上的Ruby驅動程序。

您可以使用Ruby Gems安裝驅動程序:


$ gem install cassandra-driver

這是一個創建集羣和會話並執行迭代我們的hotels表的內容的簡單異步查詢的示例:

require 'cassandra'
 
cluster = Cassandra.cluster(hosts: ['127.0.0.1'])
session  = cluster.connect('hotel') 
 
future = session.execute_async('SELECT * FROM hotels') 
future.on_success do |rows|
  rows.each do |row|
    puts "Hotel: #{row['id']} Name: #{row['name']}"
  end
end
future.join


Ruby驅動程序在標準Ruby上運行,但也可以在JRuby 1.7或更高版本上運行以提高性能。 該驅動程序在Linux,Mac OS上運行,但不支持Windows。

DataStax C#驅動程序

DataStax C#驅動程序於2013年7月首次發佈,爲使用.NET框架的Windows客戶端提供支持。 出於這個原因,它也經常被稱爲“.NET驅動程序”。

C#驅動程序可在NuGet上獲得,NuGet是Microsoft開發平臺的軟件包管理器。 在PowerShell中,在程序包管理器控制檯中運行以下命令:

PM> Install-Package CassandraCSharpDriver


要使用該驅動程序,請在Visual Studio中創建一個新項目,並添加一個引用Cassandra名稱空間的using指令。 以下示例連接到我們的酒店密鑰空間,並將新記錄插入到hotels表中:

Cluster Cluster = Cluster.Builder()
  .AddContactPoint("127.0.0.1")  .Build();

ISession Session = Cluster.Connect("hotel");
Session.Execute(
  "INSERT INTO hotels (id, name, phone) " +
  "VALUES (" +
    "'AZ123'," +
    "'Super Hotel at WestWorld'," +
    "'1-888-999-9999'," +
    ";");


C#驅動程序與語言集成查詢(LINQ)集成,後者是一種Microsoft .NET Framework組件,可爲.NET語言添加查詢功能;還有一個單獨的對象映射器。

示例應用程序:KillrVideo

Luke Tillman,Patrick McFadin和其他人創建了一個名爲KillrVideo的視頻共享應用程序。 KillrVideo是一個使用DataStax C#驅動程序構建的開源.NET應用程序,並部署到Microsoft的Azure雲中。它還利用了DataStax Enterprise功能,例如與Apache Spark和Apache SOLR的集成。您可以在GitHub上下載源代碼。

DataStax C / C ++驅動程序

DataStax C / C ++驅動程序於2014年2月發佈。您可以訪問https://github.com/datastax/cpp-driver上的驅動程序,以及http://datastax.github.io/cpp-driver上的文檔。

C / C ++驅動程序與其他驅動程序略有不同,因爲它的API側重於異步操作以排除同步操作。例如,創建會話是一個返回未來的異步操作:

#include <cassandra.h>
#include <stdio.h>

int main() {
  CassFuture* connect_future = NULL;
  CassCluster* cluster = cass_cluster_new();
  CassSession* session = cass_session_new();

  cass_cluster_set_contact_points(cluster, "127.0.0.1");

  connect_future = cass_session_connect(session, cluster);

  if (cass_future_error_code(connect_future) == CASS_OK) {
  /* proceed with processing... */



但是,如示例所示,通過立即阻止將來可以輕鬆支持同步語義。 構建和執行簡單查詢如下所示:

CassStatement* select_statement
  = cass_statement_new("SELECT * "
                           "FROM hotel.hotels", 0);

CassFuture* hotel_select_future =
  cass_session_execute(session, select_statement);

if(cass_future_error_code(result_future) == CASS_OK) {

  const CassResult* result = cass_future_get_result(result_future);
  CassIterator* rows = cass_iterator_from_result(result);

  while(cass_iterator_next(rows)) {
    const CassRow* row = cass_iterator_get_row(rows);
    const CassValue* value =
      cass_row_get_column_by_name(row, "name");
    const char* name;
    size_t name_length;
    cass_value_get_string(value, &name, &name_length);
    printf("Hotel_name: '%.*s'\n", (int)name_length, name);
  }
}


請記住,內存管理在C / C ++程序中非常重要; 爲簡潔起見,我們省略了對諸如集羣,會話,期貨和結果等對象進行釋放的語句。

C / C ++驅動程序使用libuv庫進行異步I / O操作,如果需要,還可以使用OpenSSL庫進行加密的客戶機 - 節點連接。 編譯和鏈接的說明因平臺而異,因此請參閱驅動程序文檔以獲取詳細信息。

DataStax PHP驅動程序

DataStax PHP驅動程序支持PHP服務器端腳本語言。 該驅動程序於2015年發佈,包含DataStax C / C ++驅動程序,並支持Unix和Windows環境。

驅動程序有多個安裝選項,但最簡單的方法是使用PECL存儲庫:


pecl install cassandra

以下簡短示例從hotels表中選擇行,並使用異步API打印出它們的值:


<?php

$keyspace  = 'hotel';
$session   = $cluster->connect($keyspace);
$statement = new Cassandra\SimpleStatement(
    'SELECT * FROM hotels'
);

$future    = $session->executeAsync($statement);
$result    = $future->get();
foreach ($result as $row) {
  printf("id: %s, name: %s, phone: %s\n",
    $row['id'], $row['name'], $row['phone']);
}

您可以訪問https://github.com/datastax/php-driver上的PHP驅動程序文檔,以及https://datastax.github.io/php-driver上的源代碼。

總結

您現在應該瞭解Cassandra可用的各種客戶端接口,它們提供的功能以及如何安裝和使用它們。 我們特別關注DataStax Java驅動程序,以獲得一些實踐經驗,即使您選擇使用其他DataStax驅動程序,也應該爲您提供良好的服務。 我們將在接下來的章節中繼續使用DataStax Java驅動程序,因爲我們會進行更多的閱讀和編寫。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章