2016-07-29 38 views
0

我在寫一個Java客戶端,它測試一百萬行數據的讀取。我正在過濾來自列映射中鍵的數據。代碼正在創建並正確插入數據,但無法讀取數據。我的代碼是:Apache Cassandra讀取數據給出ReadFailureException

public class MillionMapTest { 
    private Cluster cluster; 
    private Session session; 

    public void connect(String node) { 
     cluster = Cluster.builder().addContactPoint(node).build(); 
     session = cluster.connect(); 
    } 

    public void createSchema() { 
     session.execute("CREATE KEYSPACE xx WITH replication " + 
       "= {'class':'SimpleStrategy', 'replication_factor':3};"); 
     session.execute(
       "CREATE TABLE xx.events (" + 
         "log_time_local timeuuid," + 
         "username text," + 
         "log_type text," + 
         "log_time timestamp," + 
         "device_category text," + 
         "log text," + 
         "priority INT," + 
         "client_ip text," + 
         "backend_app text," + 
         "location_details map<text, text>," + 
         "device_details map<text, text>," + 
         "extra_info Blob," + 
         "PRIMARY KEY (log_time_local, username, log_type)" + 
       ");"); 
     session.execute("CREATE INDEX devicekeys ON xx.events(KEYS(device_details));"); 
    } 

    public void loadData() { 
     PreparedStatement statement = session.prepare(
       "INSERT INTO xx.events VALUES (now(), ?, ?, toTimestamp(now()), ?, ?, ?, ?, ?, ?, ?, ?);"); 
     BoundStatement boundStatement = new BoundStatement(statement); 
     for (int i=0; i<1000000; i++) { 
      Map<String, String> tags = new HashMap<>(); 
      tags.put("os", "ios"); 
      tags.put("category", "tab"); 
      tags.put("dev_num", "12ABF847CA"); 
      if (i % 100 == 0) tags.put("category", "mobile"); 
      session.execute(boundStatement.bind("name_"+i,"type_"+i, "cat_"+i, "log_"+i, i, "ip_"+i, "app_"+i, null, tags, null)); 
     } 
    } 

    public void querySchema() { 
     ResultSet results = session.execute("SELECT * FROM xx.events WHERE device_details['category'] = 'mobile' ALLOW FILTERING;");  
    } 

    public static void main(String[] args) { 
     MillionMapTest client = new MillionMapTest(); 
     client.connect("localhost"); 
     client.createSchema(); 
     client.loadData(); 
     client.querySchema(); 
     session.close(); 
     cluster.close(); 
    } 
} 

錯誤是com.datastax.driver.core.exceptions.ReadFailureException: Cassandra failure during read query at consistency LOCAL_ONE (1 responses were required but only 0 replica responded, 1 failed)

在運行cqlsh時,查詢運行正常,此代碼使用少量數據。但它並沒有與百萬人一起工作。什麼導致這個錯誤,我該如何解決它?

+0

你能從cqlsh運行這個查詢嗎? – Rocherlee

+0

@Rocherlee是的,它可以從Cassandra服務器上的cqlsh工作。 – khateeb

回答

0

您的問題似乎是「二級索引」。它們並不是C *中最高性能的東西,並帶有自己的警告。關於C *中的二級索引問題,有一些很好的文檔這link。您已經獲得了二級索引,並且也具有地圖數據類型。這會很慢。事實上,你得到ReadFailureException而不是ReadTimeout可能與索引不是最新的當你查詢它(我不太確定它,但指這個issue哪種情況下可以拋出ReadFailureException)。

我認爲你應該看看重構你的模式或反規範化你的表,並可能有辦法做關鍵查找,而不是依靠二級索引。

+0

我試着在cqlsh上運行這個查詢,它工作。我用小數據試了一下,結果很奏效。 第二個鏈接中的問題在版本3.1中得到解決。我正在使用3.7版本 – khateeb