项目问题
为什么要用GO重构Java的项目
比较好部署,写好之后不会频繁进行修改,用go build 打包成二进制文件即可
go的性能上比较占优势 因为go是编译成机器码,而Java是字节码
抢票相关问题
雪花算法:
长64位
由1位符号位
41位时间戳
10位机器标识码
12位序列号
递增快速生成无重复
令牌桶算法:
以恒定的速度往桶里添加令牌(代表发送数据的权利)
确保平均流量不会超过预期
又可以应对一定的突发流量
如何解决超卖问题的?
使用MYSQL的乐观锁
Redis预减库存,减完标记
从一个请求进入,然后会先进行一个预处理 实行一些策略进行流量控制,使用令牌桶算法保证后端服务不受瞬时大流量冲击
通过尝试在Redis中减少商品库存,这个操作是原子性的,可以保证并发安全
检查抢购的状态,
乐观锁更新MYsql库存,如果Redis预减库存成功,查询mysql中该票的原始库存版本号,使用乐观锁更新
解决重复下单的问题
利用redis来实现这个分布式锁
在redis里边加一张有关锁的表
利用uuid 生成一个唯一索引
插入表中,如果最后抢票失败删除记录
如果成功保留记录
下次请求进来,对uuid进行一个查询
防止重复下单
重复短时间多次请求
在redis中增加一个表来进行一个资源的锁定,防止多条指令
如何防止刷票
利用验证码 验证码使用base64生成的图形验证码
限制IP范围
IP限流
使用消息队列做什么?
来进行日志的记录和保存
使用Tmpfs来做什么?
是一种基于内存的文件系统,可以进行高速访问 动态大小调整
自动清理 简化管理 资源限制
适合用于存储那些生命周期短、频繁读写的临时文件
手动挂载即可
放的是抢票系统中抢票的信息,宣讲会的时间地点之类的
GIN框架相关问题
gin框架如何保证panic 不会影响程序运行
使用recovery中间件来实现,使用gin.Default(),就包含了这个中间件.该中间件的作用是在每一个请求处理的go中捕获panic
并执行一些清理操作,并记录错误信息到日志中
回复goroutine的上下文,保证服务的高可用
gin高性能是因为基于Radix树结构来高效地匹配HTTP请求路径和方法,
减少内存占用和提高请求处理速度
支持中间件
Gin的核心在安曾Engine RouterGroup Context Routing Rednder interface Middleware这几种结构体上
GO八股:
GO 栈和堆
GO传统意义上的栈,go语言放入了调度器,垃圾回收,系统调用等, go中的堆和栈其实是go运行时通过管理向操作系统申请的堆内存,构造逻辑上的堆和栈,本质都是从堆申请内存得来的,
在必要的时候,go为了防止内存碎片化,会在合适的时候堆整个栈进行深度拷贝,然后放到别的地方
GMP
数组和切片
切片本质上是对数组的一个封装
切片的结构体里边是长度,容量和底层数组
切片的扩容:
1.18以前的话:
首先判断期望容量是不是大于当前容量2倍,如果是就使用期望容量
小于1024翻倍
大于1024 增加25% 直到大于期望容量
后来1.18之后:
如果大于当前容量2倍使用期望容量
小于256翻倍
大于256 oldcap+oldcap+3*256/4直到大于期望容量
未扩容切片影响底层数组
map
map的初始化和删除delete