阿里云 golang 一面
消息队列
分布式文件系统
Linux的虚拟网络设备
TCP SSL/TLS
场景:对于打车场景,如何设计一个系统来处理并发打车请求?
设计一个处理并发打车请求的系统需要考虑多个方面,包括系统架构、数据存储、负载均衡和实时性。以下是一个基本的系统设计方案:
1. 系统架构
-
微服务架构:将系统拆分为多个微服务,例如用户管理、订单管理、司机管理和支付服务。
-
API 网关:作为所有请求的入口,负责路由、负载均衡和身份验证。
2. 请求处理流程
-
用户请求打车:
- 用户通过移动应用发送打车请求,API 网关接收请求。
-
位置服务:
- 后端调用位置服务获取用户的实时位置。
-
司机匹配:
- 使用实时数据分析算法(如最近邻算法)匹配离用户最近的可用司机。可以使用 Redis 等内存数据库快速获取信息。
-
订单创建:
- 一旦找到合适的司机,创建新的订单,并将订单信息存储在数据库中(如 MySQL 或 MongoDB)。
-
通知司机:
- 通过推送通知或 WebSocket 实时通知司机接单。
3. 并发处理
-
消息队列:使用消息队列(如 RabbitMQ 或 Kafka)来处理请求的高并发。将打车请求放入队列中,后端服务从队列中逐个处理。
-
负载均衡:使用负载均衡器(如 Nginx 或 HAProxy)分发请求到多个后端服务,确保系统的高可用性。
-
限流和熔断:使用限流策略(如令牌桶或漏斗算法)来控制并发请求的数量,防止系统过载。
4. 数据存储
-
关系型数据库:存储用户信息、司机信息和订单历史等结构化数据。
-
NoSQL 数据库:存储实时数据和日志信息,以便快速访问和分析。
5. 实时性和性能
-
缓存:使用 Redis 或 Memcached 缓存常用数据(如司机状态、用户历史请求等),提高响应速度。
-
异步处理:对于非实时的操作(如支付处理和评价),可以采用异步处理机制,提高用户体验。
6. 监控和日志
-
监控工具:使用 Prometheus 和 Grafana 监控系统性能,实时监测请求量、响应时间和错误率。
-
日志管理:集中管理日志(如 ELK Stack),便于排查问题和进行数据分析。
总结
通过微服务架构、消息队列、缓存、负载均衡等方法,可以有效地处理并发打车请求,确保系统的高可用性和良好的用户体验。同时,监控和日志管理也能帮助及时发现和解决问题。
场景:关于打车场景,如何实现用户加价以有限派车的功能?
redis hash 存储当前订单信息(勾选的车型们)
当有司机接单成功时redis落入mysql中创建订单成功
LC179最大数
https://leetcode.cn/problems/largest-number/description/
func largestNumber(nums []int) string {sort.Slice(nums, func(i,j int)bool{s1:= strconv.Itoa(nums[i])s2:= strconv.Itoa(nums[j])return s1+s2>s2+s1})ans := ""for _,v := range nums{if ans=="" && v==0{continue}ans += strconv.Itoa(v)}if ans==""{ans = "0"}return ans
}
多线程模拟C/S模型
package mainimport ("fmt""net""time"
)func startServer(port string) {listenter, err := net.Listen("tcp", ":"+port)defer listenter.Close()if err!=nil{fmt.Println("Error Listening:",err)return }// 持续监听客户端for{conn, err := listenter.Accept()if err!=nil{fmt.Println("Error accepting connection:", err)continue}go handelClient(conn)}
}// 处理客户端的请求
func handelClient(conn net.Conn){defer conn.Close()clientAddr := conn.RemoteAddr().String()fmt.Printf("Client %s connected\n", clientAddr)time.Sleep(5*time.Second)
}func startClient(clinetId int, serverAddr string){conn, err := net.Dial("tcp", serverAddr)defer conn.Close()if err!=nil{fmt.Println(err)return}fmt.Printf("Client %d connected to server\n", clinetId)
}func main(){port := "7777"go startServer(port)time.Sleep(time.Second)for i:=1;i<=5;i++{go startClient(i, "localhost:"+port)}// 阻塞select{}
}