php综合应用

一、如果要求每隔5分钟执行一次脚本five.php,如何实现?

用到的函数ignore_user_abort(),set_time_limit(),sleep($interval),此代码只要运行一次后关闭浏览器就可以了


二、假设给你五台服务器,请大致的描述一下,如何使用你熟悉的开源软件,搭建一个日pv300万左右的中型网站

3台web服务器,两台mysql数据库服务器,采用master/slave同步的方式减轻数据库负载,web服务器可以结合memcache缓存来减少负载,同时三台web服务器内容一致,可以采用DNS轮询的方式来进行负载平衡

master db意思是主数据库,一般负责数据的写入,slave db是从数据库,主数据库会把写入的数据复制到从数据库。这样读数据库的操作就可以从从数据库读了。即传说中的读写分离。

dns负载均衡是指:在dns中为多个地址配置同一个名字,因而查询这个名字的客户机得到其中一个地址,从而使得不同客户访问不同的服务器,达到负载均衡的目的。


三、memcache主要工作原理

memcache是把所有的数据保存到内存中,采用hash表的方式,每条数据由key和value组成,每个key是独一无二的,当要访问某个值的时候先按照key,然后返回结果,memchache采用LRU算法来逐渐把过期数据清除掉。

memcached主要作用是为减轻大访问量对数据库的冲击,所以一般的逻辑是首先从memcached中读取数据,如果没有就从数据库中读取数据 写入到memcache中,等下一次读取的时候就可以从memcache中读取了,但是在项目中的具体应用策略(也就是那些数据应该缓存?怎么样缓存,)就是个问题。他的一个总原则是讲经常需要从数据库读取的数据缓存在memcache中,这些数据分为几类:

1、经常被读取并且实时性要求不强可以等到自动过期的数据。例如网站首页最新文章列表,某某排行榜等数据。也就是虽然新数据产生了,但对用户体验不会产生任何影响的场景。这类数据就是用典型的缓存策略,设置一个合理的过期时间,当数据过期以后再从数据库中读取。

2、经常被读取并且实时性要求强的数据。比如订单详情,用户订单列表,这些数据首先被载入到memcache中,当发生更改(添加,删除,修改)时,就消除缓存。在缓存的时候,我们将查询的sql语句md5()得到他的hash值作为key,结果数组作为值写入memcache,并且将该sql设计的表名以及hash值配对存入memcache中,当更改了这个表时,我就将与此表想配对的key的缓存全部删除。


问题来了:其实用这个原理,同时我们还能解决另一个问题,当有黑客想注入我的网站时,通过一个订单详情orderid,这时我能做的事情就是,当app调用我的接口,我将返回值md5()得到他的hash值,将对应的orderid作为key,hash值作为value,通过key来判断value值是否匹配


四、操作系统中的线程和进程的区别

进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位。

线程是进程的一个实体是cpu调度和分派的基本单位,他是比进程更小的能独立运行基本单位。

进程和线程的主要差别在于它们是不同的操作系统资源管理方式。进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其他进程产生影响,而线程只是一个进程中的不同执行路径。线程有自己的堆栈和局部变量,但线程之间没有独立的地址空间,一个线程死掉就等于整个进程死掉,所以多进程的程序比多线程的程序健壮,但在进程切换时,耗费资源较大,效率差一些。但对于一些要求同时进行并且又要共享某些变量的并发操作只能用线程,不能用进程。


五、列举web开发中的安全性问题

sql注入攻击:用户可以提交一段数据库查询代码,根据程序返回的结果,获得某些他想得知的数据。从正常的WWW端口访问,而且表面看起来跟一般的Web页面访问

防止SQL注入攻击

防止SQL注入攻击

没什么区别,所以市面的 防火墙 都不会对SQL注入发出警报,如果 管理员 没查看ⅡS日志的习惯,可能被入侵很长时间都不会发觉

数据库操作安全,update,delete,insert的操作没有限制用户操作权限,是一件很危险的事情

没有验证用户http请求的方式post或者get,get请求被合法通过

没有验证表单来源的唯一性,不能识别是合法的表单提交还是黑客伪造的表单提交


六,memcache跟redis的区别


七、memcache缓存处理缓存的两种方案

1) 第一种,最常见的方式 读取数据的主要步骤如下:

       1)先从缓存中获取数据(如果在缓存中获取到,则直接返回已获取的数据)

        2)如果获取不到,再从数据库里面读取相应的数据

        3)  把获取到的数据加入缓存中

注意:这种方式是在Model层,也就是业务处理层加入的。

      实例代码如下:

    public static function getCombatPowerRank()
    {
        $cacheKey = 'Rank:CombatPower';

        // 先从缓存中读取
        if ($list = F('Memcache')->get($cacheKey)) {
            return $list;
        }

        $list = array();

        // 遍历所有用户分库,执行清理
        for ($i = 1; $i <= DIST_USER_DB_NUM; $i++) {
            if ($distList = Dao('Dist_User')->setDs($i)->getCombatPowerTopUsers(self::RANK_LIMIT)) {
                $list = array_merge($list, $distList);
            }
        }

        // 保存到缓存中
        F('Memcache')->set($cacheKey, $list, C('RANK_CACHE_TIME'));

        return $list;
    }

这种方式确实很好理解,有一个弊端就是,所有的缓存都需要手动的加上以上缓存的代码,需要修改函数的内部代码。请注意,我们在项目中加入缓存的时间是项目完成的差不多了,也就是说需要有很多这样的“读取类”函数加入缓存,如果全是以上这种加入缓存方式的话,需要修改很多函数的内部代码,那绝对是一个复杂而容易遗漏的苦力活。如果一不小心,就会出现错误。有没有好的方式可以集中的给某些函数加入这样的缓存系统呢(如果有的话,绝对是一个福音,哈哈)


2)第二种方式 ,在DAO层集中处理。在解释这种方法之前,我先简要说明一下我们的需求,便于更好理解为什么我可以这么做。

 在我们的游戏项目中,有一部分数据时静态资源数据,这种数据时配置好的,不会经常变动,每个用户需要的都一样。例如各种角色类的基础的属性,船只的基础属性等。这类数据涉及到的操作一般是读:把一张表全部读出来,获取根据某个条件读取相应的内容。既然操作单一,我们就直接在DAO层处理这类方法的缓存。做法就是给每一个Dao类里面的函数加入缓存。

        不改变方法的内部代码,却可以给每个方法加入缓存,PHP魔术方法__call()就可以实现,如果对象调用某个方法,而这个方法又不存在,那么就会调用到这个魔术方法了,具体实现代码如下:

    /**
     * 调用魔术方法
     *
     * @param string $method
     * @param mixed $args
     * @return mixed
     */
    public function __call($method, $args)
    {
        if (! method_exists($this, '__CACHE__' . $method)) {

            // 这里是实现数据库链式查询的,这里可以忽略
            return parent::__call($method, $args);
        }

        $cacheKey = md5($this->_dbName . ':' . $this->_tableName . ':' . $method . ':' . serialize($args));

        $data = $this->_cache->get($cacheKey);

        if ($data === false) {
            // 调用类里面的方法
            $data = call_user_func_array(array($this, '__CACHE__' . $method), $args);
            $this->_cache->set($cacheKey, $data);
        }

        return $data;
    }

代码运行机制: 比如说有这样的一个调用关系:Dao('Static_Ship')->get(),但是在Static_Ship这个类中没有get()这个方法,于是程序就会执行__call(),在这个类中,有一个这样的方法__CACHE__get()这样的一个方法,于是我就执行了这个方法,并且把这个函数的数据缓存起来了。这样就达到了我们的目的,不改变函数内部的代码,把函数的结果缓存起来。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值