bigchaindb源码分析(八)——stale

本节我们来分析stale进程,stale进程也是一个pipeline,其作用在于处理联盟中有被分配节点由于某些原因没有处理bakclog中的事务的问题,主要做法是对该事务的被分配节点进行重新分配

# bigchaindb/pipelines/stale.py
def create_pipeline(timeout=5, backlog_reassign_delay=5):
    stm = StaleTransactionMonitor(timeout=timeout,
                                  backlog_reassign_delay=backlog_reassign_delay)

    monitor_pipeline = Pipeline([
        Node(stm.check_transactions),
        Node(stm.reassign_transactions)
    ])

    return monitor_pipeline


def start(timeout=5, backlog_reassign_delay=None):
    pipeline = create_pipeline(timeout=timeout,
                               backlog_reassign_delay=backlog_reassign_delay)
    pipeline.start()
    return pipeline

stale进程的pipeline如上,该pipeline中只有两个Node:check_transactions->reassign_transactions

check_transactions

每一个pipeline的Node调用了一个无限循环着的target程序,对于本Node来说,意味着check_transactions每休眠self.timeout后将会被再次调用。而在每一次调用时,将会从backlog表中找到时间戳比当前时间减去分配时延还要小的记录,并将这些记录通过生成器抛出给下一个Node。这些记录的时间戳小于当前时间减去分配时延,意味着该记录本应该已经被分配,但是却并没有被分配节点所处理(因为还留在backlog表中),所以已经过时了,应当被重新分配节点来处理

# bigchaindb/pipelines/stale.py
def check_transactions(self):
    sleep(self.timeout)
    for tx in self.bigchain.get_stale_transactions():
        yield tx

# bigchaindb/backend/mongodb/query.py      
@register_query(MongoDBConnection)
def get_stale_transactions(conn, reassign_delay):
    return conn.run(
        conn.collection('backlog')
        .find({'assignment_timestamp': {'$lt': time() - reassign_delay}},
              projection={'_id': False}))

reassign_transactions

事务传输到本Node,代表着事务没有被之前的分配节点来处理,所以应该重新分配。重新分配的流程为:找到联盟中除之前分配节点外的其他节点,从中随机抽取一个节点作为新的被分配节点,更新backlog表中事务的assigneeassignment_timestamp

# bigchaindb/pipelines/stale.py
def reassign_transactions(self, tx):
    logger.info('Reassigning transaction with id %s', tx['id'])
    self.bigchain.reassign_transaction(tx)
    return tx

# bigchaindb/core.py   
def reassign_transaction(self, transaction):
    other_nodes = tuple(
        self.federation.difference([transaction['assignee']])
    )
    new_assignee = random.choice(other_nodes) if other_nodes else self.me

    return backend.query.update_transaction(
            self.connection, transaction['id'],
            {'assignee': new_assignee, 'assignment_timestamp': time()})

# bigchaindb/backend/mongodb/query.py 
@register_query(MongoDBConnection)
def update_transaction(conn, transaction_id, doc):
    # with mongodb we need to add update operators to the doc
    doc = {'$set': doc}
    return conn.run(
        conn.collection('backlog')
        .find_one_and_update(
            {'id': transaction_id},
            doc,
            return_document=ReturnDocument.AFTER))
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值