1.面对抢优惠券这样的高负载场景,你从架构、负载均衡等方面说一下你的设计? 答了参考Nginx进行负载均衡,然后在每台服务器怎么怎么弄(架构每一层怎么设计)
参考https://toutiao.io/posts/6z3uu2m/preview,https://zhuanlan.zhihu.com/p/482817229
SLB负载均衡发给API网管再分给抢购系统
10w一分钟,28法则,8w10s,有40w人抢10s,4w/s的qps -》 常规系统1000/s(4核8G的机器,开200个线程处理请求)
后果:网络带宽打满、cpu使用率达到90%多、数据库负载过高、下游依赖频繁超时
例如:写数据尽量直接写缓存,然后异步写db;读数据尽量优先把数据缓存在系统jvm内存里,本地读取返回
击穿jvm和redis要查mysql:抢购系统内可以开一个后台线程,然后让他每隔30min自动去redis里查最新缓存数据,或者去商品系统查最新缓存数据,然后刷新本地缓存
缓存不一致:扣减and恢复的顺序不一致(乱序),所以要实现mq顺序消息,发到同一个分区有序
前端:页面上各类静态资源首先应分开存放,然后放到cdn节点上分散压力,倒计时用后端获取按钮变灰,查询和购票只能按一次,js限制时间
后端:同一个uid限制频率,nginx分发请求到不同机器,预处理是否还有余量
数据库:分片解决数据量太大,路由哪个库(范围,哈希(均匀),路由服务)
超卖:悲观锁解决安全,但慢,乐观锁版本号机制控制
稳定性:redis雪崩,先进性预热
2.用户隐私数据怎么处理?
1.哈希,md5等彩虹表攻击
2.加盐哈希(盐就是随机的字符串拼接密码)
3.匿名化、差分隐私、同态加密
3.https和http的区别,https怎么保证安全
详见小林coding:https://www.xiaolincoding.com/network/2_http/http_interview.html#https-%E6%98%AF%E5%A6%82%E4%BD%95%E5%BB%BA%E7%AB%8B%E8%BF%9E%E6%8E%A5%E7%9A%84-%E5%85%B6%E9%97%B4%E4%BA%A4%E4%BA%92%E4%BA%86%E4%BB%80%E4%B9%88
ca保证了公钥不能被伪造
4.算法:K个一组反转链表
妙不可言,k个一组翻转
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def reverseKGroup(self, head: Optional[ListNode], k: int) -> Optional[ListNode]:
n = 0
cur = head
while cur:
n += 1 # 统计节点个数
cur = cur.next
p0 = dummy = ListNode(next=head)
pre = None
cur = head
while n >= k:
n -= k
for _ in range(k): # 同 92 题
nxt = cur.next
cur.next = pre # 每次循环只修改一个 next,方便大家理解
pre = cur
cur = nxt
# 见视频
nxt = p0.next
nxt.next = cur
p0.next = pre
p0 = nxt
return dummy.next
5.思维题
长方形纸片上有一个圆洞,怎样才能沿着直线把它剪成面积相同的两块(几何中心相连)
一根木棍掰成三段,组成三角形的概率(条件概率) 1/4
6.进程通信的方式,用过哪些
匿名管道( pipe ):管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用
有名管道 (named pipe) :有名管道也是半双工的通信方式,但是它允许无亲缘关系进程间的通信。
消息队列( message queue ) :消息队列是由消息的链表,存放在内核中并由消息队列标识符标识。消息队列克服了信号传递信息少、管道只能承载无格式字节流以及缓冲区大小受限等缺点。
信号量( semophore ) :信号量是一个计数器,可以用来控制多个进程对共享资源的访问。它常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源。因此,主要作为进程间以及同一进程内不同线程之间的同步手段。
信号 ( sinal ) :信号是一种比较复杂的通信方式,用于通知接收进程某个事件已经发生
共享内存( shared memory ) :共享内存就是映射一段能被其他进程所访问的内存,这段共享内存由一个进程创建,但多个进程都可以访问。共享内存是最快的 IPC 方式
套接字( socket ) :套接口也是一种进程间通信机制(bind listen connect send close)
7.C++STL vector和数组的区别
动态大小
数组的大小在定义时就被固定了,无法在运行时进行扩展或缩小,而vector则可以动态调整大小,可以在运行时根据需要进行扩展或缩小。
内存管理
数组在内存中是一段连续的空间,需要手动分配和释放内存。而vector会在需要的时候自动进行内存管理,不需要手动处理内存的分配和释放,这样可以减少内存泄漏和其他内存管理问题的出现。
使用方便性
数组使用时需要手动进行遍历和访问元素,使用起来比较繁琐,而vector提供了一系列的成员函数,例如push_back、pop_back、insert、erase等,可以方便地进行元素的添加、删除和访问。
适用性
数组适合用于存储数据量固定的情况,例如矩阵运算、排序算法等;而vector适合用于数据量不确定或需要动态扩展的情况,例如动态存储读入的数据、动态维护容器等。
总之,vector和数组都有各自的优势和适用场景,需要根据实际情况进行选择。如果需要动态调整大小、不需要手动管理内存或需要方便地访问元素,则应该选择vector;如果需要固定大小、需要手动管理内存或只需要简单地访问元素,则可以选择数组。
8.信号量与互斥锁的不同
(1):互斥量用于线程的互斥,信号线用于线程的同步。这是互斥量和信号量的根本区别,也就是互斥和同步之间的区别。
(2):互斥量值只能为0/1,信号量值可以为非负整数。
互斥:同一个资源同一时间只有一个访问者可以进行访问,其他访问者需要等前一个访问者访问结束才可以开始访问该资源。但互斥无法限制访问者对资源的访问顺序,即访问是无序的。
同步:分布在不同进程之间的若干程序片断,它们的运行必须严格按照规定的某种先后次序来运行,这种先后次序依赖于要完成的特定的任务。所以同步就是在互斥的基础上,通过其它机制实现访问者对资源的有序访问。
总结:同步是一种更为复杂的互斥,而互斥是一种特殊的同步。
同步:同步就是顺序执行,执行完一个再执行下一个,需要等待、协调运行。
异步:异步和同步是相对的,异步就是彼此独立,在等待某事件的过程中继续做自己的事,不需要等待这一事件完成后再工作。
9.ATM机,怎么考虑它的设计
用户:账户、 存款、取款、 转账、修改密码、退出、注销账户
系统管理员:注册、查看用户信息
10.一亿个int类型的数字,怎么取top1w个,怎么用分布式的方案
1.用一个长度为1w的stl存,遍历找到topk
2.分治:分成100份每份100w,找到每份的top1w,在100w个找1w个最大的,过滤掉99%
3.hash去重
4.最小堆
11.有哪种排序算法是稳定的
冒泡排序:如果两个元素相等,没有动作
插入排序:如果碰见一个和插入元素相等的,那么插入元素把想插入的元素放在相等元素的后面。所以,相等元素的前后顺序没有改变
归并排序:2个元素如果大小相等也没有人故意交换
基数排序
12.C++怎么让一个对象只在栈上分配
只有使用new运算符,对象才会建立在堆上,因此,只要禁用new运算符就可以实现类对象只能建立在栈上。
new operator 总是先调用 operator new,而后者我们是可以自行声明重写的
13.java后端,多安全问题、遇到攻击怎么办?开发的安全问题
Web攻击动机:
恶作剧;
关闭Web站点,拒绝正常服务;
篡改Web网页,损害企业名誉;
免费浏览收费内容;
盗窃用户隐私信息,例如Email;
以用户身份登录执行非法操作,从而获取暴利;
以此为跳板攻击企业内网其他系统;
网页挂木马,攻击访问网页的特定用户群;
仿冒系统发布方,诱骗用户执行危险操作,例如用木马替换正常下载文件,要求用户汇款等