Liam0205 / liam0205.github.io

Deployment of my weblog.
https://liam0205.github.io
34 stars 5 forks source link

设计一个线程安全的数据重载器 | 始终 #367

Open Liam0205 opened 3 years ago

Liam0205 commented 3 years ago

https://liam.page/2021/01/03/design-a-thread-safe-data-reloader-in-cxx/

实际工程中,可能会遇见这样的场景: 一个词典,在 C++ 里实现为一个 class。它的生命周期从进程启动开始到进程杀死结束。这个词典很大,所以在多线程工作的时候,希望在全局共享一份。 现在的问题是,进程可能持续跑很长时间,比如跑几个月。在进程执行过程中,这个词典可能会更新。于是我需要重新载入词典。要求线程安全并且高效地做这个重新载入的工作。 今天我们来设计一下,要怎样实现它。

BlodSide commented 3 years ago

词典这个东西和词典使用方绑在一起同生共死其实不是一个好的选择,因为:

  1. 词典很大启动贼慢,在微服务场景下会带来更大的风险
  2. 业务代码比起词典来说,几乎不占内存
  3. 调试极其痛苦 解决方案一般是专门搞个轮子托管词典,词典的提供方式可以由多种:比如说通过 mmap 共享;比如说动态链接挂载使用方等等
Liam0205 commented 3 years ago

词典这个东西和词典使用方绑在一起同生共死其实不是一个好的选择,因为:

  1. 词典很大启动贼慢,在微服务场景下会带来更大的风险

case-by-case,都微服务了,词典应该直接上 Redis/Couchbase 这些东西。

  1. 业务代码比起词典来说,几乎不占内存
  2. 调试极其痛苦 解决方案一般是专门搞个轮子托管词典,词典的提供方式可以由多种:比如说通过 mmap 共享;比如说动态链接挂载使用方等等

mmap 只解决读入这一步的效率,解决不了解析的问题。而且 mmap 还得逐帧预载,否则对外提供服务的时候,还会触发缺页中断。实际上也快不到哪里去。如果不解析,就得编成特定格式的字典。比如做成二分,或者做成 Trie 树。但并不是所有的 case 都适合这么做。

至于说共享,除非服务混布在一台服务器上,不然也共享不起来。