假设您正在撰写博客网站。它显示多个作者按“优先级”排序的最近博客文章。最高优先级。优先级由以下公式决定:
订单必须始终准确实时。
按优先级排序很容易。问题是让我们说我们的网站非常受欢迎,评论以每分钟数百的速度飞行。他们在几十个帖子上飞来。
是否有处理此方案的模式?换句话说,只要对帖子发表评论,然后在每次加载页面时对帖子进行排序,我们能做的只是更新优先级字段吗?缓存发布顺序没有多大帮助,因为繁重的用户活动会导致订单频繁更改。
对于“模式”,我从代码和数据库架构的角度来讲。
答案 0 :(得分:0)
您可以使用平衡二叉树(例如红黑树)来存储已排序的索引,这样可以比每次对整个索引进行排序时更快地进行更新。
使用Java-ish伪代码看起来像
Tree tree;
Node {
int priority;
incrementPriority() {
priority = priority + 1;
if(priority > tree.nextHighestNode(this)) {
tree.remove(this);
tree.add(this);
}
}
decrementPriority() {
priority = priority - 1;
if(priority < tree.nextLowestNode(this)) {
tree.remove(this);
tree.add(this);
}
}
}
如果更改节点的优先级意味着它位于无效的树位置(意味着它高于应该是下一个最高节点,或者低于应该是下一个最低节点),那么它将被删除并重新添加到树(它负责重新平衡本身)。插入是O(log(n)),但通常(当没有插入/删除时)更新优先级是一个恒定时间操作。
Red-black trees是如何平衡二叉树通常实现的,但有一些替代方案,例如一个Tango tree可能更合适,因为它是一个在线实现。最大的问题是并发性 - 理想情况下,您希望能够使用某种AtomicInteger实现节点的优先级字段(允许原子增量和减量;很多语言都有这样的东西),这样你就赢了“每次更改时都需要锁定字段,但很难将优先级与相邻节点的优先级进行原子比较。
作为替代方案,您可以将所有内容存储在数组或链接列表中,并在优先级更改时交换相邻元素 - 这样您就不需要每次都进行完整排序,而不像平衡二叉树那样删除插入元素是O(log(n)),交换两个相邻的数组/列表元素是恒定时间。唯一的问题是,添加一个全新的元素对于数组来说代价很高,因为你需要移动所有数组的元素;它也是带有列表的O(n),因为你需要遍历列表,直到找到插入项目的正确位置,但这可能比数组更好,因为你不需要移动任何相邻的元素(这将减少你需要做的锁定量)。