cassandra的HintedHandOff的功能主要是当节点掉线,或者各个副本节点中网络闪断的时候,此时数据的保存,等节点间恢复正常以后,副本数据就可以一致了。
1、Hints表的表结构
当副本节点传输数据失败以后,数据就会被保存在hints系统表中。
hints系统表的表结构为,compositeCF,rowkey为target_id,即节点的token值的uuid;
compositeName分别为hint_id 由产生hint数据的时间生成的uuid;和message_version为产生hint数据的时候数据的版本号;
普通字段有:mutation主要存在需要传输的数据RowMutation。
这里每一条hint数据就相当于一个Column
* The hint schema looks like this: * * CREATE TABLE hints ( * target_id uuid, * hint_id timeuuid, * message_version int, * mutation blob, * PRIMARY KEY (target_id, hint_id, message_version) * ) WITH COMPACT STORAGE; |
当数据传输失败以后,就会直接调用RowMutation中的hintFor方法,将数据转化为需要插入hints表中的数据格式。
/**
* Returns mutation representing a Hints to be sent to <code>address</code>
* as soon as it becomes available. See HintedHandoffManager for more details.
*/
public static RowMutation hintFor(RowMutation mutation, UUID targetId) throws IOException
{
RowMutation rm = new RowMutation(Table.SYSTEM_KS, UUIDType.instance.decompose(targetId));
UUID hintId = UUIDGen.getTimeUUID();
// determine the TTL for the RowMutation
// this is set at the smallest GCGraceSeconds for any of the CFs in the RM
// this ensures that deletes aren't "undone" by delivery of an old hint
int ttl = Integer.MAX_VALUE;
for (ColumnFamily cf : mutation.getColumnFamilies())
ttl = Math.min(ttl, cf.metadata().getGcGraceSeconds());
// serialize the hint with id and version as a composite column name
QueryPath path = new QueryPath(SystemTable.HINTS_CF, null, HintedHandOffManager.comparator.decompose(hintId, MessagingService.current_version));
rm.add(path, ByteBuffer.wrap(FBUtilities.serialize(mutation, serializer, MessagingService.current_version)), System.currentTimeMillis(), ttl);
return rm;
}
2、Hint数据的产生
cassandra这种nosql型数据库,为了保证数据的安全性,需要将一份数据存储在几个副本中,防止一个节点掉线或者节点数据有损坏的时候,数据还可以通过其他的节点访问和恢复,这样又不会影响当前的业务,最后也可以恢复数据。
副本间数据进行传输的时候,当发送失败,以后判断是否记录hint数据的条件有两个: