[原] SQL 查询优化,子查询

场景

假设表 table_snapshot 表 为一个电商系统库存的快照表,里面有 goods_id,num,time 等字段。快照数据大约为50W。其中 goods_id 字段,其上未加索弓丨,不同的goods_id有大约3000个。 

要求

指定了 250个goods_id,要求判断其中多少个在 table_snapshot 表中出现过。 

Continue reading

MySQL | wwpeng | | (0) |

[原] PHP 踩坑实战第二坑:empty

    最近在同事在实践中踩到的一个 empty 坑。关于 empty 的判断类型,就不赘述了,网上解释有很多。例如:0, ”, false, null 等都会被判定为 true。

    这次的坑是 empty 对于对象私有属性的判断。我们来直接上代码:

     Continue reading

PHP | wwpeng | | (0) |

[原] MySQL 如何让一个字段的值不能被减为负数

当用数据库存储一个数值,并且这个数值需要被增减的时候,比如物品的数量。

在这种场景下,物品的数量是不能为负数的。那如何确保在扣减这个数量的时候,不会被扣成负数呢。

假设表数据如下: 

sku num
a 10
b 20

假设现在 a 的 num 要 减少10个。

用程序在操作之前判断? num 是否足够扣减 ? 这明显是不靠谱的。因为有并发的情况存在。

在并发的情况下,a 的 num 会变成 -10 当然,前提你的 sql 是这么写的:

UPDATE table SET num=num-10 WHERE sku="a"

绝对不能用程序去计算 num 的值,在赋值到 sql 中,在并发情况下  num 会变成 0,错误示例:

$data = 'select * from table where sku="a"';
$num = $data['num'] - 10;
UPDATE table SET num=$num WHERE sku="a"

Continue reading

MySQL | wwpeng | | (0) |

[原] PHP 踩坑实战第一坑:双等号

    PHP 的双等号比较,不会比较类型,只会比较值是否相等,但是这第一坑其实是双等号其中非常隐蔽的一个隐式转换。之前遇到过这个问题,找到原因后没太在意,昨天,,就在昨天。。。NND 又掉进去了。。

    首先先看几个实例代码:

<?php
var_dump( 0 == "a" );
var_dump( "0" == "a" );

 请想想这两个比较的返回结果。

Continue reading

PHP | wwpeng | | (0) |

[原]使用算法放大用户点击坐标数据的粒度

    最近在公司昨做了一个关于用户点击行为的各种统计,其中包括最直观的 点击热点图。   样貌如下: 

    

    我是做后端的,前端肯定直接用写好的库,其中用到的生成热点图的类库是 heatmap,详情参看 github。在此感谢作者。

    关于这个heatmap 还是有一些坑的,之后我在写一个关于heatmap的文章。下面介绍另外的一个问题,就是数据量的问题。一个网站的页面用户的点击量是很大的,即使只有一天。因为用户的每一次点击都会被记录下来。这些数据不论存储在关系数据库里面 还是 nosql里面 都是不小的。效率问题很严重。

    如果这个页面被点击了100W次,再除去坐标重复,因为存储的时候会有一个坐标计数,也就是同一个坐标被点击多次,只有一个记录,但是即使这样,数据量依旧很大,将近100W条记录。这在程序里面直接读出来然后交给JS再画到canvas画布上,服务器内存再大也是吃不消的,

    举个栗子:如果PHP被开的memory limit 内存限制是8G的话,也就能取出10-20W条记录,就爆掉了。而且没有大数据字段,字段数据量都不大。

    比如我们当时的记录是 url:xxxx , x_y:100,200 , count 10 , time:xxxxxx 。就是这样一些简单的字段。

    所以解决方案有两种:

Continue reading

Code | wwpeng | | (1) |

[原]子站点不可控的情况下iframe跨域自动适应高度

    关于iframe如何自动适应内部网站的高度,这个 在网上搜出来的千篇一律,都是用js获取内部内容的高度然后重新设置iframe的高度。但是这个方式在非跨域的情况下完全没有问题。只是跨域的时候,js是不能获得内部内容的高度的,什么都获取不到。

    很多的跨域解决方案都需要内部子站点做出动作,主动发起通知父站点的iframe。但是还有一种很棘手的情况,就是你对于子站点完全没有权限,或者,也不想为了这个事情,再去做一个通知这样的功能。

    所以,就只能自己动手满足自己的需求了。

    这里的方案的主要思路是:把跨域的转换成非跨域的

    我再本地项目中做一个页面专门用来对url对应网站的内容进行转发。

    a.php?url=www.baidu.com

<?php
echo file_get_contents('http://'.$_GET['url']);
?>

     这样的话,只需要将当前站点的 a.php?url=www.baidu.com 放在iframe当中就可以了,内部的css,js,图片等资源还是用的原来的远程地址,但是加载这些东西不会存在跨域问题,最重要的是这样我们就可以随意的用js去获取内部内容的高度了,然后再设置外部iframe的高度。

    唯一的弊端是:如果这个网站中又大量ajax加载的内容的话,就不适用这个方案,当然,jsonp的话是没关系的。

    因为如果页面中得内容是ajax加载进来的话,因为把页面转发到了本地网站,所以ajax会存在跨域请求不成功的问题,内容自然也就加载不出来了。

    所以,都是有缺点的,所以根据具体情况具体确定方案吧。

    

PS:我找过CSS的解决方案,但是没找到,不好使。有没有前端大神。知道可行的CSS解决方案???

Code | wwpeng | | (0) |

[原]关于高并发下限流用户访问

    在高并发大流量下总是有一些意想不到或者考虑不周全的事情发生。而一个网站首先是保证能够提供服务,哪怕分流或者降低速度(不得已情况下)。这就需要有一套限流的方案,在不得已的情况下启用,防止服务器停止服务。就好比小米商城抢小米时候的排队,其实就是类似的。这里我们向讨论一些简单的方案思路。

   方案1:

    直接按照用户访问数量的百分比进行限制。比如要举行大的促销。预计并发访问量是 15W,集群服务器平均打到每台机器上的并发访问量是 500,而单台机器的最大承受并发400,这时候只要限制20%的流量就可以了。(这些数据都是粗糙的举例,不要较真啊。)

    但是这种方案明显有一个弊端就是你判断不出来,当前的访问量是否需要启用限流,以为这样的限流都是针对某次大规模请求,有预估,促销之前,代码启用,促销之后,流量下降,代码就要下线。很是麻烦和不好评估统计。

   方案2:

    首先我们可以确定,一台机器的承受能力一般是固定的,可以测试出来的。如果我们能涉及一种计数机制,当QPS达到机器极限的时候限制,就可可以了。

    另外设计这种计数机制不能同步进行,也就是不能加锁,因为同步计数的话,会导致另外的进程等待。。这明显不符合初衷。比如说,我试过用memcache计数,但是很明显,链接memcache然后计数是一个同步过程,最后计数倒是一个都不差,但是很慢。但是不加锁并发惊醒的话就会导致有误差,也就是说多个进程取到同一个值,这个其实我们可以在测试过程中获得一个这种情况出现的概率。然后只要概率在接收范围之内就可以了。所以宗上,PHP的无锁共享内存就是一个可以考虑的方式。

    这里先说一下结果。

    在我自己的机器上,PHP5.4+nginx 四核 i5 nginx进程数4 模拟并发请求 200 限制用户数 100,超过计数的用户会跳转到一个等待页面。

    在这种情况下,实际数据是 进入的用户回进入 100-110左右。也就是说 会上浮 5%-10% (不过我觉得线上服务器CPU多达20多个核心,进程数也多很多,所以误差可能会更大一些

    下面看说一下实现方式:

    在共享内存当中存两个字段,一个字段用来计数,另一个字段用来计时,每一秒中,计数器从0开始重新计,如果超过预设值,就 跳出,否则进入。

    注意:PHP共享内存有两种方式,一种是 shmop系列,还有一种是 shm_attach 系列,这两种都可以完成共享内存的操作,具体区别。。请自行补脑。。我这里使用的是 shmop。 Continue reading

Code Server | wwpeng | | (0) |

[原]RecursiveDirectoryIterator 递归目录迭代器

    PHP5开始支持了接口, 并且内置了Iterator接口, 所以如果你定义了一个类,并实现了Iterator接口,那么你的这个类对象就是ZEND_ITER_OBJECT,否则就是ZEND_ITER_PLAIN_OBJECT. 

    对于ZEND_ITER_PLAIN_OBJECT的类,foreach会通过HASH_OF获取该对象的默认属性数组,然后对该数组进行foreach.

    以上是PHP迭代器的一些描述。这里我们主要来看以下 RecursiveDirectoryIterator 这个迭代器的作用,这个东西其实还是比较有用的只是容易被大家忽略。他的主要作用就是实现递归目录扫描,返回目录中的内容。很多人一想到要扫描目录 然后就google一下,然后国内的文章基本都是粘来粘去,都一样的,用 dir  read scandir 之类的循环,并不是说不行或者不好,只是PHP给我们提供了一个更方便的方式。

    那就是 RecursiveDirectoryIterator 和 RecursiveIteratorIterator 了。他们同属于 SPL 的迭代器范围。

SPL,PHP 标准库(Standard PHP Library) ,此从 PHP 5.0 起内置的组件和接口,并且从 PHP5.3 已逐渐的成熟。SPL 其实在所有的 PHP5 开发环境中被内置,同时无需任何设置。SPL 还提供了其他非常多的迭代器  详见: 文档

    OK,我们继续回到扫描目录的问题。其实非常简单只是大家都不知道而已,没啥高深的东西,做个示例就OK了。

Continue reading

PHP | wwpeng | | (0) |

[原]PHP服务器端上传参数限制

1.首先我们先看最常见的配置选项,php.ini 中的配置

upload_max_filesize “2M” PHP_INI_PERDIR 在 PHP <= 4.2.3 时是 PHP_INI_ALL。 

post_max_size “8M” PHP_INI_PERDIR 在 PHP <= 4.2.3 时是PHP_INI_SYSTEM。从 PHP 4.0.3 起可用。

upload_max_filesize 配置的是 上传的文件的大小限制 默认值2M.

post_max_size 配置的是 post的请求做提交的内容的最大限制,默认值8M

这也就是我们最常见的想要上传更大的文件需要修改的配置参数。post_max_size 理论上应该比 upload_max_filesize 大,因为文件上传包含在post请求当中。

2.关于.htaccess文件中的配置选项

php_value upload_max_filesize 50M  #上传文件大小限制 默认 2M

php_value post_max_size 100M         #POST 提交数据的大小限制 默认8M

.htaccess 文件配置生效的前提条件是 该站点的虚拟主机中 配置了:AllowOverride All

3.关于HTML tag中对上传文件的大小限制:

<input type=”hidden” name=”MAX_FILE_SIZE” value=”100″ />

Continue reading

PHP | wwpeng | | (0) |

[原]PHP GD库静态图片格式转换

近期自己一直做的一个图片分享类别的网站,对于上传之后的图片处理转换的一些东西记录分享一下。

PS:目前有很多三方云服务提供图片云,这就不需要我们自己来处理了,他们的方案更好而且还有各种CDN,个人预算能省则省,自己动手丰衣足食,如果是公司项目访问量过大,还是用云服务吧,自己转换挺费资源的。

1.分析

    静态图片的格式一般的我们允许 png,bmp,jpeg虽然gif也可以是静态的但是我把它统一放到动态里面了,因为一旦gif是动态的转换之后就不会再动了,会只保留第一帧,我们暂不讨论他的处理。我总是觉得服务器上放那么多格式的图片很蛋疼,我们还要自己区分,所以我就想用户上传图片上来之后 统一全部都转换成jpeg格式的图片。

2.实现

    一般的我们上传图片都是要做对应的处理的,不管是要压缩缩略图还是添加水印等等操作,我们都需要将图片文件转为内存资源处理。

    GD库已经给我们提供了函数 imagecreatefrompng,imagecreatefromjpeg,imagecreatefromgif,imagecreatefromwbmp给函数一个绝对路径就可以将读入图片资源, Continue reading

PHP | wwpeng | | (1) |