range

If there were you, the world would be just right

应用场景1:在很多时候,我们会把数据库中查出来的数据存入缓存,当缓存失效时,再从数据库中取出数据并重新添加到缓存中。但是如果这时并发量很大时,会有很多进程同时去数据库取数据,很多请求穿透到数据库,最终导致数据库崩溃

<?php
    $data = $cache->get('key');
    if(!$data){
        $fp = fopen('lock.txt',"w+");
        if(flock($fp, LOCK_EX)){
            $data = $cache->get('key');//拿到锁后再次检查缓存,这时可能已经有了
            if(!$data){
                $data = mysql->query();
                $cache->set('key', $data);
            }
            flock($fp, LOCK_UN);
        }
        fclose($fp);
    }

应用场景2:准点抢游戏皮肤,我们的代码是以下这种情况:

<?php
    $count = 检查数据库中的库存量
    if($count > 0){
        生成订单,皮肤库存减一
    }

在正常情况下,上面的这个demo是没有任何问题的,但是当大并发产生时,在执行数据库减一之前,库存只剩下1个时,用户1查到库存>0,用户2这个时候也查到库存>0...,后面的代码继续执行时,库存就会出现负数。

解决方案:

  1. 用额外的单进程处理一个队列,下单请求放到队列里,一个个处理,就不会有并发的问题了,但是要额外的后台进程以及延迟问题,不予考虑。
  2. 借助文件锁,如果锁定失败说明有其他订单正在处理,此时要么等待要么直接提示用户"服务器繁忙"

文件锁: (非阻塞【不等待】模式)

<?php
    $fp = fopen("lock.txt", "w+");
    if(flock($fp,LOCK_EX | LOCK_NB)){
      //..处理订单
      flock($fp,LOCK_UN);
    }else{
      echo "系统繁忙,请稍后再试";
    }

    fclose($fp);

文件锁: (阻塞【等待】模式)

<?php
    $fp = fopen("lock.txt", "w+");
    if(flock($fp,LOCK_EX)){
      //..处理订单
      flock($fp,LOCK_UN);
    }
    fclose($fp);

处理高并发:https://blog.csdn.net/gaisidewangzhan1/article/details/80186584


1、区别只有在继承中才能体现出来,如果没有任何继承,那么这两者是没有区别的。
2、new self()返回的实例是万年不变的,无论谁去调用,都返回同一个类的实例,而new static()则是由调用者决定的。
例子:

<?
class Father {

    public function NewSelf() {
        return new self();
    }

    public function Newstatic() {
        return new static();
    }
}
class Sun extends Father {

}
$sun = new Sun();

print get_class($sun->NewSelf());     //=> 返回的是Father类
print get_class($sun->Newstatic());  //=> 返回的是sun类  

1.查看 日志是否开启

mysql> show variables like 'log_%'; 

2.查看所有binlog日志列表

mysql> show master logs;

3.查看指定binlog文件的内容

mysql> show binlog events in 'mysql-bin.000002';