1.流量削峰这事应该怎么做
1.一个是通过队列来缓冲请求,即控制请求的发出;
2.一个是通过答题来延长请求发出的时间,在请求发出后承接请求时进行控制,最后再对不符合条件的请求进行过滤.(微信的“摇一摇”都是类似的方式)
整个秒杀答题的逻辑主要分为3部分
1、题库生成模块,这个部分主要就是生成一个个问题和答案,其实题目和答案本身并不需要很复杂,重要的是能够防止由机器来算出结果,即防止秒杀器来答题。
2、题库的推送模块,用于在秒杀答题前,把题目提前推送给详情系统和交易系统。题库的推送主要是为了保证每次用户请求的题目是唯一的,目的也是防止答题作弊。
3、题目的图片生成模块,用于把题目生成为图片格式,并且在图片里增加一些干扰因素。这也同样是为防止机器直接来答题,它要求只有人才能理解题目本身的含义。这里还要注意一点,由于答题时网络比较拥挤,我们应该把题目的图片提前推送到CDN上并且要进行预热,不然的话当用户真正请求题目时,图片可能加载比较慢,从而影响答题的体验。
其实真正答题的逻辑比较简单,很好理解:当用户提交的答案和题目对应的答案做比较,如果通过了就继续进行下一步的下单逻辑,否则就失败。
我们可以把问题和答案用下面这样的key来进行MD5加密:
问题key:userId+itemId+question_Id+time+PK
答案key:userId+itemId+answer+PK
答题的验证逻辑
注意,这里面的验证逻辑,除了验证问题的答案以外,还包括用户本身身份的验证,例如是否已经登录、用户的Cookie是否完整、用户是否重复频繁提交等。
除了做正确性验证,我们还可以对提交答案的时间做些限制,例如从开始答题到接受答案要超过1s,因为小于1s是人为操作的可能性很小,这样也能防止机器答题的情况。
3.最后一种是对请求进行分层过滤。
2.Nginx实现负载均衡
什么是负载均衡?
建立很多很多服务器,组成一个服务器集群,当用户访问网站时,先访问一个中间服务器,在让这个中间服务器在服务器集群中选择一个压力较小的服务器,然后将该访问请求引入该服务器
几种常用方式?
1、轮询(默认)
每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器down掉,能自动剔除。
upstream backserver {
server 192.168.0.14;
server 192.168.0.15;
}
2、weight
指定轮询几率,weight和访问比率成正比,用于后端服务器性能不均的
upstream backserver {
server 192.168.0.14 weight=3;
server 192.168.0.15 weight=7;
}
上述方式存在一个问题就是说,在负载均衡系统中,假如用户在某台服务器上登录了,那么该用户第二次请求的时候,因为我们是负载均衡系统,每次请求都会重新定位到服务器集群中的某一个,那么已经登录某一个服务器的用户再重新定位到另一个服务器,其登录信息将会丢失,这样显然是不妥的
3.采用ip_hash
指令解决这个问题,如果客户已经访问了某个服务器,当用户再次访问时,会将该请求通过哈希算法,自动定位到该服务器。
每个请求按访问ip的hash
结果分配,这样每个访客固定访问一个后端服务器,可以解决session
的问题。
upstream backserver {
ip_hash;
server 192.168.0.14:88;
server 192.168.0.15:80;
}
配置实例:
#user nobody;
worker_processes 4;
events {
# 最大并发数
worker_connections 1024;
}
http{
# 待选服务器列表
upstream myproject{
# ip_hash指令,将同一用户引入同一服务器。
ip_hash;
server 125.219.42.4 fail_timeout=60s;
server 172.31.2.183;
}
server{
# 监听端口
listen 80;
# 根目录下
location / {
# 选择哪个服务器列表
proxy_pass http://myproject;
}
}
}
Cookie 和 Session 关系和区别
https://juejin.im/post/5aa783b76fb9a028d663d70a
sessionid如何产生?由谁产生?保存在哪里?
1.sessionid是一个会话的key,浏览器第一次访问服务器会在服务器端生成一个session,有一个sessionid和它对应。
2.tomcat生成的sessionid叫做jsessionid。
3.session在访问tomcat服务器HttpServletRequest
的getSession(true)
的时候创建,tomcat的ManagerBase
类提供创建sessionid的方法:随机数+时间+jvmid
;
3.删除:超时;程序调用HttpSession.invalidate();程序关闭;
4.session存放在哪里:服务器端的内存中。不过session可以通过特殊的方式做持久化管理(memcache,redis)
tomcat中session的创建
ManagerBase是所有session管理工具类的基类,它是一个抽象类,
所有具体实现session管理功能的类都要继承这个类,该类有一个受保护的方法,该方法就是创建sessionId值的方法
tomcat的session的id值生成的机制是一个
随机数
加
时间
加上
jvm的id值
jvm的id值会根据服务器的硬件信息计算得来,因此不同jvm的id值都是唯一的
StandardManager类是tomcat容器里默认的session管理实现类,
它会将session的信息存储到web容器所在服务器的内存里。
PersistentManagerBase也是继承ManagerBase类,它是所有持久化存储session信息的基类,
PersistentManager继承了PersistentManagerBase,但是这个类只是多了一个静态变量和一个getName方法,目前看来意义不大
对于持久化存储session,tomcat还提供了StoreBase的抽象类,它是所有持久化存储session的基类,
另外tomcat还给出了文件存储FileStore和数据存储JDBCStore两个实现。
一条SQL语句执行得很慢的原因有哪些?
2种状态
1、大多数情况是正常的,只是偶尔会出现很慢的情况。
本身是没什么问题的,而是其他原因导致的
可能原因1:数据库在在同步数据到磁盘的时候,就有可能导致我们的SQL语句执行的很慢了。
我们知道数据库会在内存中把对应字段的数据更新了,但是更新之后,这些更新的字段并不会马上同步持久化到磁盘中去,而是把这些更新的记录写入到
redo log
日记中去,等到空闲的时候,在通过redo log
里的日记把最新的数据同步到磁盘中去。不过,redo log
里的容量是有限的,如果数据库一直很忙,更新又很频繁,这个时候redo log
很快就会被写满了,这个时候就没办法等到空闲的时候再把数据同步到磁盘的,只能暂停其他操作,全身心来把数据同步到磁盘中去的,而这个时候,就会导致我们平时正常的SQL语句突然执行的很慢
可能原因2:要执行的这条语句,刚好这条语句涉及到的表,别人在用,并且加锁了,我们拿不到锁,只能慢慢等待别人释放锁了
show processlist
这个命令来显示用户正在运行的线程,需要注意的是,除了 root 用户能看到所有正在运行的线程外,其他用户都只能看到自己正在运行的线程,看不到其它用户正在运行的线程。除非单独个这个用户赋予了process 权限。
可能又问锁https://www.jianshu.com/p/c12a863dfa1f
2.一直都这么慢
可能原因1:好好考虑下 SQL 书写
字段没有索引
字段有索引,但却没有用索引
这个select * from t where c - 1 = 1000;
即使c有索引,但是还是不会用,改成select * from t where c = 1000 + 1;
还有就是函数操作导致没有用上索引
可能原因2:当我们的查询语句有多个索引的时候,系统有可能也会选错索引
可能又问索引https://www.jianshu.com/p/6e86b30386ff
网友评论