利用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内部类_1
使用内部类的原因: (1)可以访问该类定义所在作用域中的数据,包括私有数据. (2)可以对同一个包中的其它类隐藏起来. (3)当想要定义一个回调函数且不想编写大量代码时,使用匿名内部类比较便捷. 下面 ...
- Using mysqldump for Backups(备份还原数据库实例及参数详细说明)
官网mysqldump命令如下: Using mysqldump for Backups https://dev.mysql.com/doc/refman/5.7/en/using-mysqldump ...
- Linux多线程实践(9) --简单线程池的设计与实现
线程池的技术背景 在面向对象编程中,创建和销毁对象是很费时间的,因为创建一个对象要获取内存资源或者其它更多资源.在Java中更是如此,虚拟机将试图跟踪每一个对象,以便能够在对象销毁后进行垃圾回收.所以 ...
- Microsoft Office Excel cannot access the file, There are several possible reasons
今天在做EXCEL打印读取模板时报错了,错误信息如下: Microsoft Excel cannot access the file 'D:\xx.xlsx'. There are several p ...
- Gradle实现的两种简单的多渠道打包方法
本来计划今天发Android的官方技术文档的翻译--<Gradle插件用户指南>的第五章的,不过由于昨天晚上没译完,还差几段落,所以只好推后了. 今天就说一下使用Gradle进行类似友盟这 ...
- 手把手教你画一个 逼格满满圆形水波纹loadingview Android
才没有完结呢o( ̄︶ ̄)n .大家好,这里是番外篇. 拜读了爱哥的博客,又学到不少东西.爱哥曾经说过: 要站在巨人的丁丁上. 那么今天,我们就站在爱哥的丁丁上来学习制作一款自定义view(开个玩笑,爱 ...
- Cocos2d中update与fixedUpdate的区别(三)
没错!现在的情况是很糟糕.因为玩家不会看到平滑的动作. 不管怎样,我们都对此无能为力.玩家期待在1秒后小球出现在位置(8),所以我们应该把球放在那里. 我们不会讨论如何避免掉帧的情况.对于这个例子我们 ...
- centos6.5 rsync+inotify实现服务器之间文件实时同步
1. rsync的优点与不足 与传统的cp.tar备份方式相比,rsync具有安全性高.备份迅速.支持增量备份等优点,通过rsync可以解决对实时性要求不高的数据备份需求,例如定期的备份文件服务器数据 ...
- OAF开发概念和案例总结(项目总结)
留看: 网上关于OAF学习的资料比较少,最近有些时间,整理了下自己在项目上的经验总结和同学们一下共享一下 和学友一起讨论一下OAF开发,还有两个比较复杂的系列正在整理中..... 一.OAF EO定义 ...
- Java进阶(十二)JDK版本错误之Unsupported major.minor version 51.0(jdk版本错误)
错误:Unsupported major.minor version 51.0(jdk版本错误) 如果在win7下开发项目是使用的jdk版本和项目运行服务器jdk版本不同就会出现上面的问题. 用jdk ...