简介

前面介绍了广告定向的实现,它是一个查询密集型 (query-intensive) 程序,所以每个发给它的请求都会引起大量计算。本文将实现一个简单的社交网站,则会尽可能地减少用户在查看页面时系统所需要做的工作。 P184

用户和状态 P185

用户对象存储了用户的基本身份标识信息、用户的关注者人数、用户已发布的状态消息数量等信息,它是构建其他可用且有趣的数据的起点。 P185

状态消息记录了不同的用户都说了什么,以及不同用户之间进行了什么交流,这些由用户创建的状态消息是社交网站真正的内容。 P185

用户信息 P185

用户信息使用 HASH 来存储,用户信息包括:用户名、用户拥有的关注者人数、用户正在关注的人的数量、用户已发布的状态消息的数量、用户的注册日期以及其他一些元信息 (meta-information) 。示例: "user:139960061": {"login": "dr_josiah", "id": "139960061", "name": "Josiah Carlson", "followers": "176", "following": "79", "posts": "386", "signup": "1272948506"} P185

创建用户 P185

创建用户时需要根据用户指定的用户名以及当时的时间戳,创建一个正在关注数量、关注者数量、已发布状态消息数量都被设置为 0 的对象。 P185

创建时除了要对用户信息进行初始化,还需要对用户名进行加锁,用以防止多个请求 (request) 在同一时间内使用相同的用户名来创建新用户(可以使用 08. 实现自动补全、分布式锁和计数信号量 中实现的分布式锁进行加锁操作)。

状态消息 P186

状态消息使用 HASH 来存储,状态消息包括:消息本身、消息发布的时间、消息发布者的 id 、用户名(冗余用户名是为了展示时避免用户信息的 HASH ,因为用户名是不会改变的)以及其他一些关于状态消息的附加信息。示例: "status:223499221154799616": {"message": "My pleasure. I was amazed that...", "posted": "1342908431", "id": "223499221154799616", "uid": "139960061", "login": "dr_josiah"} P186

创建消息时需要先获取用户名,再将相关的信息组合起来存储到 HASH 中。 P187

主页时间线 P187

主页时间线是一个列表,它由用户以及用户正在关注的人所发布的状态消息组成。个人时间线与主页时间线类似,它只包含用户自己所发布的状态消息。因为主页时间线是用户访问网站时的主要入口,所以这些数据必须尽可能地易于获取。 P187

主页时间线使用有序集合存储,成员为状态消息的 id ,成员的分值为状态消息发布的时间戳。示例: "home:139960061": {..., "227138379358277633": "1342988984", ...} P188

获取主页时间线分为两步: P188

  1. 使用 ZREVRANGE 分页获取最新状态消息的 id 列表
  2. 使用流水线和 HGETALL 获取到状态消息 id 列表中所有状态消息

关注者列表和正在关注列表 P189

用户正在关注列表以及关注者列表同样用有序集合存储,成员为用户的 id ,成员的分值为用户开始关注某人或被某人关注的时间戳。示例:"followers:139960061": {..., "558960079": "1342915440", "14502701": "1342917840", ...} "following:139960061": {..., "18697326": "1339286400", "558960079": "1342742400"} P188

当用户开始关注或者停止关注另一个用户时,就需要对这两个用户的正在关注有序集合和关注者有序集合进行更新 (ZADD, ZREM),并修改他们用户信息中的关注数量和被关注数量 (HINCRBY),同时还需要操作者的主页时间线,添加或删除另一个用户的状态消息 (ZUNIONSTORE)。 P189

删除操作需要两个命令,因为有序集合没有求差集的命令,有两种方式可以实现:

  1. 使用 ZREVRANGE 获取另一用户个人主页对应的有序集合的成员列表,然后再使用 ZREM 从操作用户主页流水线对应的有序集合中删除这些成员
  2. 先使用 ZUNIONSTORE 合并集合,操作用户主页流水线对应的有序集合的权重为 1 ,另一用户个人流水线对应的有序集合的权重为 0 ,聚合方式使用 MIN ,然后再使用 ZREMRANGEBYSCORE key 0 0 移除所有分值为 0 的成员(可以使用流水线合并)

所思

练习题让在给定的基础上支持批量关注和取消关注的操作。其实业务中大部分情况下单个和批量操作都是类似的,并且后续很可能会支持批量操作,为了减少后期后端开发量、避免改动接口签名或类似功能接口爆炸性增长,我常常都会提前实现批量操作的接口。我们平时开发时不能仅对当前需求进行处理,还要去理解整体功能并站在用户的角度进行思考,尽早关注可能的变动,这样才能开发出具有扩展性的接口。

状态消息的发布与删除 P191

用户可以执行的一个最基本的操作就是发布状态消息,前面已将实现了创建状态消息的逻辑,接下来将实现把新的状态消息添加到每个关注者的主页时间线中。 P191

为了让发布操作尽可能快地返回,我们在创建后会仅针对前 1000 个关注者的主页时间线添加新的状态消息,如果当前发布者的关注者超过了 1000 个,则使用 09. 实现任务队列、消息拉取和文件分发 中实现的任务队列异步处理后续的关注者。 P192

删除消息时同理操作即可,先删除状态消息本身,然后处理发布者自己的统计信息,再从个人时间线中删除该消息 id ,最后再从前 1000 个关注者的主页时间线中删除,若关注者人数超过 1000 ,再使用任务队列异步处理后续的关注者。 P193

流 API P194

构建一些函数来广播 (broadcast) 简单的事件 (event) ,然后由负责进行数据分析的事件监听器 (event listener) 来接收并处理这些事件,流 API 请求能在一段比较长的时间内持续地返回数据。 P194

流 API 的作用是随着时间的推移,产生一个由时间组成的序列,以此来让整个网络上的客户端和其他服务及时地了解到网站目前正在发生的事情。 P195

构建流 API 的过程中需要进行各种各样的决策,这些决策主要和以下 3 个问题有关: P195

  • 流 API 需要对外公开哪些事件?

    • 需要公开目前实现的四种用户操作:发布消息、删除消息、关注用户和取消关注用户。本节将以创建发布消息事件和删除消息事件为例进行实现
  • 是否需要进行访问限制?如果需要的话,采取何种方式实现?
    • 目前仅在涉及用户隐私或者系统资源的时候,考虑访问限制
  • 流 API 应该提供哪些过滤选项?
    • 既可以通过关注过滤器(基于用户进行过滤)、检测过滤器(基于关键字进行过滤)和位置过滤器来获取过滤后的消息,又可以通过类似推特的 firehose (可以获取所有公开消息) 和 sample (只能获取少量公开消息) 这样的流来获取一些随机的消息。
标识客户端 P198

为了区分不同的客户端,需要对其进行标识,大部分情况下来说只用考虑已登陆用户即可,那我么使用用户 id 进行标识,为了同时实现验证用户 id 的功能,可以使用 JWT 。

过滤消息 P200

我们将使用 Redis 的 PUBLISH 命令和 SUBSCRIBE 命令(05. Redis 其他命令简介 介绍了这两个命令的用法和缺陷)来实现订阅发布功能:当用户发布一条消息时,程序会通过 PUBLISH 发送给某个频道,而各个过滤器则通过 SUBSCRIBE 来订阅并接收那个频道的消息,并在发现与过滤器相匹配的消息时,将消息回传 (yield back) (如果是发布消息,则回传实体;如果是删除消息,则回传 id 和当前状态)给 Web 服务器,然后由服务器将这些消息发送给客户端。 P200

本文首发于公众号:满赋诸机(点击查看原文) 开源在 GitHub :reading-notes/redis-in-action

Redis 实战 —— 11. 实现简单的社交网站的更多相关文章

  1. redis实战笔记(8)-第8章 构建简单的社交网站

    本章主要内容   用户和状态 主页时间线 关注者列表和正在关注列表 状态消息的发布与删除 流API                  

  2. Redis实战:如何构建类微博的亿级社交平台

    微博及 Twitter 这两大社交平台都重度依赖 Redis 来承载海量用户访问.本文介绍如何使用 Redis 来设计一个社交系统,以及如何扩展 Redis 让其能够承载上亿用户的访问规模. 虽然单台 ...

  3. (转)国内外三个不同领域巨头分享的Redis实战经验及使用场景

    随着应用对高性能需求的增加,NoSQL逐渐在各大名企的系统架构中生根发芽.这里我们将为大家分享社交巨头新浪微博.传媒巨头Viacom及图片分享领域佼佼者Pinterest带来的Redis实践,首先我们 ...

  4. Redis实战经验及使用场景

    随着应用对高性能需求的增加,NoSQL逐渐在各大名企的系统架构中生根发芽.这里我们将为大家分享社交巨头新浪微博.传媒巨头Viacom及图片分享领域佼佼者Pinterest带来的Redis实践,首先我们 ...

  5. Redis实战

    大约一年多前,公司同事开始使用Redis,不清楚是配置,还是版本的问题,当时的Redis经常在使用一段时间后,连接爆满且不释放.印象中,Redis 2.4.8以下的版本由于设计上的主从库同步问题,就会 ...

  6. Redis实战之Redis + Jedis

    用Memcached,对于缓存对象大小有要求,单个对象不得大于1MB,且不支持复杂的数据类型,譬如SET 等.基于这些限制,有必要考虑Redis! 相关链接: Redis实战 Redis实战之Redi ...

  7. Redis实战之征服 Redis + Jedis + Spring (一)

    Redis + Jedis + Spring (一)—— 配置&常规操作(GET SET DEL)接着需要快速的调研下基于Spring框架下的Redis操作. 相关链接: Redis实战 Re ...

  8. Redis实战之Redis + Jedis[转]

    http://blog.csdn.net/it_man/article/details/9730605 2013-08-03 11:01 1786人阅读 评论(0) 收藏 举报   目录(?)[-] ...

  9. redis实战笔记(10)-第10章 扩展Redis

    本章主要内容   扩展读性能 扩展写性能以及内存容量 扩展复杂的查询   随着Redis的使用越来越多, 只使用一台Redis服务器没办法存储所有数据或者没办法处理所有读写请求的问题迟早都会出现, 这 ...

随机推荐

  1. 【Java并发编程】阿里最喜欢问的几道线程池的面试题?

    引言 上一篇文章我们有介绍过线程池的一个基本执行流程<[Java并发编程]面试必备之线程池>以及它的7个核心参数,以及每个参数的作用.以及如何去使用线程池 还留了几个小问题..建议看这篇文 ...

  2. JDBC访问数据库的基本步骤是什么?

    1.加载(注册)数据库驱动(到JVM) 2.建立(获取)数据库连接. 3.创建(获取)数据库操作对象. 4.定义操作的SQL语句. 5.执行数据库操作. 6.获取并操作结果集. 7.关闭对象,回收数据 ...

  3. java.util.Collections

    p.p1 { margin: 0; font: 11px Monaco } span.s1 { text-decoration: underline } span.s2 { color: rgba(1 ...

  4. HTTP 常用状态码200 301 302 403 500

    200(OK):成功处理了请求. 301 redirect: 301 代表永久性转移(Permanently Moved) //助记 1 永恒,如果你记住了这一条就算这篇博客没白写.302 redir ...

  5. 注意力论文解读(1) | Non-local Neural Network | CVPR2018 | 已复现

    文章转自微信公众号:[机器学习炼丹术] 参考目录: 目录 0 概述 1 主要内容 1.1 Non local的优势 1.2 pytorch复现 1.3 代码解读 1.4 论文解读 2 总结 论文名称: ...

  6. 域名解析 看Cname 信息

    CMD 命令: nslookup -q=cname www.yuzhentan.com

  7. Linux设备上没有空间之复盘

    某天前端在调接口的时候,发现登录页面得验证码接口居然没有响应数据,显示的是500响应码.于是我一路排查,首先排查验证码接口所属的微服务是否正常,通过lsof -i:服务端口进行排查,发现该微服务进程存 ...

  8. fastjsion反序列化漏洞渗透测试笔记

    本文原创地址:https://www.cnblogs.com/yunmuq/p/14268028.html 一.背景 fastjsion是阿里的开源Java工具:https://github.com/ ...

  9. Java NIO 缓冲区 Buffer

    缓冲区 Buffer 是 Java NIO 中一个核心概念,它是一个线性结构,容量有限,存放原始类型数据(boolean 除外)的容器. 1. Buffer 中可以存放的数据类型 java.nio.B ...

  10. Docker-ce Centos8 笔记一:安装Docker-ce

    Docker是一个建设企业及数据中心服务仓库的进程,通过裸金属机和虚拟机承载的MAC.windows和linux系统提供本地和远程软件服务,涉及应用软件镜像.系统镜像.虚拟化仓库(虚拟机).它承载着灵 ...