跳到内容

RedisGears设计:隔离技术

RedisGears带有嵌入式系统Python解释器.这样就可以使用RG。PYEXECUTE命令.因为解释器是一个单例,在所有调用之间共享RG。PYEXECUTE,如果使用相同的标识符(即全局变量、函数、类名等),则存在执行不同的风险。

解决这个问题的一种方法是在每次执行之前重新启动解释器。然而,解释器重新启动是一项耗时的操作,因此这种方法并不理想。另外,两个执行可能并行运行,在两个不同的线程中,甚至在同一个线程中(虽然Python代码本身的执行始终是非并行的,但执行生命周期的其余部分实际上可能是并行的)。当多个执行正在运行时,重新启动解释器不再是一个选项。

目前,RedisGears使用全局字典来隔离每个执行。这意味着,如果两个执行声明相同的函数名(具有不同的实现),它们不会互相攻击。尽管这种隔离在大多数情况下是足够的,但它并不是完美的。这种方法最大的缺点是导入模块:所有导入模块的执行X将得到相同的模块实例X.这意味着即使我们用不同的模块实现为每次执行创建一个虚拟环境X,所有的执行都将首先使用导入的实现。

另一种提供隔离的方法是Python的Sub-Interpreters.子解释器是(几乎)独立的Python代码执行环境。使用Python C API可以创建一个新的子解释器Py_NewInterpreter,用Py_EndInterpreter,并在使用子解释器之间切换PyThreadState_Swap

RedisGears以前也使用过子解释器,但当我们发现一些库与子解释器不兼容时,我们决定转向全球词典。我们计划在未来返回对子解释器的支持,并提供一些开/关开关,以允许使用与子解释器不兼容的库。其思想是维护用户调用之间的关联RG。PYEXECUTE及其各自的子解释器。

RG。PYEXECUTE时,将创建一个新的子解释器来执行所提供的脚本。该子解释器也将被脚本创建的所有后续操作(即执行和注册)“继承”。因为子解释器可能有多个所有者,所以RedisGears会为每个子解释器保留一个内部引用计数,这样就可以安全地释放它。

请注意,次级口译员之间的隔离也不完美。例如,当使用低级文件操作时,例如os.close (),由于扩展名的共享方式,子解释器可以(意外地或恶意地)影响彼此打开的文件。

进一步的参考

Python Sub-Interpreters

Baidu