消息队列
分布式文件系统
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 main
import (
"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{}
}