要求
我目前正在构建权限系统。要求之一是它是水平可扩展的。
为此,我们做了以下工作
有一个“已编译资源权限”表,如下所示:
| user_id | resource_id | reason |
| 1 | 1 | 1 |
| 1 | 2 | 3 |
| 2 | 1 | 2 |
该表的结构表示用户 1 可以访问资源 1 和 2,而用户 2 只能访问资源 1。
“原因”列是一个按位数字,根据“为什么”他们拥有该权限,它的位被打开。二进制位“1”表示他们是管理员,二进制位“2”表示他们创建了资源。
所以用户 1 可以访问资源 1,因为他们是管理员。他有权访问资源 2,因为他是管理员并且他创建了该资源。如果他不再是管理员,他仍然可以访问工单 2,但不能访问工单 1。
为了弄清楚需要进入这个表的内容,我们使用了一个“修补程序”类,它以编程方式循环传递给它的用户和资源,并在逻辑上查看所有必要的数据库表,以确定需要添加哪些行以及需要从中删除哪些行桌子。
我们如何尝试扩展和问题
为了横向扩展,我们将逻辑拆分为块并将其提供给异步队列上的许多“工作人员”
这似乎只是在它不再加速之前扩展,有时甚至发生行锁定,这会减慢它的速度。
我们可以使用特定类型的行锁来允许它无限扩展吗?
我们是从完全错误的角度来处理这个问题吗?我们有很多“原因”和很多复杂的权限逻辑,我们需要能够相当快地重新编译
并发运行的 SQL 查询,供参考
当我们“添加”原因时:
INSERT INTO `compiled_permissions` (`user_id`, `resource_id`, `reason`) VALUES ((1,1,1), (1,2,3), (2,1,2)) ON DUPLICATE KEY UPDATE `reason` = `reason` | VALUES(`reason`);
当我们“删除”原因时:
UPDATE `compiled_permissions` SET `reason` = `reason` & ~ (CASE
(user_id = 1 AND resource_id = 1 THEN 2 ... CASE FOR EVERY "REASON REMOVAL")
ELSE `reason`
END)
WHERE (`user_id`, `resource_id`) IN ((1,1),(1,2) .. ETC )