Cassandra通过线程池检索数据

时间:2016-04-10 17:28:26

标签: java multithreading cassandra prepared-statement datastax-java-driver

我对Cassandra比较新,我正在尝试使用通过Executor Pool执行的预处理语句来检索数据。看起来我收到的数据不一致。

我有这个user_connections表,其中user_id是行键,friends_id列表是set列。 我有另一个表,friends_info表,其中friend_id是行键,所有其他信息作为列。

当我尝试检索用户AA的好友列表时,我正在检索好友列表BBB,CCC,DDD。这完全没问题。

当我尝试使用预准备语句通过执行程序池检索BBB,CCC,DDD时。数据不一致。有时候所有三个记录都是BBB,有时候三个记录都是,有时两个记录是BBB,一个是CCC等......

我提供了我正在使用的方法和相关课程,请你帮我解决一下。我知道准备好的语句是线程安全的,并且预计会按预期工作。

public Set<User> listUserConnections(String userId) {
    Session session = client.getSession();

    Set<String> listUserConnectionIds = listUserConnections(userId, session);

    if (listUserConnectionIds.size() == 0)
        return new HashSet<User>();



    Set<User> listConnectionUserDetails = retrieveUserConnectionProfileInfo(
            listUserConnectionIds, session);
    return listConnectionUserDetails;

}



private Set<User> retrieveUserConnectionProfileInfo(Set<String> listUserConnectionIds,
        Session session) {


    Set<Callable<User>> callables = new HashSet<Callable<User>>();


     for(String key:listUserConnectionIds){



        logger.info("about to add callable" + key);

        Callable<User> callable = new QueryTask(key);

        callables.add(callable);

    }
    // invoke in parallel
    List<Future<User>> futures;
    Set<User> users = new HashSet<User>();

    // TODO Revisit this
    ExecutorService executorPool = Executors.newFixedThreadPool(100);

    try {
        futures = executorPool.invokeAll(callables);
        for (Future<User> f : futures) {

            User user = f.get();
            users.add(user);

            logger.info("User from future"+user.getUserId());

        }
    } catch (ExecutionException e) {
        logger.error("Error in retrieving the stores in parallel ", e);
    } catch (InterruptedException e) {
        logger.error("Error in retrieving the stores in parallel as it was interrupted ", e);
    } finally {
        executorPool.shutdown();
    }

    return users;
}

//执行者池类

class QueryTask implements Callable<User> {

    private String userName;

    // final PreparedStatement statement =
    // client.getSession().prepare(QueryConstants.GET_ALL_STORE_BRANDS);

    QueryTask(String name) {
        this.userName = name;

    }

    @Override
    public User call() throws Exception {
        // -------------I am seeing the userName is correct------------- for example BBB
        logger.info("inside call processing queries for " + userName);

        //------------This is a prepared statement, userPreparedStatement.getbStUserInfo()
        BoundStatement bStUserInfo = userPreparedStatement.getbStUserInfo();
        bStUserInfo.bind(userName);
        Session session = client.getSession();
        ResultSet rs = session.execute(bStUserInfo);

        User user = new User();

        Iterator<Row> rowIterator = rs.iterator();
        while (rowIterator.hasNext())
        {
        Row row = rowIterator.next();

        //-------This user id is not right 
        logger.info("Inside the callable after retrieval"+row.getString(TableConstants.Users.COLUMN_NAME_USER_ID));
        user.setUserId(row.getString(TableConstants.Users.COLUMN_NAME_USER_ID));



        return user;
        }

        logger.info("outside the while loop");
        return user;

    }

}

1 个答案:

答案 0 :(得分:0)

非常感谢@Ralf和Alex Popescu回复我这件事。 Datastax的文档深入探讨了Aync调用的工作原理。

@ Alex Popescu。谢谢我尝试了他们的异步调用,它对我来说很好。