m2m模型翻译
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

77 lines
2.8 KiB

6 months ago
  1. from __future__ import absolute_import
  2. import collections
  3. import logging
  4. from kafka.vendor import six
  5. from kafka.coordinator.assignors.abstract import AbstractPartitionAssignor
  6. from kafka.coordinator.protocol import ConsumerProtocolMemberMetadata, ConsumerProtocolMemberAssignment
  7. log = logging.getLogger(__name__)
  8. class RangePartitionAssignor(AbstractPartitionAssignor):
  9. """
  10. The range assignor works on a per-topic basis. For each topic, we lay out
  11. the available partitions in numeric order and the consumers in
  12. lexicographic order. We then divide the number of partitions by the total
  13. number of consumers to determine the number of partitions to assign to each
  14. consumer. If it does not evenly divide, then the first few consumers will
  15. have one extra partition.
  16. For example, suppose there are two consumers C0 and C1, two topics t0 and
  17. t1, and each topic has 3 partitions, resulting in partitions t0p0, t0p1,
  18. t0p2, t1p0, t1p1, and t1p2.
  19. The assignment will be:
  20. C0: [t0p0, t0p1, t1p0, t1p1]
  21. C1: [t0p2, t1p2]
  22. """
  23. name = 'range'
  24. version = 0
  25. @classmethod
  26. def assign(cls, cluster, member_metadata):
  27. consumers_per_topic = collections.defaultdict(list)
  28. for member, metadata in six.iteritems(member_metadata):
  29. for topic in metadata.subscription:
  30. consumers_per_topic[topic].append(member)
  31. # construct {member_id: {topic: [partition, ...]}}
  32. assignment = collections.defaultdict(dict)
  33. for topic, consumers_for_topic in six.iteritems(consumers_per_topic):
  34. partitions = cluster.partitions_for_topic(topic)
  35. if partitions is None:
  36. log.warning('No partition metadata for topic %s', topic)
  37. continue
  38. partitions = sorted(partitions)
  39. consumers_for_topic.sort()
  40. partitions_per_consumer = len(partitions) // len(consumers_for_topic)
  41. consumers_with_extra = len(partitions) % len(consumers_for_topic)
  42. for i, member in enumerate(consumers_for_topic):
  43. start = partitions_per_consumer * i
  44. start += min(i, consumers_with_extra)
  45. length = partitions_per_consumer
  46. if not i + 1 > consumers_with_extra:
  47. length += 1
  48. assignment[member][topic] = partitions[start:start+length]
  49. protocol_assignment = {}
  50. for member_id in member_metadata:
  51. protocol_assignment[member_id] = ConsumerProtocolMemberAssignment(
  52. cls.version,
  53. sorted(assignment[member_id].items()),
  54. b'')
  55. return protocol_assignment
  56. @classmethod
  57. def metadata(cls, topics):
  58. return ConsumerProtocolMemberMetadata(cls.version, list(topics), b'')
  59. @classmethod
  60. def on_assignment(cls, assignment):
  61. pass