浅析php如何实现App常用的秒发功能

前言

想象一下,我们平常发朋友圈的时候,N张图片配上文字,嗖的一下就发出去了,不带任何拖泥带水的那种,体验感觉好爽~。

但是我们停下来用技术手段思考一下,这可能吗?有些2G网络最多也就几十K网速,我们的图片随便一张都几M,即使压缩过也有几百K,怎么可能瞬间发出消息呢?

现在想想,是不是有些诡异呢~

其实吧,众多社交软件(微博,微信)都是用了一种秒发机制。他并不是真的先去发送然后发送完毕再告诉你发送成功,而是直接告诉你发送成功,然后后台再偷偷去上传你发的东西,所以在网速不好的时候我们会经常发现一个现象,刚开始发出的朋友圈刚开始很正常,但是过了几分钟后,提示我们发送失败!这很很尴尬啊,明明刚开始你什么也没说啊,到了最关键的时候你告诉我不行了..

不要被高大上的技术吓到了,无非就是做了一些小技巧而已,真的很基础,但是也真的很实用。

在讨论技术前首先声明一些初始条件。

1.对数据库表结构进行了一些特殊改造: 朋友圈内容表有一个特殊的字段status, status值有两种情况,值可以为1或者2,
值为1是朋友圈未发布。 值为2是朋友圈已发布。 (暂时看不懂为什么这样做的同学,可以先继续阅读,后面会讲解)

2.此篇文章的秒发功能指的有图片的情况下使用,因为有图片的话,图片上传太慢,所以需要采用秒发机制,但是没有图片纯文字的话,就没太大的必要了,因为文本传输量很低,按照正常流程发送即可。

3.此篇文章的代码是基于PhalApi框架,语法都比较简单,有过ORM操作经验的同学应该都看得懂

4.此篇文章主要讲解APP的秒发功能,WEB端不是特别需要这个功能,因为现代网络足以我们的PC一次性发送很多很多张图片(10M/s,20M/s)

大方向讨论一下整个执行流程:

客户端调用发布API,服务端进行发布内容(publish.php),如果是有图片,那么客户端还要额外调用一个上传API(upload.php),在这个上传API(upload.php)还没完成工作的时候,客户端会直接告诉你发布成功(其实当前是没有上传完成,后面有一个进程在拼命帮你上传着呢),然后客户端会把你发的文字和图片暂时拼接好显示给你看(当前只有你能看到,你朋友圈其他人是看不到的),然后等待着上传API(upload.php)的结果/当然也可能上传超时(通常一分钟内会出结果),如果成功的话则顺利上传,失败的话则报发送失败,但是在等待结果的一分钟之内,他会先让你觉得你已经发送了,除非上传失败,才会在后来提醒你。

那么让我们在技术层面来分析一下这套机制吧:

当我们点上右上角的发送键后,有两个进程在同时启动,其中一个进程是帮你上传文本并且告诉你已经发送成功啦(publish.php),另外一个进程是偷偷去上传你发的图片(upload.php),具体代码如下:

Publish.php

<?php

//正常获取数据(文本,图片,位置信息等)

…

Code …

Code …

//进行判断,如果有图片则为未发布(status为1),无图片则为立即发布(status为2)

//如果有图片则通过返回标识符告诉客户端,让他赶紧去调用真实的上传逻辑upload.php,我们这只把最基本的文本上传好,再设置多一个status而已~

$status = ($pic_num > 0) ? 1 : 2;

//拼接入库数据

$where_data = array( "status"=> $status)

//数据入库

DI()->notorm-> friends ->insert($where_data);

?>

看出玄妙了吗?我们对入库的status字段进行了一次判断,分别会有1(未发布)和2(已发布)两种情况,那么在读取数据的时候我们应该怎么做呢(list.php)?

那么展示页面就是这样:

Lists.php

<?php

//code ..

//获取文字信息

Code..

//获取图片信息
//(它在获取当前用户pic表内的f_id(即获取朋友圈图片),最关键的地方是where条件
$data= DI()->notorm->pic->select('f_id')->where("status > 1 OR (status = 1 && u_id = {$u_id})")->->fetchAll();

//code ..

?>

此处的where条件是秒发机制的最关键的地方:

status大于1(已发表)或者等于1(未发布),(tipsstatus在有图片的情况下默认值为1)但是属于当前用户发布的内容,都可以读出来,这就有一个很奇妙的现象,就是无论如何,我们自己发的朋友圈,自己永远是可以读出来的,但是其他人就不一定了(因为如果有图片的话,还需要去调用另外一个进程上传图片,然后在那个进程将status改为2)

那么还有最后一个关键点,就是负责上传图片的那个进程(upload.php),这个是真实上传图片的逻辑,

有几张图片,这么upload.php就会被调用几次

每次上传成功后将图片行的字段status改成2

upload.php

<?php

//Code..

//把图片上传到服务器目录

//获取长传结果标识,更改状态

If(上传成功){

//将status改回2

$status_data = array("status" => 2);

DI()->notorm->pic->select('u_id')->where('u_id, $u_id)-->update($status_data);

}else{

Code…

}

经过以上的几个操作(首先是publish.php,如果有图片上传的话则调用upload.php,展示的时候是list.php)。

不知道大家看出门道没有,和我们平常写的发布功能不同的是,上传upload.php功能被独立出来了,改装后的发布publish.php会用最快的速度将你的文本内容存进数据库,并且如果有图片内容的话,他会单独调用上传API upload.php

最关键的是在显示的时候做了一些小技巧,让自己保证可以看到自己发的东西。

好了,以上就是本文的全部内容了,希望对大家学习PHP有所帮助,也请大家继续关注我们。

(0)

相关推荐

  • php结合redis实现高并发下的抢购、秒杀功能的实例

    抢购.秒杀是如今很常见的一个应用场景,主要需要解决的问题有两个: 1 高并发对数据库产生的压力 2 竞争状态下如何解决库存的正确减少("超卖"问题) 对于第一个问题,已经很容易想到用缓存来处理抢购,避免直接操作数据库,例如使用Redis. 重点在于第二个问题 常规写法: 查询出对应商品的库存,看是否大于0,然后执行生成订单等操作,但是在判断库存是否大于0处,如果在高并发下就会有问题,导致库存量出现负数 <?php $conn=mysql_connect("localho

  • php实现倒计时效果

    现在很多的团购网站上都有剩余时间的显示.显示剩余时间可以使用Javascript来实现,但是我们会发现使用Javascript来实现的话不安全,因为Javascript获取的是客户端的时间.比方说,这次团购已经结束了,但是懂技术的访客只要修改他客户端电脑的时间就又显示该商品还可以购买.很明显,这不是我们网站设计的初衷.团购结束了就不可以再购买啦.这里写了一个考试系统剩余时间倒计时的显示代码和大家一起探讨. 实现原理: PHP获取的是服务器端的时间,我们只要设置考试的开始时间和结束时间及当前时间.

  • php获取当前时间的毫秒数的方法

    php本身没有提供返回毫秒数的函数,但提供了一个microtime()函数,该函数返回一个array,包含两个元素,一个是秒数,一个是小数表示的毫秒数,借助此函数,可以很容易定义一个返回毫秒数的函数,例如: 复制代码 代码如下: function getMillisecond() { list($s1, $s2) = explode(' ', microtime()); return (float)sprintf('%.0f', (floatval($s1) + floatval($s2)) *

  • PHP+JS实现的商品秒杀倒计时用法示例

    本文实例讲述了PHP+JS实现的商品秒杀倒计时用法.分享给大家供大家参考,具体如下: <?php //php的时间是以秒算.js的时间以毫秒算 date_default_timezone_set('PRC'); //date_default_timezone_set("Asia/Hong_Kong");//地区 //配置每天的活动时间段 $starttimestr = "2016-3-29 8:10:00"; $endtimestr = "2016-

  • PHP获取指定时间段之间的 年,月,天,时,分,秒

    核心代码: Class Utils { /** * format MySQL DateTime (YYYY-MM-DD hh:mm:ss) 把mysql中查找出来的数据格式转换成时间秒数 * @param string $datetime */ public function fmDatetime($datetime) { $year = substr($datetime,0,4); $month = substr($datetime,5,2); $day = substr($datetime,

  • php 计算两个时间相差的天数、小时数、分钟数、秒数详解及实例代码

    php计算两个时间相差的天数.小时数.分钟数.秒数 PHP中计算两个时间相差的天数.小时数.分钟数.秒数不如其它语言方便,但搞清了PHP中时间的表示方法后也很简单.本文章向大家讲解php如何计算时间相差.需要的码农可以参考一下. 先看下面这个网上给的例子: //$startdate是开始时间,$enddate是结束时间 <?php $startdate="2011-3-15 11:50:00"; $enddate="2012-12-12 12:12:12";

  • PHP 类商品秒杀计时实现代码

    要求要有小时分钟秒的实时倒计时的显示,用户端修改日期时间不会影响到倒计时的正常显示(也就是以服务器时间为准). 其实这和很多的考试等系统的时间限制功能同样的要求. 总不能用ajax每秒都获取服务器时间吧,所以实时倒计时一定要用javascript实现.这很简单,网上一大把的例子. 现在问题是解决用户端修改日期时间对我们的显示的影响. 解决的办法是计算出用户端的时间和服务器的时间差,这样问题的完成解决了. 这样只需要运行一次php,实时倒计时的时间就和服务器的时间同步了. 理论是同步的,但实际测试

  • 时间戳与时间相互转换(php .net精确到毫秒)

    /** 获取当前时间戳,精确到毫秒 */ function microtime_float() { list($usec, $sec) = explode(" ", microtime()); return ((float)$usec + (float)$sec); } /** 格式化时间戳,精确到毫秒,x代表毫秒 */ function microtime_format($tag, $time) { list($usec, $sec) = explode(".",

  • php倒计时出现-0情况的解决方法

    本文实例讲述了php倒计时出现-0情况的解决方法.分享给大家供大家参考,具体如下: 问题:今天有反馈,说倒计时出现了-0天的情况,我看了看程序,卧槽,当时怎么没测试到 原因是PHP的逻辑判断中 -0 > 0 分析:贴出错的代码 $starttime = 1362585600; //3.7凌晨 $nowtime = 1362618921;//3.7早上 $off = ceil(($starttime - $nowtime)/86400); //倒计时 if ($off < 0) { $off =

  • php实时倒计时功能实现方法详解

    本文实例讲述了php实时倒计时功能实现方法.分享给大家供大家参考,具体如下: 这几天公司要做一个限时购物的功能.这就要做到倒计时,要有实时的倒计时. 要求: 1) 要有小时分钟秒的实时倒计时的显示 2)用户端修改日期时间不会影响到倒计时的正常显示(也就是以服务器时间为准) 其实这和很多的考试等系统的时间限制功能同样的要求. 解决思路: 1)总不能用ajax每秒都获取服务器时间吧. 所以实时倒计时一定要用javascript实现.这很简单.网上一大把的例子. 2)现在问题是解决用户端修改日期时间对

  • PHP获取毫秒级时间戳的方法

    本文实例讲述了PHP获取毫秒级时间戳的方法.分享给大家供大家参考.具体分析如下: PHP本身没有提供获取毫秒级时间戳的函数,java里面可以通过gettime();获取.如果是要与java写的某些程序进行高精度的毫秒级的对接通信,则需要使用PHP输出毫秒级的时间.之前我采取的方法是采用不精准的方式,也就是在PHP原生的时间函数后面加上一个三位数字构成.为获取更为精准的毫秒级时间戳可以使用下面的代码: <?php function getMillisecond() { list($t1, $t2)

  • php+js实现倒计时功能

    js部分 复制代码 代码如下: setInterval("time_controller()",1000);function time_controller(){    $(".time_val").each(function(){         var time_id = "time_show_"+$(this).attr('for');         var time_val= $(this).attr('value');        

  • php解决抢购秒杀抽奖等大流量并发入库导致的库存负数的问题

    我们知道数据库处理sql是一条条处理的,假设购买商品的流程是这样的: sql1:查询商品库存 if(库存数量 > 0) { //生成订单... sql2:库存-1 } 当没有并发时,上面的流程看起来是如此完美,假设同时两个人下单,而库存只有1个了,在sql1阶段两个人查询到的库存都是>0的,于是最终都执行了sql2,库存最后变为-1,超售了,要么补库存,要么等用户投诉吧. 解决这个问题比较流行的思路: 1.用额外的单进程处理一个队列,下单请求放到队列里,一个个处理,就不会有并发的问题了,但是要

随机推荐