我们在之前的文章(谈谈Cassandra的客户端)中讲解了如何在Client端查询Cassandra中的数据。
为什么要使用RingCache
Cassandra的内部读写流程大概是这样的:
1 Client端先随机找到Cassandra集群中的一台机器,然后将查询请求发送给这台Cassandra机器。
2 接收到查询请求的Cassandra机器会判断需要查询的数据是否在本机中:如果在本机中,直接查询;如果不在本机中,将请求转发给另外一台机器来查询,并等待另外一台机器的查询结果。
3 查询请求的Cassandra机器将最终的结果返回给Client端。
我们可以看到,在上面的这个查询流程中,如果Client端将需要查询的数据发送给了一台不相关的Cassandra机器,那么这个不相关的Cassandra机器就充当了一个代理。
最坏的情况是所有的请求都发送到某一台Cassandra机器,这样就导致这台Cassandra机器就成为了瓶颈。
理想的状态是:Client端将查询的请求直接发送到存储有需要查询数据的Cassandra机器中,这样就省掉了其中一层不必要的代理。
那么我们如果达到这种理想的状态呢?可以考虑使用Cassandra(我使用的版本是0.6.2)中自带的RingCache。
如何使用RingCache
使用RingCache非常简单,我们只需要编写如下代码即可获得负责某一个数据的实际机器:
ringCache = new RingCache();
List<InetAddress> endPoints = ringCache.getEndPoint(keyspaceName, key);
在这里,我们只用2行代码就得到了某一个KeySpace下面的key(如果对Cassandra模型感兴趣,可以参考:大话Cassandra数据模型)对于的所有机器地址。这样我们就能直接对这些机器进行读写操作了。
但是这里需要注意一点,上面的代码依赖与Cassandra的配置文件,所以需要在环境变量中指定才能正常工作。
RingCache的工作原理
为什么RingCache能找到我们需要的节点?
我们在执行RingCache rc = new RingCache();的时候,内部会读取配置文件中的seed信息,然后找到一个有效的seed节点,请求token map信息,并将所有的token map信息缓存在本机。
我们在执行List<InetAddress> endPoints = ringCache.getEndPoint(keyspaceName, key);的时候,RingCache会根据之前找到的token map获取相应的AbstractReplicationStrategy,这个AbstractReplicationStrategy能够根据我们指定的keyspaceName, key再定位到我们需要的节点信息。
这也就解释了RingCache的工作原理。
使用RingCache需要注意的地方
既然使用RingCache能让我们快速地找到对应的Cassandra节点,那是不是以后我们所有的查询都可以使用RingCache了呢?
当然不是,RingCache毕竟只是一个缓存,而Cassandra集群内部的信息是时刻变动的,可能有机器离开,也可能有新的机器加入之类的。但是RingCache一旦使用以后,里面的信息就是不变的啦。
所以我们在实际的使用中需要注意这一点,并进行相应的处理才能更好的发挥出RingCache的作用。