1.laravel中的设计模式
单例模式 工程模式
class DB{
private static $Instance=null;
private $link;
private function __construct($host,$user,$pwd)
{
$this->link=mysql_connect($host,$user,$pwd);
if(!$this->link){
return false;
}
return $this->link;
}
private function __clone()
{
return false;
}
public function static getInstance($host,$user,$pwd)
{
if(self::$Instance==null){
return self::$Instance=new self($host,$user,$pwd);
}
return self::$Instance;
}
}
2.php常用数组函数
array_chunk() array_diff() list() in_array() sort() array_merge() array_coulmn() array_search()
3.排序
function($arr,$key)
{
for($i=0;$i<count($i)-1;i++){
for($j=0;$j<count($j)-1-$i;$j++){
if($arr[$j][$key]<$arr[$j+1][$key]){
$tmp=$arr[$j+1];
$arr[$j+1]=$arr[$j];
$arr[$j]=$tmp;
}
}
}
return $arr;
}
4.PHP中数组的结构实现
hashtable
5.nginx epoll 和poll
6.数据库的事务隔离级别
mysql事务隔离级别
①读未提交
②读已提交
③可重复读
④串行化
为了解决脏读、不可重复读、幻读 支持程度
7.抽象类和接口的区别
抽象类特点
①顾名思义,它是抽象的,当然也就是不能被实例化。所以,抽象类一般是作为我们的基类来进行定义的
②在一个类中只要有一个方法被定义为抽象的,那么这个类就必须加上abstract关键字成为抽象类
③被定义为抽象的方法只声明其调用方式,不能定义其具体的功能实现
④子类必须定义父类中的所有抽象方法,这些方法的访问控制必须和父类一致或更为宽松
⑤方法的调用方式必须匹配,即类型和所需参数数量必须一致。子类实现的抽象方法可以增加参数但必须有默认值
接口的特点
①可以指定某个类必须实现哪些方法,但不需要定义这些方法的具体内容
②就行定义一个标准的类一样,但其中定义所有的方法都是空的
③接口中定义的所有方法都必须是共有,这是接口的特性
④类中必须实现接口中定义的所有方法,否则会报一个致命错误,类可以实现多个接口用逗号来分隔多个接口名称
⑤类要实现接口,必须使用和接口中所定义的方法完全一致的方式,否则会导致致命错误
⑥接口也可以继承通过extends操作符
⑦接口也可以继承定义常量,接口常量和类常量的使用完全相同,但是不能呗子类或子接口所覆盖
抽象类和接口区别
①抽象类的子类遵循继承原则,只能有一个父类;但一个类可以实现多个接口
②抽象类中可以有非抽象的已经实现的方法;接口中全是抽象方法,都是方法定义
③抽象类中方法和变量的访问控制自己定义;接口中只能是公用的
8.主键索引和唯一索引的区别
①主键索引是一种约束,唯一索引是一种索引,两者在本质上是不同的
②唯一索引可以是多个 主键索引在一个表中只能有一个
③主键索引唯一且不能为空,唯一索引允许空值
9.多态
多态是指 OOP 能够根据使用类的上下文来重新定义或改变类的性质或行为,或者说接口的多种不同的实现方式即为多态
10.cookie和session区别
http是无状态的cookie可以解决记录在客户端状态的问题,cookie会根据从服务端发来的响应报文里的set-cookie首部字段通知客户端去保存cookie,等下一次客户端在向服务端发送请求时客户端会自动再请求报文里加入cookie值,服务端接收到来自客户端的cookie会进行对比从而得到之前的状态信息
cookie安全保护机制是同源策略(三元组name,domin,path)进行判断的,还有httponly和secure属性限制当secure设置为true,cookie就只能在https中传送到服务端,对重要的值会加上httponly,防止恶意获取
cookie禁用怎么使用session
通过url来传送sessionId
设置session.use_trans_sid = 1或者编译时打开打开了--enable-trans-sid选项
这样他会在每个url后面自动加上PHPSESSID的值,然后正常使用session就可以了
session生理周期回收机制
PHP内置了session回收机制
在php.ini中session.gc_maxlifetime为session设置了生存时间(默认为1440s)
如果session文件的最后更新时间到现在超过了生存时间,这个session文件就被认为是过期的了。在下一次session回收的时候就会被删除。那下一次session回收是在什么时候呢?这和php请求次数有关的。在PHP内部机制中,当php被请求了N次后就会有一次触发回收机制。到底是请求多少次触发一次是通过以下两个参数控制的:
session.gc_probability = 1
session.gc_divisor = 100
11.redis
memcache
key 不能超过 250 个字节;
value 不能超过 1M 字节;
key 的最大失效时间是 30 天;
只支持 K-V 结构,不提供持久化和主从同步功能
redis
与 memcache 不同的是,Redis 采用单线程模式处理请求。这样做的原因有 2 个:一个是因为采用了非阻塞的异步事件处理机制;另一个是缓存数据都是内存操作 IO 时间不会太长,单线程可以避免线程上下文切换产生的代价。
Redis 支持持久化,所以 Redis 不仅仅可以用作缓存,也可以用作 NoSQL 数据库。
相比 memcache,Redis 还有一个非常大的优势,就是除了 K-V 之外,还支持多种数据格式,例如 list、set、sorted set、hash 等。
Redis 提供主从同步机制,以及 Cluster 集群部署能力,能够提供高可用服务
reids单线程为什么快?
redis采用单线程模式处理请求。这样做的原因有2个:一个是采用了非阻塞的异步事件处理机制;另一个是缓存数据都是内存io时间不会太长,单线程可以避免线程上下文切换产生的代价
缓存雪崩
缓存雪崩是指缓存中数据大批量到过期时间,而查询数据量巨大,引起数据库压力过大甚至down机。和缓存击穿不同的是, 缓存击穿指并发查同一条数据,缓存雪崩是不同数据都过期了,很多数据都查不到从而查数据库
解决方案
使用快速失败的熔断策略,减少 DB 瞬间压力;
使用主从模式和集群模式来尽量保证缓存服务的高可用
缓存穿透
缓存穿透是指缓存和数据库中都没有的数据,而用户不断发起请求。由于缓存是不命中时被动写的,并且出于容错考虑,如果从存储层查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到存储层去查询,失去了缓存的意义。
在流量大时,可能DB就挂掉了,要是有人利用不存在的key频繁攻击我们的应用,这就是漏洞
解决方案
从缓存取不到的数据,在数据库中也没有取到,这时也可以将key-value对写为key-null,缓存有效时间可以设置短点,如30秒(设置太长会导致正常情况也没法使用)。这样可以防止攻击用户反复用同一个id暴力攻击
缓存击穿
缓存击穿是指缓存中没有但数据库中有的数据(一般是缓存时间到期),这时由于并发用户特别多,同时读缓存没读到数据,又同时去数据库去取数据,引起数据库压力瞬间增大,造成过大压力。
解决方案
1、设置热点数据永远不过期
3、布隆过滤器
4、加互斥锁
持久化
Redis 提供了 RDB 和 AOF 两种持久化方式,RDB 是把内存中的数据集以快照形式写入磁盘,实际操作是通过 fork 子进程执行,采用二进制压缩存储;AOF 是以文本日志的形式记录 Redis 处理的每一个写入或删除操作。
RDB 把整个 Redis 的数据保存在单一文件中,比较适合用来做灾备,但缺点是快照保存完成之前如果宕机,这段时间的数据将会丢失,另外保存快照时可能导致服务短时间不可用。
AOF 对日志文件的写入操作使用的追加模式,有灵活的同步策略,支持每秒同步、每次修改同步和不同步,缺点就是相同规模的数据集,AOF 要大于 RDB,AOF 在运行效率上往往会慢于 RDB。
过期策略和内存淘汰
过期策略
客户端主动给Rediskey设置的过期时间到达过期时间进行删除
惰性删除:key被操作时会检查过期时间不会主动删除 导致冷数据长期存在内存中无法释放占用内存
定期删除:随机检测部分的key,并删除,当过期数据达到25%时候会再次检查
内存淘汰
默认策略 申请内存操作报错
FIFO先进先出 越早过期的key就越早删除
随机删除
LRU最近最少使用的key删除
LFU最不经常使用的key先删除
Nginx
Nginx采用异步非阻塞的方式来处理网络事件
master进程先建好需要listen的socket后,然后再fork出多个woker进程,这样每个work进程都可以去accept这个socket。当一个client连接到来时,所有accept的work进程都会受到通知,但只有一个进程可以accept成功,其它的则会accept失败。Nginx提供了一把共享锁accept_mutex来保证同一时刻只有一个work进程在accept连接,从而解决惊群问题。当一个worker进程accept这个连接后,就开始读取请求,解析请求,处理请求,产生数据后,再返回给客户端,最后才断开连接,这样一个完成的请求就结束了。
PHP浮点计算减少误差
bcmath 还提供了以下方法:
bccomp 比较两个任意精度的数字
bcmod 对一个任意精度数字取模
bcpow 任意精度数字的乘方
bcpowmod 高精度数字乘方求模
bcscale 设置所有bc数学函数的默认小数点保留位数
bcsqrt 任意精度数字的二次方根
PHP array_merge和+
数组相加以数字和字符串为key值都不变 并以前面数组为基准 相同键值会覆盖
数组合并以字符串为key值的不变 并以后面的为基准 相同键值会覆盖
12.线程间如何进行通讯
①线程之间可以通过共享内存或给予网络通信
②如果是通过共享内存来进行通信,则需要考虑并发问题,什么时候阻塞,什么时候唤醒
③像Java中wait(),notify(),就是阻塞和唤醒
④通过网络就比较简单了,通过网络将通信数据发送给对方,当然也要考虑并发问题,处理方式就是加上等方式
13.分布式锁实现
分布式锁解决的问题本质是:能够对分布在多台机器中的线程对共享资源互斥访问,在这个原理上可以有很多的实现方式
①基于mysql,分布式环境中的线程连接同一个数据库,通过数据库中的行锁来达到互斥访问,但是MySQL的加锁和释放锁性能比较低,不适合真正的生产场景
②基于redis,reids中的数据也是在内存,基于redis的消费订阅功能,数据超时时间,lua脚本等功能,也能很好的实现分布式锁
14.redis数据结构和使用场景
①字符串:可以用来做最简单的数据缓存,可以缓存某个简单的字符串,也可以缓存某个json字符串,redis分布式锁的实现就利用这种数据结构,还包括可以实现计数器、session共享、分布式id
②哈希表:可以用来存储key-value对,更适合用来存储对象
③列表:redis的列表通过命令的组合,既可以当做栈又可以当做队列来使用,也可以缓存公众号、微博等消息流数据
④集合:和列表类似,也可以存储多个元素,但不能重复,集合可以进行交集、并集、差集操作,从而可以实现类似,我和某人共同关注的人,朋友圈点赞等功能
⑤有序集合:集合是无序的,有序集合可以设置顺序,可以用来实现排行榜等功能
15.redis集群策略
redis提供了三种集群策略:
①主从模式:这种模式比较简单,主库可以读写,并且和从库进行数据同步,这种模式下,客户端直接连接主库或某个从库,但是主库或从库宕机后,客户端需要手动修改ip,另外,这种模式也比较难以扩容,整个集群所能存储的数据受到某台机器的内存容量,所以不支持特大数据量存储
②哨兵模式:这种模式在主从的基础上新增了哨兵节点,当主库宕机后,哨兵节点会发现主节点宕机,然后从从库选择一个库作为主库,另外哨兵也可以做集群,从而可以保证某一个哨兵节点宕机后,还有其它哨兵节点可以继续工作,这种模式可以比较好的保证redis集群高可用,但是仍然不能解决redis容量上限问题
③cluster模式:cluster模式是用的比较多的模式,它支持多主多从,这种模式按照key进行槽位分配,可以使不同的key分撒到不同的主节点上,利用这种模式可以使整个集群支撑大的容量,同时主节点可以拥有自己多个从节点,如果该节点宕机,会从的从节点选举一个新的主节点
对于这三种模式,如果redis要存的数据量不大,可以选择哨兵模式,如果redis要存的数据量大,并且要持续扩展,那么选择cluster模式
16.B树和B+树
①B树特点:节点排序 一个节点可以存储多个元素,多个元素也排好了顺序
②B+树特点:拥有B树的特点 叶子结点之间有指针 非叶子节点上的元素在叶子节点有冗余,这就是叶子节点中也存储了所有元素,并且排好了顺序
mysql索引使用的是B+树,因为索引是用来加快查询的,而B+树对数据进行排序所以是可以提高查询速度的,然后通过一个节点存储多个元素,从而可以使B+树的节点不会太高,在mysql中一个innodb也就是月给他节点,一个innodb页默认16kb,所以一般情况下一颗两层的B+数可以存储2000万行左右的数据然后通过利用B+树叶子结点存储了数据所有元素并且进行了排序,可以很好的支持全表扫描,范围查找等sql语句
17.poll和epoll
①select模型,使用的是数组存储socket连接文件描述符,容量是固定的,需要通过轮询来判断是否发生了io事件
②poll模型,使用的是链表来存储socket连接文件描述符,容量是不固定的,同样需要通过轮询来判断是否发生了io事件
③epoll模型,epoll和poll模型完全不同,epoll是一种事件通知模型,当发生了io事件,应用程序才进行io操作,不需要向poll那样主动去轮询