分类 技术 下的文章

一些面试题 P1

写这玩意的初衷:

刚好写这段文章的时候正在面试,但是面试的时候发现对一些问题回答的不够规范,在此感谢其中一家公司的HR建议,对此重新写一下个人对于面试题的解析.

1.Redis-什么是缓存穿透?

[适用于高速缓存系统回答(也许)]

我们先来描述一下含有Redis时用户访问场景:

有缓存:用户请求-》查询Redis是否有缓存-》有-》从Redis返回数据-》处理数据-》返回用户

无缓存:用户请求-》查询Redis是否有缓存-》无-》请求MYSQL-》处理MYSQL数据-》写入Redis缓存-》-》返回用户

Redis本身就是对于高并发的数据读取来缓解MYSQL 的I/O查询过慢 ,缓存穿透就是当用户访问网站的时候,查询高速缓冲数据库中是否有数据,当太多用户刚好都访问没有中标Redis数据时,就会都去查询持久性数据库(也就MYSQL类型),这会给持久性数据库的造成过大的压力。

简要的说,就是查询一个一定不存在的数据,由于缓存是不命中时需要从数据库查询。这会给持久性数据库的造成过大的压力。

2.Redis-什么是缓存击穿?

而击穿就会有点不同了,这种情况就是有一个很火的Key,例如首页,微博热点什么的,但是刚好Key失效或者太多人Redis直接干崩溃了,那么用户就穿过Redis,全部都去查询持久性数据库,但这个时候本身就是热点Key很容易就会把持久性数据库打到崩溃。这就是击穿

3.针对上述问题如何解决?

缓存穿透

  1. 接口层增加校验,如用户鉴权校验,id做基础校验,id<=0的直接拦截;(因为非法的访问根本就不用理)
  2. 从缓存取不到的数据,在数据库中也没有取到,这时也可以将key-value对写为key-null,缓存有效时间可以设置短点,如30秒(设置太长会导致正常情况也没法使用)。这样可以防止攻击用户反复用同一个id暴力攻击。

缓存击穿

  1. 热点Key直接设置为永远不过期,有数据直接刷新value不用,理过期时间
  2. 添加排斥锁,假设如果有一个人进行查询时,顺带上锁,其他人检查到锁的时候,等待10s后重新从Redis中获取即可
  3. 部署集群Redis,就算打到一个Redis还有千千万万的Redis服务

4.epoll与select有什么区别?

epoll 和 select 都是 I/O 多路复用的技术,都可以实现同时监听多个 I/O 事件的状态。

epoll 相比 select 效率更高,主要是基于其操作系统支持的I/O事件通知机制,而 select 是基于轮询机制。

来源:张朋

5.单机redis与集群redis?

单机Redis会有可能会很容易导致内存和CPU的能力上限。

集群Redis可以分担单机的缓解压力减少穿透、击穿情况,由于Redis主从复制架构每个数据库都要保存整个集群中的所有数据,容易形成木桶效应,为了最大化利用内存,可以采用集群,就是分布式存储,即每台redis存储不同的内容可

6.为什么memcache只支持kv,而redis支持类型多?

【个人觉得两者是不同方向解决不同环境下的高并发问题,所以我硬原理,我也不清楚】

7.redis数据过期策略是什么?

  1. 定时删除
  2. 惰性删除
  3. 定期删除

8.如何快速定位php程序运行慢的地方?

  1. 装个xdebug,打开profiling, 用cache grind看调度的日志就知道哪是瓶颈了
  2. slow log追踪

9.一个事务里面如果嵌套一个curl操作,会发生什么?

其实这道题,应该是MYSQL事务中进行CURL操作?我觉得应该不会发生太大问题可能主要有这种情况?

try {
    //run startTrans
    //run crul?
    //run commit
} catch (\Throwable $th) {
    //db rollback
}

可能报错什么的?直接回触发cath操作了吧直接回滚了?

同样等待一个大佬回复
  1. curl 如果产生 Fatal error,程序不往下执行,事务交由自动处理程序处理(通常是自动回滚);
  2. curl不产生致命错误,将不影响事务的处理;
  3. 如果在事务中必须使用curl的化,最好设置curl的超时时间,以便主动控制事务回滚。
来源:张朋

DDNS相关介绍

[scode type="share"]DNS:域名系统,是因特网的一项服务,它作为将域名和IP地址相互映射的一个分布式数据库,能够使人们更方便的用数字英文组合甚至中文访问互联网,而不需要用IPv4、IPv6 复杂的数字字符组合;

DDNS:动态域名系统,是域名系统(DNS)中的一种自动更新名称服务器内容的技术。在传统的DNS中,域名必须和固定的IP绑定,当IP变化时,必须手动更新IP与域名的映射关系,才能保证变化后的IP仍与域名相对应,其他用户才可访问。DDNS的作用就是将这更新过程自动化
[/scode]

3911016366.png

172714455.png

目前公司商用、家用宽带 几乎都是动态IP的宽带,所谓动态IP就是 随机分配给你的IP地址,动态IP地址(Dynamic IP)指的是在需要的时候才进行IP地址分配的方式。动态IP地址和静态IP地址是对应的。所谓动态就是指当你每一次上网时,ISP会随机分配一个IP地址,静态指的是固定分配一个IP地址,每次都用这一个地址;

那么怎么才能固定,答案是否定的! 但可以换个思路,IP不固定 那么 域名 是固定的,只需要记得域名,域名则通过DDNS解析,就能在广义上定义为固定。

DDNS用来干什么

用DDNS动态域名的目的是什么?
现在智能家电越来越多,物联网时代;通过APP就能远程家电、监控、家庭私有云、公司云盘... ...

[scode type="yellow"]特别提醒:使用动态域名搭建服务 请自觉遵守互联网安全法和相关法律法规[/scode]

实现原理

  1. 在一个公网固定IP的服务器上部署PHP版域名解析API作为服务端
  2. 客户端设备访问服务器的URL
  3. 服务器GET客户端IP并把客户端IP解析到指定的域名A记录上

3238681657.png

环境准备

1.固定IP的公网WEB服务器 WEB环境支持PHP7 推荐宝塔面板 以下用宝塔举例其他环境类似安全起见至少为nginx或apache
2.阿里云域名,并申请阿里云 AccessKey, AccessKeySecret(先保存记录)
3.客户端的动态IP带宽

[scode type="yellow"]说明:客户端IP地址需要 公网非城域,并且有可运行curl的设备 大多数路由的计划任务中都是支持的
且24小时不关机,(我个人在家有群晖和宝塔面板都是不关机的;也可以树莓派甚至是可curl的路由,比如老毛子,openwrt等)

如果满足条件就接着往下看
[/scode]

开始配置

公网服务器配置

1.解析一个作为DDNS服务域名到该服务器例如'ddns.abc.com',并创建对应的网站,不需要数据库
2.再解析一个要作为动态域名的子域名例如'www.abc.com',指向暂时IP随便写一个
3.Linux环境ssh进入新建网站根目录,运行命令(由阿里云提供)

git clone https://github.com/roura356a/alicloud-php-dns-updater.git dyndns-updater
Windows或者其他环境可直接访问 https://github.com/roura356a/alicloud-php-dns-updater.git 下载项目并解压到根目录
5.这时候就会有根目录下就有有一个文件夹 dyndns-updater
6.进入dyndns-updater文件夹找到 index.php 点击编辑
代码如下

<?php
date_default_timezone_set('UTC');
include_once 'alicloud-php-updaterecord/V20150109/AlicloudUpdateRecord.php';
use Roura\Alicloud\V20150109\AlicloudUpdateRecord;
$AccessKeyId = '填写你的 AccessKeyId';
$AccessKeySecret = '填写你的 AccessKeySecret';
$updater = new AlicloudUpdateRecord($AccessKeyId, $AccessKeySecret);
$newIp = $_SERVER['REMOTE_ADDR']; // New IP
$updater->setDomainName('填写你的顶级域名(没有www)如abc.com');
$updater->setRecordType('A');
$updater->setRR('填写作为动态解析的子域名,如www');
$updater->setValue($newIp);
print_r($updater->sendRequest());
修改后保存,然后进行先测试,然后再作安全方面配置
浏览器打开
http://你服务端域名/dyndns-updater/
http://ddns.abc.com/dyndns-updater/

如果返回格式(JSON转义,源为数组格式)

{
"RecordId":"0833293686517392",
"RequestId":"xxxx-xxxx-xxxx-xxxx"
}
那么说明解析成功,应该稍后就能收到DNS变更邮件提醒,如果没有返回则检查配置,和确认你的动态IP是否是城域;

安全配置

接下来做安全方面配置,避免你的url泄露,无论谁 一访问 A记录就解析成别人的了,总之谁访问就解析谁;

1.宝塔面板nginx点击站点修改——网站目录——密码访问 点击开启,密码建议稍复杂 我这里举例为 账号:btdnsadmin 密码:passwd
设置后 服务器端就完成了;

2.Apache(linux)的使用 .htaccess 和 .htpasswd 来进行安全加固
.htaccess
把.htaccess文件放在与index.php相同的文件夹中
内容如下

AuthType Basic
AuthName "DNS Updater Access"
AuthUserFile /var/www/dyndns-updater/.htpasswd
Require valid-user
.htpasswd
在任意位置运行以下命令,来创建用户及密码:

htpasswd -c /var/www/dyndns-updater/.htpasswd updater_user
以上命令会首次创建.htpasswd文件。其中,updater_user是您要添加的用户名。当运行该用户名时,它会要求您输入密码。

[scode type="share"]注意:根据 Apache 官方文档,htpasswd 使用 bcrypt(针对 Apache 的 MD5 修订版本),SHA1,或者系统的crypt()
例程来加密密码,确保密码不会以纯文本形式保存。所以,在执行以上命令后,我们建议您将密码保存在安全的地方。如果由于加密而忘记密码,您将无法恢复它[/scode]

推荐一个懒人工具 在线 htpasswd 生成器 可直接生成出需要的文件 生成完成直接拷贝进目录即可

完成以上配置后,您可以使用用户名和密码来访问 URL

创建定时执行脚本

接下来,来到动态IP环境中,使用你的linux或者宝塔面板 创建定时任务执行脚本
这里列举宝塔面板 计划任务中的脚本执行

执行命令(脚本) 时间周期建议10分钟一次就行,本人使用1分钟 都是能稳定运行的

curl -u btdnsadmin:passwd http://你服务端域名/dyndns-updater/index.php
btdnsadmin:passwd为你服务端为网站建立的访问账号:密码
返回日志:

[2019-04-30 08:45:54] Successful
{

"RequestId":"xxxx-xxxxxxxx-xxxxxxxx-xxx",
"HostId":"youdmoain.com",
"Code":"DomainRecordDuplicate"

}
说明执行成功

如没有公网服务器的,那么就只能选择纯客户端版python的 这里就脱本文内容了,就不说了 度娘有一堆教程。
如果动态IP宽带没有公网IP的,可以尝试部署Ngrok 内网穿透

一切就绪

[scode type="green"]推荐使用端搭配阿里云公共DNS

223.5.5.5
223.6.6.6[/scode]

就能达到几乎秒级的解析速度

总结

实测用过LEDE&OpenWRT 还有梅林 AliDDNS插件 效果都没有上述方法高效稳定 可能是强迫症犯了
至于为何不用免费的一些厂商DDNS,这个问题很好理解 重点我已经标出来;
追求稳定和急速的想法已经造就了强迫症的严重度;

本文部分内容引用阿里云官方提供的阿里云解析API文档

[scode type="yellow"] 2020年9月10日 使用的时候发现目前办法已失效,只能每3个月重新申请[/scode]

SSL是什么?

SSL(Secure Sockets Layer 安全套接层 ),及其继任者 传输层安全 (Transport Layer Security,TLS)是为 网络通信 提供安全及 数据完整性 的一种安全协议。TLS与SSL在 传输层 对网络连接进行加密。

为什么首先要使用HTTPS呢?

它有三个主要原因:

保密。这保护了双方之间的通信,使其免受诸如因特网之类的公共媒体的影响。例如,在没有HTTPS的情况下,当使用接入点的某人在线购买某物时,运行Wi-Fi接入点的某人可以看到诸如信用卡之类的私人信息。

诚信。这可以确保信息完整且未经更改地到达其目标方。例如,我们的Wi-Fi好友可以在我们的网站上添加额外的广告,降低图像质量以节省带宽或更改我们阅读的文章内容。HTTPS确保无法修改网站。

验证。这确保了网站安全。例如,运行Wi-Fi接入点的同一个人可以将浏览器发送到虚假网站。HTTPS确保你访问的网址是一个唯一安全网站。

那为什么要生成泛域名的SSL证书呢?
如果建过站的朋友一应该了解,在宝塔Linux面板中可以非常便捷的申请免费的SSL证书,但是有缺陷的是,加入我申请的是www.xxx.com证书,那么就无法适用于www2(这里是前缀).xxx.com其他前缀的域名,所以我们借Let's Encrypt来申请泛域名证书,这样就可在七牛云等其他地方可以共用一套证书。

如何申请?

访问www.sslforfree.com
填写泛域名和一级域名然后点击 Create Free SSL Certificate

微信截图

通过验证后点击Manually Verify Domain进行域名验证
微信截图

此时会分配需要在域名服务商填写的必要信息

微信截图

登入域名服务商(以阿里云为例)

依照生成的验证信息设置域名解析

添加TXT记录(请注意添加是要添加2个!)

微信截图

添加完成后点击Download SSL Certificate会进行相关验证

微信截图

等待验证中....
微信截图

证书申请成功
点击Download All SSL Certificate Files可以下载生成的三个证书

微信截图

免费的泛域名证书到手啦!
微信截图