Facebook 或 Twitter 是如何实现他们的订阅系统的
How did Facebook or Twitter implement their subscribe system
我正在开发类似 SNS 的移动应用程序项目,用户可以在其中上传他们的内容并可以在他们的主页上看到他们订阅的主题或朋友的更新。
我将用户内容存储在mysql中,通过简单地先查询出用户订阅的人和内容来查询用户特定的主页数据,然后查询使用[=过滤掉的内容table 24=] 子句。
我怀疑当内容 table 堆积或用户订阅大量用户或主题时,这会变得相当慢。我们新发布的应用程序已经开始每周都有数以千计的新用户,并且随着时间的推移会越来越多。可扩展性现在必须是我们关注的问题。
所以我想知道 Facebook 或 Twitter 是如何处理这个拥有惊人数量用户的订阅问题的。他们是否为每个用户处理一个列表?我试图搜索,但我得到的只是如何与 Facebook 或 Twitter 交互,而不是他们如何实际实现此功能。
我注意到您在使用 Facebook 时只能看到更新而不是历史记录。这意味着订阅新用户不会像使用我当前的方法那样将大量过时的内容转储到您的供稿中。
Facebook 如何设计他们的数据库以及他们如何向订阅用户发送新内容?
我的后端目前是 PHP+MySQL,我不介意引入其他后端技术,例如 Redis 或 JMS 之类的,如果这是应该的方式的话。
听起来你们还处于早期阶段。有 N 种方法可以解决这个问题,所有这些都取决于你认为你会在短期内达到 DAU 的哪个阶段,你必须在硬件上花费多少钱,你手中的时间来构建它,等等
您可以尝试使用临时 table 对新引入的项目进行排队,以及它所包含的元数据(哪个主题、朋友 user_id 列表等)。然后使用像 RabbitMQ/GearMan 这样的队列消费者系统来管理这个不断增长的列表的消费,并找出谁应该处理这个。在 Scala 或类似 Maven/Tomcat 的 J2EE 系统中构建队列消费者程序,可以持久化。如果你真的想坚持使用 PHP,构建一个 PHP REST API,它可以存在于 php5-fpm 的内存中,并由 FastCGI 进程管理器管理,并通过像 nginx 这样的代理,由 curl 调用以适当的时间间隔从 cron 执行的脚本启动。
[编辑] - 最好不要将数据库用于排队系统,使用像 Redis 这样的缓存服务器,它在很多方面都优于数据库,并且可以持久保存到磁盘(查找 RDB 和 AOF)。它不是很容错,万一作业突然失败,您可能会丢失作业记录。您很可能不会关心这些崩溃边缘情况。还查找 php-resque!
为了让 SNS 有效地走出去,我假设您已经对 table 进行了去规范化。我想象一个 "user_topic" table 主题映射到订阅他们的用户。创建另一个 table "notification_metadata" 描述用户喜欢在哪里接收通知(SMS/push/email/in-app 通知),以及推送到这些渠道所需的元数据(APNS/GCM 的移动客户端批准密钥,电子邮件地址、用户身份验证令牌)。对 notification_metadata 中的两个字段使用 JSON blob,因此每个用户将有一行。这节省了 I/O 对数据库的点击。
使用 user_id 作为 "notification_meta" 的主键,使用 user_id + topic_id 作为 "user_topic" 的主键。不要为任何一个添加自动递增 "id" 字段,它在这个用例中毫无用处(占用 space、CPU、索引内存等)。如果两个字段都在 PK 中,则 user_topic 上的查询将全部来自内存,并且在 JOIN 期间唯一的磁盘命中是在 "notification_meta" 上。
因此,如果一个用户订阅了 2 个主题,"user_topic" 中将有两个条目,并且每个用户在 "notification_meta"
中始终只有一行
有更多扩展方法,比如为每个新主题动态创建一个新的 table,根据 user_id 分片到不同的 MySQL 个实例,分区等。有 N - 扩展方式,尤其是在 MySQL 中。祝你好运!
我正在开发类似 SNS 的移动应用程序项目,用户可以在其中上传他们的内容并可以在他们的主页上看到他们订阅的主题或朋友的更新。
我将用户内容存储在mysql中,通过简单地先查询出用户订阅的人和内容来查询用户特定的主页数据,然后查询使用[=过滤掉的内容table 24=] 子句。
我怀疑当内容 table 堆积或用户订阅大量用户或主题时,这会变得相当慢。我们新发布的应用程序已经开始每周都有数以千计的新用户,并且随着时间的推移会越来越多。可扩展性现在必须是我们关注的问题。
所以我想知道 Facebook 或 Twitter 是如何处理这个拥有惊人数量用户的订阅问题的。他们是否为每个用户处理一个列表?我试图搜索,但我得到的只是如何与 Facebook 或 Twitter 交互,而不是他们如何实际实现此功能。
我注意到您在使用 Facebook 时只能看到更新而不是历史记录。这意味着订阅新用户不会像使用我当前的方法那样将大量过时的内容转储到您的供稿中。
Facebook 如何设计他们的数据库以及他们如何向订阅用户发送新内容?
我的后端目前是 PHP+MySQL,我不介意引入其他后端技术,例如 Redis 或 JMS 之类的,如果这是应该的方式的话。
听起来你们还处于早期阶段。有 N 种方法可以解决这个问题,所有这些都取决于你认为你会在短期内达到 DAU 的哪个阶段,你必须在硬件上花费多少钱,你手中的时间来构建它,等等
您可以尝试使用临时 table 对新引入的项目进行排队,以及它所包含的元数据(哪个主题、朋友 user_id 列表等)。然后使用像 RabbitMQ/GearMan 这样的队列消费者系统来管理这个不断增长的列表的消费,并找出谁应该处理这个。在 Scala 或类似 Maven/Tomcat 的 J2EE 系统中构建队列消费者程序,可以持久化。如果你真的想坚持使用 PHP,构建一个 PHP REST API,它可以存在于 php5-fpm 的内存中,并由 FastCGI 进程管理器管理,并通过像 nginx 这样的代理,由 curl 调用以适当的时间间隔从 cron 执行的脚本启动。
[编辑] - 最好不要将数据库用于排队系统,使用像 Redis 这样的缓存服务器,它在很多方面都优于数据库,并且可以持久保存到磁盘(查找 RDB 和 AOF)。它不是很容错,万一作业突然失败,您可能会丢失作业记录。您很可能不会关心这些崩溃边缘情况。还查找 php-resque!
为了让 SNS 有效地走出去,我假设您已经对 table 进行了去规范化。我想象一个 "user_topic" table 主题映射到订阅他们的用户。创建另一个 table "notification_metadata" 描述用户喜欢在哪里接收通知(SMS/push/email/in-app 通知),以及推送到这些渠道所需的元数据(APNS/GCM 的移动客户端批准密钥,电子邮件地址、用户身份验证令牌)。对 notification_metadata 中的两个字段使用 JSON blob,因此每个用户将有一行。这节省了 I/O 对数据库的点击。
使用 user_id 作为 "notification_meta" 的主键,使用 user_id + topic_id 作为 "user_topic" 的主键。不要为任何一个添加自动递增 "id" 字段,它在这个用例中毫无用处(占用 space、CPU、索引内存等)。如果两个字段都在 PK 中,则 user_topic 上的查询将全部来自内存,并且在 JOIN 期间唯一的磁盘命中是在 "notification_meta" 上。
因此,如果一个用户订阅了 2 个主题,"user_topic" 中将有两个条目,并且每个用户在 "notification_meta"
中始终只有一行有更多扩展方法,比如为每个新主题动态创建一个新的 table,根据 user_id 分片到不同的 MySQL 个实例,分区等。有 N - 扩展方式,尤其是在 MySQL 中。祝你好运!