面经 | Backend | 🔥🔥 | Datadog
2026(7-9月) Software Engineer @ Datadog - Technical Screen | 🙂 Positive | Medium | Pending
这一轮大概 50 分钟,前面简单聊了下背景,没聊多久就开始 coding。
就一道题,没有 LC:用 Python threading 写一个简单的 Pub-Sub。
我一开始觉得加个 lock 就差不多了,结果 interviewer 就一直顺着我刚写的东西往下加条件。
Technical Screen — Python Pub-Sub
第一版很直接:一个 dict 存 topic -> subscribers,publish 的时候找到这个 topic 的 subscriber,把 message 发过去。
因为是多线程,我在外面直接加了一个 lock,shared state 的读写都走它。
publish 的时候另一个 thread 在 subscribe
第一个问题:一个 thread 在 publish 的时候,另一个 thread 同时 subscribe 怎么办。
我说 shared state 都在 lock 里,subscribe 改的是 topic -> subscribers 这个映射,publish 读的也是它,不会读到改了一半的状态。
两个 publish 同时发生
然后是:两个 publish 同时发生呢。
这个也差不多,还是同一份 shared state 和同一个 lock,serialize 掉了。
这两个我前面答得还行,基本就是围绕 shared state 和 lock。
subscriber callback 卡在 lock 里
再往后他问,如果有一个 subscriber 特别慢会怎么样。
这里我第一版就有问题。因为我当时是在 lock 里面直接调 subscriber callback:
def publish(self, topic, message):
with self.lock:
for sub in self.subscribers.get(topic, []):
sub.callback(message)
一个 callback 卡住的话,其他 publish / subscribe 也会跟着等。
是他顺着这个问题往下问以后,我才改成先把 subscriber list 拿出来,release lock,再往下 dispatch:
def publish(self, topic, message):
with self.lock:
subs = list(self.subscribers.get(topic, []))
for sub in subs:
sub.callback(message)
这样 lock 只保护 shared state,不保护 callback。
Slow consumer
他又继续问 slow consumer 怎么处理。
我说可以给每个 subscriber 自己一个 queue,publish 只负责往 queue 里放,每个 subscriber 有自己的 worker thread 去消费。这样慢的那个只堵自己,不会把别人一起堵住。
他接着问:queue 满了呢。
我先说的是 bounded queue / backpressure。
他又说,假设 message 不能直接丢。
这一块我聊得有点乱。我提了 block,也提了 retry,但是没有讲成一个完整的东西,代码也没继续补完。
Unsubscribe 时 queue 里还有消息
最后还问了 unsubscribe 的时候,如果 queue 里面还有没处理完的 message 怎么办。
这个我印象已经没那么深了,当时主要是口头讲了一下,没落到代码。
整轮就这一题,没有 LC。题不难,但是 interviewer 会一直顺着你现在写的东西往下问。我前面写得挺快,后面才发现这种 concurrent code 很容易一开始觉得“加个 lock 就完了”。lock scope 和 slow consumer 这两块,我觉得自己答得一般。