外行看热闹,内行看门道,盘点精彩世界杯背后你看得见的Redis身影

本文涉及的产品
云原生多模数据库 Lindorm,多引擎 多规格 0-4节点
云数据库 MongoDB,独享型 2核8GB
推荐场景:
构建全方位客户视图
云数据库 Tair(兼容Redis),内存型 2GB
简介: 背景 6月14日晚,2018年俄罗斯世界杯在莫斯科开幕。国内数以千万的观众通过优酷、央视影音或者是咪咕视频观看了此次开幕赛。阿里云公布的一份数据显示,第一波流量洪峰出现在揭幕战开场后的第44分钟,峰值达到了1.5个2018年春晚的规模。

背景

6月14日晚,2018年俄罗斯世界杯在莫斯科开幕。国内数以千万的观众通过优酷、央视影音或者是咪咕视频观看了此次开幕赛。
_
阿里云公布的一份数据显示,第一波流量洪峰出现在揭幕战开场后的第44分钟,峰值达到了1.5个2018年春晚的规模。自此,本届世界杯也成为了史上最大规模的一次在线直播。比赛期间,预计全网70%的世界杯直播流量都跑在了阿里云上。(注:上述内容引用自:https://www.leiphone.com/news/201806/Du10JxOxuJ6Ou782.html,所属权归原作者所有。)

细心的网友们肯定已经注意到了,今年的世界杯与以往的世界杯相比,不仅比赛结果出人意料,而且观看比赛的APP客户端中也增加了丰富的互动和红包惊喜,众平台为了引流和激活“僵尸”用户也是使出了浑身解数。下面一起来盘点一下精彩世界杯背后你看得见的Redis身影吧!主要从业务架构、应用场景、高可用建设以及弹性扩缩容等几个方面进行展开。

业务架构

15300907231675
(图来源自网络)
上图是某企业直播解决方案,主要使用了弹性计算、CDN、智能动态编码技术、视频AI、窄带高清2.0、Redis等等产品技术,充分保证了超清画质体验的同时,节省了带宽的消耗,并最大限度优化资源和成本,给观众带来流畅和丰富多彩的互动体验,极大的满足了用户的参与感。当然,本文重点不是谈论视频如何从录制到播出的,而是要探讨一下“数据库服务器”中Redis在丰富观看直播体验中发挥的重要作用和使用场景及实现。

应用场景

Redis之所以能够被广泛的应用于企业的架构中,而且是不可或缺的重要组成部分,也可以说是标配,其中很重要的一点就是得益于它具有丰富的数据结构,这也是它逐渐替代Memcached,备受青睐的重要原因。它的数据结构有:String、List、Hash、set、Sorted set、bitmap、bit field、hyperLogLog、Geospatial Index等。
15304457602659
正是因为有了这些数据结构和Redis技术的不断完善和发展,才被广泛应用于各行各业中,应用场景也是百花齐放。比如:会话缓存(Session cache)、全页缓存(FPC)、手机验证码、访问频率限制/黑白名单、消息队列、发布与订阅、消息通知、排名/排行榜/最新列表、计数器(比如微博的转评赞计数、阅读数(浏览数,视频播放计数)、博文数(发帖数)、粉丝数、关注数(喜欢商品数)、未读数(动态数))、共同好友/喜好/标签、推送、下拉刷新、私信、商品库存管理(限时的优惠活动信息)、证券指标实时计算,发号器/UUID、以及随着LBS(基于位置服务)的发展,加入的GEO(地理信息定位)的功能和基于Lua自定义命令或功能等等。大家在使用过程中,需要结合自己的业务场景,选择正确的数据类型。那么下面以“优酷APP”为例,来看看有哪些看得见的场景用到了Redis技术。

聊天列表(评论列表)

JS5woYPoSBKerDSMO0upaw_thumb_d

这种评论列表可以用Hash来实现,比如:{userID:contents}

用户ID 评论内容
11101000 破产了

关于评论,你有没有想过一个问题,“垃圾评论” 怎么在评论列表里看不到?没有用户一直在刷评论的?是的,这个肯定是spam系统在默默工作的,这个Redis也是可以做到的,更多策略/机制需要结合drools配合完成。当然通常都是有专门的spam的系统来实现。举个例子,比如要限制某个用户一分钟内的评论次数:

Method1: 用sorted set实现。将最近一天用户评论操作记录起来, score用timestamp替代得分,然后通过Zset的命令RANGEBYSCORE、ZADD、ZRANGEBYSCORE结合实现
RANGEBYSCORE userID:10000:operation:comment 61307510405600 +inf //获得1分钟内的操作记录
redis> ZADD userID:10000:operation:comment 61307510402300 "这是一条评论" //score 为timestamp (integer) 1
redis> ZRANGEBYSCORE userID:10000:operation:comment 61307510405600 +inf //获得1分钟内的操作记录

Method2: 用Redis+Lua实现访问频率控制

# KEYS[1]表示限制次数,由调用程序传入
local key1 ,key2 = 'access:limit' ,'access:expire'
if redis.call('EXISTS' ,key2) > 0 then
   return redis.call('DECR' ,key1) ;
else 
   redis.call('SET' ,key2 ,1)
   redis.call('EXPIRE' ,key2 ,60)
   redis.call('SET' ,key1 ,KEYS[1])
   return KEYS[1]
end

赛况(赛事列表)

aaa1_jpeg
最新活动列表,可以用Redis的List数据结构或者sorted set数据结构实现,加上过期时间轻松搞定。同样的方法,也能轻松的实现最新商品列表、各种排行榜等。

消息(未读消息数)

0saJB2_uTvy_un5BoBtlOQ_thumb_f

实现思路是:使用hash存储用户上次看过的时间,使用sorted set存储每个模块(评论区、群聊)的每个信息产生的时间,并记录未读消息的数量

点赞(点赞数)

GjyATfcAQe6vVwF48kwZ8Q_thumb_e

点赞数,实现相对比较简单了,用string数据结构或者Hash数据结构都能实现,这种点赞没有取消的操作,直接Incr即可。假设key为场次编号:active16

string:
INCR active16
GET active16

Hash:
HSET active:active16 zan 0
HINCRBY active:active16 zan 1
HGETALL active:active16

红包雨(传送门、红包雨)、商品库存/红包金额管理

UNADJUSTEDNONRAW_thumb_13
aaa1
下面介绍一种基于Redis的抢红包方案。

把原始的红包称为大红包,拆分后的红包称为小红包。

1、小红包预先生成,插到数据库里,红包对应的用户ID是null。

2、每个大红包对应两个Redis队列,一个是未消费红包队列,另一个是已消费红包队列。开始时,把未抢的小红包全放到未消费红包队列里。

未消费红包队列里是json字符串,activeID是活动场次,money是红包金额,product是商品个数。如{activeId:'16', money:'300'} 或 {activeID:'16',product:'50'}

3、在Redis中用一个map来过滤已抢到红包的用户。

4、抢红包时,先判断用户是否抢过红包,如果没有,则从未消费红包队列中取出一个小红包,再push到另一个已消费队列中,最后把用户ID放入去重的map中。

5、用一个单线程批量把已消费队列里的红包取出来,再批量update红包的用户ID到数据库里。

上面的流程是很清楚的,但是在第4步时,如果是用户快速点了两次,或者开了两个浏览器来抢红包,会不会有可能用户抢到了两个红包?

为了解决这个问题,采用了lua脚本方式,让第4步整个过程是原子性地执行。

下面是在Redis上执行的Lua脚本:

-- 函数:尝试获得红包,如果成功,则返回json字符串,如果不成功,则返回空
-- 参数:红包队列名, 已消费的队列名,去重的Map名,用户ID
-- 返回值:nil 或者 json字符串,包含用户ID:userId,红包ID:id,红包金额:money

-- 如果用户已抢过红包,则返回nil
if redis.call('hexists', KEYS[3], KEYS[4]) ~= 0 then
return nil
else
-- 先取出一个小红包
local hongBao = redis.call('rpop', KEYS[1]);
if hongBao then
local x = cjson.decode(hongBao);
-- 加入用户ID信息
x['userId'] = KEYS[4];
local re = cjson.encode(x);
-- 把用户ID放到去重的set里
redis.call('hset', KEYS[3], KEYS[4], KEYS[4]);
-- 把红包放到已消费队列里
redis.call('lpush', KEYS[2], re);
return re;
end
end
return nil

参考:https://blog.csdn.net/hengyunabc/article/details/19433779

消息推送

aaa1

上图中的这种弹出消息,未必是Redis实现或者说肯定不是,哈哈。但是这里想提示的是消息提醒,Redis是可以实现的。
15304588827783

这种用pub/sub机制来实现的消息通知,没有持久化机制,属于即发即弃模式。生产者不需要关心有多少的订阅者,也不用关心订阅者的具体信息,在线的客户端(消费者)正常情况下是都看到的,正如我们关注的某个节目一样,在线的时候总能关注的节目更新通知一样。

高可用建设和弹性扩展

面对世界杯这种全球性的全民赛事,尤其是在大家都比较关注的明星或球队对抗的时候(朋友圈都被刷屏的那种),那压力可想而知,虽然拿不到具体的数据,但是从我在微博时保障的热点事件来看,也能猜着个大概。它跟微博热点有很多的相似点,具有不可预见性和突发性,并且伴随着极短时间内流量的数倍增长,甚至更多,有时持续时间较长。如何快速应对突发流量的冲击,确保线上服务的稳定性,是一个非常巨大的挑战和有意义的事情。为了达到这一目标,首先需要有一个完善的,稳定可靠的,健壮的数据库运维体系来提供支撑和管理。
_

正如前面一开始提到的,优酷、央视影音、咪咕视频等视频平台,为了保障业务稳定、减少成本(不可能为了短短一个月的赛事准备4年才用到一次的基础设施),选择和公有云结合是最佳选择,这也是阿里云之所以有流量洪峰出现的重要原因。那么对于Redis来说如何去建设高可用服务以及解决弹性扩展问题?主要有两点:

高可用:异地灾备和多活能力

“不要把鸡蛋放到同一个篮子里”,相信很多架构师也肯定会这么去想,也肯定是这么做的。可以自己搭建一套高可用架构,也可以直接采用阿里云Redis服务提供的异地灾备和多活能力和, 实例部署在跨region,自动双向同步。(参考资料:https://help.aliyun.com/document_detail/71881.html?spm=a2c4g.11186623.6.660.4NtWyS)
_
通过异地灾备和多活的能力,一旦发生故障,还可以通过异地快速接管业务,确保使用体验。另外,很多分布较广的业务,用户需要跨地域远距离访问服务。如果此时访问延迟大,将直接影响用户体验。云数据库Redis提供的云上多活,还可以帮助用户消除跨地域远距离访问时的延迟大问题。

弹性:资源伸缩、读写分离

一个区域出现访问异常后,仍然能通过一些手段,比如降级、切流量、限流等一系列措施来保障服务的稳定性。在云模式下,当业务量上来了,扛不住的时候,可以通过阿里云Redis服务自动具备弹性扩缩容一劳永逸,还可以精打细算使用读写分离功能小成本卸载读压力或者通过混合存储卸载存储成本等等。(参考资料:https://help.aliyun.com/document_detail/65001.html?spm=a2c4g.11186631.6.612.JcCjqf)

总之,Redis是一个非常重要的组件,它能够被广泛的应用于企业的架构中,而且是不可或缺的重要组成部分。

如果之前没有了解过,那么,“Redis,请了解一下”!不足之处,欢迎批评指正。

作者简介:

张冬洪:阿里云MVP,极数云舟对外合作部总监、技术专家,Redis中国用户组主席,中国MySQL用户组主席团成员

点击以下链接报名

https://yq.aliyun.com/event/288/join/pre

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore     ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库 ECS 实例和一台目标数据库 RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
目录
相关文章
|
4月前
|
JavaScript 前端开发 开发者
震撼揭秘!JS模块化进化史:从混沌到秩序,一场代码世界的华丽蜕变,你怎能错过这场编程盛宴?
【8月更文挑战第23天】在 Web 前端开发领域,JavaScript 模块化已成为处理日益复杂的 Web 应用程序的关键技术。通过将代码分解成独立且可重用的模块,开发者能够更有效地组织和管理代码,避免命名冲突和依赖混乱。从最早的全局函数模式到 IIFE,再到 CommonJS 和 AMD,最终进化到了 ES6 的原生模块支持以及 UMD 的跨环境兼容性。本文通过具体示例介绍了这些模块化规范的发展历程及其在实际开发中的应用。
55 0
|
7月前
|
人工智能 数据格式 Python
每日一问-ChapGPT-20230308-关于技术与思考的问题
每日一问-ChapGPT-20230308-关于技术与思考的问题
每日一问-ChapGPT-20230308-关于技术与思考的问题
“阿里味”的「Redis核心实践全彩手册」给你,还学不会就转行吧
面过大厂资深技术岗的人都知道,Redis 基本上是必考点。比如: · Redis 常见的性能问题有哪些?该如何解决?——性能相关 · Redis 缓存的雪崩、击穿、穿透到底是什么意思?如何应对?——缓存相关 · Redis 主从集群常见的问题有哪些?该如何解决?——可用性相关 · 现有 Redis 实例,保存数量 6GB,未来预计会扩展到 32GB,请你提供一个解决方案,并分析它优点和潜在问题?——可扩展性相关
|
编译器 C语言 C++
重生之我要学C++第四天
重生之我要学C++第四天
96 0
|
Java 中间件 应用服务中间件
他山之石,可以攻玉
本文将介绍Nginx的简单部署方法,仅供个人学习。
106 0
|
JSON 算法 fastjson
Fastjon2他来了,性能显著提升,还能再战十年
阿里官方给的定义是,FASTJSON是阿里巴巴的开源JSON解析库,它可以解析JSON格式的字符串,支持将Java Bean序列化为JSON字符串,也可以从JSON字符串反序列化到JavaBean。
569 1
|
前端开发 JavaScript 数据可视化
9 年小厂老前端的年终总结
时光飞逝,岁月如梭,转眼来到 2021 年底,这一年少了些理性,多了点感性,少了些自由,多了一份责任,这一年视乎没做什么事情,但又过得非常充实,最欣慰的是回家有个人等待着我的拥抱,最快乐的是...
1331 0
|
移动开发 缓存 前端开发
圣司:我的前端成长之路,内观自在,外观世音,追寻内心平静
最文艺的前端成长之路分享,相信我,读完它你一定收获良多。
圣司:我的前端成长之路,内观自在,外观世音,追寻内心平静
|
消息中间件 缓存 NoSQL
只要我跑的够快,内卷它就卷不到我,一名高中生是如何做到在疫情下涨薪70%的?
只要我跑的够快,内卷它就卷不到我,一名高中生是如何做到在疫情下涨薪70%的?
3210 0
|
新零售 监控 供应链
观点 | 阿里云:文旅业战“疫”,冰冻期如何自救?
在这次瘟疫之后,文旅行业又会发生怎样的变化?在企业争分夺秒自救和升级的当下,我们看到了些许端倪 —— 线上线下业态融合的加深,大数据对全链路效率的提升,内容IP的打造,文化产品比重的加大……
1022 0
观点 | 阿里云:文旅业战“疫”,冰冻期如何自救?

相关产品

  • 云数据库 Tair(兼容 Redis)
  • 下一篇
    DataWorks