利用redis自制幻灯片弹幕
前段时间赶项目,忙结婚,各大技术平台都没时间上,不过还是抽出点时间为自己的婚礼做了一点小玩具,今天我就来给大家分享一下。
先来看一下效果


这个项目是基于微信个人订阅号的,订阅号的开发在此我就不再赘述了。
基本开发思路是,服务器接收到用户文本信息,用正则匹配一下然后去掉前面的cg#(这一步其实可有可无,不过为了区分其他的指令而加上),然后存进服务器。本地用浏览器跑一个轮播图,然后拿到弹幕信息就可以在浏览器播放了。
这里有2个关键点:
1、本地如何拿到弹幕信息?两台物理机器如何实时获取信息?这里的信息延迟我要求不能超过1s。这里我找到有两个方案,A 本地设置定时器直接请求远程服务器拉取弹幕信息。B 本地与远程服务器建立一个socket长连接,服务器主动写数据。
2、这个场景交互比较频繁,IO相对比较密集(婚礼上并发可能会高达100+),存数据库的话压力会比较大,如果挂掉了本少爷的脸也挂不住了-_-||
好,接着来一个一个的解决,先从技术选型开始。
1、如果数据库扛不住,那么我不存数据库,直接存缓存行得通吗?弹幕信息带有时序性的属性,redis自带队列数据结构,这很适合,redis对外宣称的并发数为3-5w,刚好之前被推荐买了一本redis实战,也看完了,就用来实践一下。服务器拿到弹幕信息后存进队列
/**
* [saveInfo description]
* @param object $postObj 微信XML实体
* @return [type] [description]
*/
private function saveInfo($postObj) {
// 数据处理
$openid = $postObj->FromUserName;
$content = preg_replace("/^(cg#){1}/i", "", $postObj->Content); // 准备存入队列的json数据
$value = array(
"openid" => $openid,
"content" => $content,
"time" => strval(microtime())
);
$json = json_encode($value); // 把用户的弹幕内容存进队列中
$result = $this->lpush(BARRAGE_KEY, $json); return $result?$json:false;
}
(原本已经调了用户接口,打算搞抽奖的,但我没有搞企业服务号,所以后面就去掉了这一部分了,就是用fromUser这个openID去获取用户nickname,headurl等信息)
2、好了,存好的弹幕信息,就差本地去拿了,获取弹幕信息的方式影响到整个程序能否成功运行,这里我想到的两个方案不知孰优孰劣,唯有一试。
首先尝试定时获取,写一个js定时器去请求远程服务器,进而拉取弹幕信息。方法甫一运行,本地就卡的不要不要的,轮播图也变成了幻灯片,毋论接收弹幕了。另外,这里还会有浏览器跨域的问题存在。
然后,查资料得知,redis本身是依赖于socket运行的,还有自带现成发布订阅功能(publish和subscribe),跟我的需求完美契合。所以我重点写好建立连接和接收数据的回调就好了。
建立连接的代码(这个我为了方便,是用php指令来运行脚本的):
/**
* [pullBarrages 拉取腾讯云中最新的弹幕]
*/
public function pullBarrages() {
try {
set_time_limit(0);
ini_set("default_socket_timeout", -1);
ignore_user_abort(TRUE);
// 首先同步一次弹幕
$this->synchronizeBarrages();
// 订阅新的弹幕频道并保存
$this->subscribe(array(BARRAGE_CHANNEL), array($this, "saveBarrage"));
} catch (Exception $e) {
// 连接超时出现异常时重新建立长连接
$host = "IP";
$port = ;
$this->redis = new RedisCache();
$this->redis->connect($host, $port);
// 检查同步远程主机的弹幕同步情况
$this->synchronizeBarrages();
// 重新调用长连接订阅方法
$this->pullBarrages();
}
}
这里我写了一段监听异常的代码,因为连接之后过了大概60秒就自动断开,所以我捕捉到异常就重新建立连接并且确认是否有没有拉取到的弹幕信息。不清楚是PHP对socket的支持不太好还是我的PHP环境的原因(我的PHP用的是集成环境),这里我没有太多时间去深究,如果有知道的大牛请告诉我,谢谢~
接收到数据之后的回调函数:
/**
* [saveBarrages description]
* @param object $redis redis对象
* @param string $channel 订阅的频道
* @param string $barrage 频道订阅返回的弹幕信息
* @return Boolean 存储结果
*/
public function saveBarrage($redis, $channel, $barrage) {
$localRedis = new RedisCache();
$localRedis->connect("127.0.0.1", 6379); $result = $localRedis->lpush(BARRAGE_KEY, $barrage);
if ($result) {
echo "barrage save success!" . PHP_EOL;
}else {
echo "barrage save fail!" . PHP_EOL;
}
echo date("Y-m-d H:i:s") . PHP_EOL;
}
本地拿到了服务器的弹幕信息,剩下的就随便怎么玩都可以了,拿到弹幕信息大概是秒达的感觉。前端浏览器现在也是有websocket,但是我不会用,所以选择了在浏览器设置一个定时器去请求本地环境的弹幕数据,间隔自己定就可以了(关于前端的东西不细讲,后端做前端的诀窍就是找插件,哈哈)。
还有一点,就是我为了方便写代码,把redis对象省略了,用到了__call方法来调用,这个在我之前的博客中提到过。
断断续续的完成这篇博客,以上写的可能有点乱,抱歉。这次就分享这么多,下次有其他东西再来分享~~
2017.12.04编辑:
关于链接被断开,通过捕捉异常来重新连接redis的部分找到了比较好的解决办法了,自动断开连接是因为redis的subscribe方默认在60s内没有接收到信息的话,就会自动断开,只需要添加一行代码:
$redis->setOption(Redis::OPT_READ_TIMEOUT, -1);
让redis不超时就可以了。
利用redis自制幻灯片弹幕的更多相关文章
- 利用Redis解决Url过长的问题
做网站,接手别人的代码,发现url有时候会过长导致页面直接翻掉. 后来想了一下可以利用redis将太长的地方暂存,加载页面时获取即可. 存Redis: /// <summary> /// ...
- 利用Redis cache优化app查询速度实践
注意:本篇文章译自speeding up existing app with a redis cache,如需要转载请注明出处. 发现问题 在应用解决方法之前,我们需要对我们面对的问题有一个清晰的认识 ...
- [翻译]利用REDIS来搭建可靠分布式锁的提议
本系列都是翻译REDIS作者的博文 另外加上我自己的一点点理解 希望有问题大家一起讨论 http://antirez.com/news/77 原文地址 在利用REDIS做分布式锁时基本持有2种观点 ...
- 利用redis写webshell
redis和mongodb我之所见 最近自己在做一些个人的小创作.小项目,其中用到了mongodb和redis,最初可能对这二者没有深入的认识.都是所谓的“非关系型数据库”,有什么区别么? 实际上,在 ...
- 如何利用redis来进行分布式集群系统的限流设计
在很多高并发请求的情况下,我们经常需要对系统进行限流,而且需要对应用集群进行全局的限流,那么我们如何类实现呢. 我们可以利用redis的缓存来进行实现,并且结合mysql数据库一起,先来看一个流程图. ...
- 利用redis实现分布式锁知识点总结及相关改进
利用redis实现分布式锁知识点总结及相关改进 先上原文,本文只为总结及对相关内容的质疑并提出若干意见,原文内容更详细https://www.cnblogs.com/linjiqin/p/800383 ...
- 利用redis实现分布式锁
分布式锁一般有三种实现方式: 1. 数据库乐观锁: 2. 基于ZooKeeper的分布式锁: 3. 基于Redis的分布式锁: 这里大概说一下三种方式的优缺点,数据库乐观锁优点是实现简单,只需要for ...
- 利用Redis发布订阅完成tomcat集群下的消息通知
以下为个人想法,如果有说的不对的地方请各位大佬见谅! 这是博主的第一篇博客,可能排版以及一些描述有不合理的地方还请勿喷,希望大家尽可能的多给我这样的新人一些鼓励让我能在写博客的道路上走下去. 进入正题 ...
- Watchdogs利用Redis实施大规模挖矿,常见数据库蠕虫如何破?
背景 2月20日17时许,阿里云安全监测到一起大规模挖矿事件,判断为Watchdogs蠕虫导致,并在第一时间进行了应急处置. 该蠕虫短时间内即造成大量Linux主机沦陷,一方面是利用Redis未授权访 ...
随机推荐
- JAVA之旅(十四)——静态同步函数的锁是class对象,多线程的单例设计模式,死锁,线程中的通讯以及通讯所带来的安全隐患,等待唤醒机制
JAVA之旅(十四)--静态同步函数的锁是class对象,多线程的单例设计模式,死锁,线程中的通讯以及通讯所带来的安全隐患,等待唤醒机制 JAVA之旅,一路有你,加油! 一.静态同步函数的锁是clas ...
- Gradle 1.12 翻译——第九章 Groovy快速入门
由于时间关系,没办法同时做笔记和翻译,关于Gradle的用户指南,本博客不再做相关笔记,而只对未翻译章节进行翻译并在此发表. 有关其他已翻译的章节请关注Github上的项目:https://githu ...
- μC/OS-II与RT-Thread对比——任务调度
在任务调度器的实现上,μC/OS-II和RT-Thread都采用了位图调度(bitmap scheduling),任务优先级的值越小则代表具有越高的优先级,主要区别在于实现形式,是采用多 ...
- Unity UGUI图文混排源码(二)
Unity UGUI图文混排源码(一):http://blog.csdn.net/qq992817263/article/details/51112304 Unity UGUI图文混排源码(二):ht ...
- DFS迷宫递归所有路径 新手入门
这篇文章写给自己以后复习和个个入门朋友:提示同学们一定耐心看完解释 哪怕看得很难受,我是新手我懂大家的心烦.看完后慢慢体会代码 我们假设迷宫为如下状况: {0,0,1,0} ...
- 三层登录实例VB.NET版详解---理论加实战篇
层,百度百科这样解释,首先-重叠起来的东西:重叠起来的东西中的一部分:层次|表层|大气层.其次-重叠:重复:层峦叠嶂|层出不穷.最后-量词,用于可以分出层次的事物,女孩儿强烈的第六感,三层中的层一定是 ...
- 02_JNI中Java代码调用C代码,Android中使用log库打印日志,javah命令的使用,Android.mk文件的编写,交叉编译
1 编写以下案例(下面的三个按钮都调用了底层的C语言): 项目案例的代码结构如下: 2 编写DataProvider的代码: package com.example.ndkpassdata; ...
- C# FTPClient--FTP操作帮助类,上传下载,文件,目录操作
FROM :http://www.sufeinet.com/forum.php?mod=viewthread&tid=1736&extra=page%3D1%26filter%3Dty ...
- 网站开发进阶(十)如何将一个html页面嵌套在另一个页面中
如何将一个html页面嵌套在另一个页面中 1.IFrame引入 <IFRAME NAME="content_frame" width=100% height=30 margi ...
- CImage 对话框初始化时候显示透明 PNG
使用CImage的时候,发现显示出来的并不是透明背景的图片,而是白色背景的图片. 后发现原因如下: PNG图片的透明背景总是一片白色,后来才发现这其实是微软GDI+的设计问题,PNG图片是ARGB,使 ...