code: async def _lease_shard(self):
          
  
          prefix = self._prefix + '/shards/'
          self._lease = await self._client.grant_lease(ttl=self._shard_ttl)
  
          timestamp_bytes = (0).to_bytes(4, byteorder='big')
  
          retries = 0
          while True:
              shard_subidx = len(prefix)
              shard_id = 0
  
              # 找到未使用的最小分片号
              records = await self._client.range_keys(range_prefix(prefix))
              nums = sorted(int_fromhexbytes(k[shard_subidx:]) for k, _ in records)
              for i, n in enumerate(nums):
                  if n > i:
                      shard_id = i
                      break
              else:
                  shard_id = len(nums)
  
              shard_id = int_tohex(shard_id, length=2)
  
              logger.debug(f'leasing shard#{shard_id}, retry={retries}')
  
              shard_path = f'{self._prefix}/shards/{shard_id}'
              is_success, _ = await self._client.txn(compare=[
                      transaction.Version(shard_path) == 0 
                  ], success=[
                      KV.put.txn(shard_path, timestamp_bytes, lease=self._lease)
                  ])
  
              if is_success:
                  self._shard_id = shard_id
                  self._timestamp = None
                  self._seqnum = None
                  break
              else:
                  logger.debug(f'failed in leasing shard#{shard_id}: retry {retries}')
                  await _random_nap(retries)
                  retries += 1
  
                  if retries > 10:
                      raise ValueError('out of retries')
docs: 申请一个新分片，从小到大[0,4095]寻找一个为占用的分片