2016-07-29 36 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