Airbnb/Booking 系统设计(high level architecture)

news2025/2/28 23:50:59

原文地址 CodeKarle: Airbnb System Design | Booking.com System Design

B站搜 “Airbnb System Design” 有视频版本

需求:

功能性需求

系统用户包括商家和客人。

Hotel - 商家(拥有hotel的人)

        onboarding - 商家可以入住系统。

        update - 商家可以修改hotel相关内容,如增加 room,修改 pricing,增加新的 images等。

        booking -  查看预定,收入等。

User - 客人(预定hotel的人)

        search -  搜索指定地点,符合搜索条件的 hotel (价格区间、星级等级、 海景房等)。

        book - 进行预定

        check booking  -  查看预定。

Analytics -  一些系统分析。

非功能性需求

Low latency

High Availability

High Consistency - (一旦用户预定了hotel,应立刻看到结果)

Scale (Google 搜索得知 )

        500k Hotels (全世界大概有 50万 家 hotel)

        10M Rooms (大概共有 1000万房间)

        1000 Rooms / Hotel (Max: 7500)   (所以假设每个hotel 大概有 1000个 room,有些有 7500个room, 估的高点,是为了更好的处理一些 edge cases)

 总体设计和数据流向

Hotel Service提供给商家入驻和修改等功能,上传的图片保存在 CDN服务器,数据库保存图片链接。MySQL采用一个Master,多个Slave集群。流量高峰时动态增加Slave缓解读取压力。Hotel Service亦可动态水平扩展。

商家新增一个 room,数据将会写入 kafka,然后 search consumer将会拉取这些数据,存储到search数据库。

Search这里使用的是 Elasticsearch,同类型的可以使用 Solr,这里使用 ES,主要是想支持模糊查询(fuzzy search)。假设用户搜索马尔代夫(Maldives)的hotel,用户可能输入错误的名字。这种情况最好也会有搜索结果。

ES 集群 之上是 Search Service,提供给用户 搜索功能。

若此时系统流量激增,我们可以进行水平扩展,增加Kafka集群的node数量、增加 search consumers数量、增加 ES 集群的node数量。

Booking Service 坐落于 一个MySQL集群之上,当预定发生时,预定数据保存在此MySQL集群中。同时调用 Payment Service,成功之后,预定状态为“已确认”。

此时,当预定发生时,应当通知Search Service这个房间已被预定,不应再次出现在搜索结果中。所以此预定数据流入Kafka集群,被Search Consumers读取,修改相关数据。

对于live data (也就是处于中间状态的预定记录)存放于MySQL数据库,一旦预定到达最终状态(如 已完成,或取消)则进入 Archival Service,然后到达 Cassandra 集群。

这里使用 Cassandra 是因为 Cassandra能够轻松处理大量读写操作。

Notification Service 从 Kafka 读取需要通知的事件,比如 预定成功通知商家,预定被取消要通知用户,通知用户费用清单等。

Booking Mgmt Service 负责商家查看预定,用户查看预定历史等。连接两个数据源,从MySQL获取所有 active bookings,从 Cassandra获取已经发生了的预定信息。

这里在MySQL前面加了个 Redis,用来缓存查询的用户拥有的Bookings的结果。这里缓存策略是 write-through,即当有新的booking进入时,先写Redis,然后同步更新MySQL。

对于系统数据分析部分,往往一开始并不能预知所有需要分析的需求。所以这里使用 Hadoop 集群,针对系统所有的事件(比如商家所有hotel的基本信息,商家所有的预定,所有的交易信息等)都写入 Kafka。所以需要Spark Streaming Consumer来从Kafka读取这些事件,放入到Hadoop集群,然后通过Hive queries或任何其他类型的queries来构建一些reporting。

Hotel Service

部分APIs

部分 DB deisgn,红色部分是 主键或外健。

hotel 表中的 original_images 指的是商户上传的图片链接, display_images是压缩过后的图片链接。

rooms 表中 price_min, price_max, 这里通过Hadoop集群,运行machine learning model做一些供需分析得出一个 optimal price。也就是说供应少,需求多,那么价格就上涨。所以这里的 price_min, price_max就是 hotel提供的价格区间, 价格根据需求再次范围浮动。

facilities 是 hotel和room所配备的设备。

hotel_facilities 和 room_facilities 是两张 mapping 表。多对多的关系。

此处我们并没有使用Redis进行缓存,因为 hotel service并不会有流量激增的情况,而是在 search service。

Booking Service

部分DB design, 红色为主键或外健。

available_rooms 中 room_id, date, initial_quantity 字段来自于 hotel_service。 available_quantity意思是特定room_id, 特定的date,剩余的房间数量。表上有约束(constraint)限制不能为负值。

booking 表中 status字段有四个值可选(reserved, booked, cancelled, completed)。

部分API设计:

一个预定API 以post的形式,包括5个参数,其中并不包括price参数,后面从数据库中获取。

这里不从 booking API中获取 price是因为 request 可能被篡改,而且从request获取price并不是一个很好的设计。

当一个 booking 请求到达时,先检查available_rooms表中的 available_quantity 是否有足够的room,进一步则进行锁定,进行支付。

这里插入booking表和 修改 available_room表中的 available_quantity是在同一个transaction中完成的。如果available_quantity 只有一个,且同时有多人争抢,则通过数据库的约束 available_quantity 不能为负值来保证只有一条记录能修改数量成功,也就是只有一条记录插入booking,也就是只有一个人会跳转到支付流程。

这里进行锁定5分钟,我们借助于 Redis的TTL(Time To Live)功能,key过期会有个callback。

当支付成功,标记status为 Booked,Payment Service返回的 invoice_id 保存到 booking表中。相对应的 events 写入kafka,以便其它消费者使用。

当支付失败,标记 status为 Cancelled, 恢复 available_quantity。

当Redis中key过期,收到通知 callback,同时 用户也被跳转至 payment 流程,且支付成功。这里分两种情况:

1,如果先收到payment success,那么 booking 状态被改成 Booked,此时再收到key 过期,修改booking status时需要判断是不是 reserved 状态,只有 reserved 才能被 cancel。

2,如果先收到 key 过期通知,那么booking 状态被改成了 cancelled,然后再收到 payment success 。要么 revert payment;要么判断是否 还有 available_quantity,修改 booking 状态成 booked。

这里还有个问题是 Redis这种key 过期的方式,并非能保证你能在精准的时间点收到 callback,多少都会有延迟,具体情况就要看对实时性的需求了。也可以每隔一秒去主动查询 Redis,不过CPU等的消耗也是一个问题。

其实无论payment 成功与否,在收到payment 结果时,就直接可以从redis中删除这个肯定会过期的key。

技术栈的替换

mysql -> 可以用其它任何支持ACID的数据库,如 Postgres。

Redis -> Memcache 等。

Cassandra->    这里打算继续使用 Cassandra,技术上可以用 HBase代替,但更费操作。

Kafka -> ActiveMQ, Rabbit MQ, Amazon queue等。但Kafka更易于扩展。

系统监控使用 Grafana

跨地域传播

数据中心的相互备份等。。。.... 看不下去了,接触到再说吧。

也太high level了 😂

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2268570.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

如何在谷歌浏览器中清理无效的扩展

谷歌浏览器是一款功能强大且广受欢迎的网络浏览器,它允许用户安装各种扩展来增强功能。然而,随着时间的推移,一些扩展可能变得无效或不再需要,这时就需要清理这些无效的扩展以减少浏览器的负担并提升性能。 一、步骤详解 1. 打开…

MySQLOCP考试过了,题库很稳,经验分享。

前几天,本人参加了Oracle认证 MySQLOCP工程师认证考试 ,先说下考这个证书的初衷: 1、首先本人是从事数据库运维的,今年开始单位逐步要求DBA持证上岗。 2、本人的工作是涉及数据库维护,对这块的内容比较熟悉&#xff…

艾体宝产品丨加速开发:Redis 首款 VS Code 扩展上线!

Redis 宣布推出其首款专为 VS Code 设计的 Redis 扩展。这一扩展将 Redis 功能直接整合进您的集成开发环境(IDE),旨在简化您的工作流程,提升工作效率。 我们一直致力于构建强大的开发者生态系统,并在您工作的每一步提…

银河麒麟系统安装Wireshark抓包工具

麒麟系统安装Wireshark抓包工具 1. 麒麟SP1安装Wireshark 【1】. 安装Wireshark 在线安装wireshark 命令如下: apt-get install wireshark-qt软件包设置 弹出对话框,选择【是】选项。 安装完成。 【2】. 使用Wireshark 如果是普通用户,…

WPF 绘制过顶点的圆滑曲线 (样条,贝塞尔)

在一个WPF项目中要用到样条曲线,必须过顶点,圆滑后还不能太走样,捣鼓一番,发现里面颇有玄机,于是把我多方抄来改造的方法发出来,方便新手: 如上图,看代码吧: ----------…

Redis--持久化策略(AOF与RDB)

持久化策略(AOF与RDB) 持久化Redis如何实现数据不丢失?RDB 快照是如何实现的呢?执行时机RDB原理执行快照时,数据能被修改吗? AOF持久化是怎么实现的?AOF原理三种写回策略AOF重写机制 RDB和AOF合…

学习路之VScode--自定义按键写注释(插件)

1. 安装 "KoroFileHeader" 插件 首先,在 VScode 中搜索并安装名为 "KoroFileHeader" 的插件。你可以通过在扩展商店中搜索插件名称来找到并安装它。 2. 进入 VScode 设置页面 点击 VScode 左下角的设置图标,然后选择 "设置&q…

开源电子书转有声书整合包ebook2audiobookV2.0.0

ebook2audiobook:将电子书转换为有声书的开源项目 项目地址 GitHub - DrewThomasson/ebook2audiobook 整合包下载 更新至v2.0.0 https://pan.quark.cn/s/22956c5559d6 修改:页面已转为中文 项目简介 ebook2audiobook 是一个开源项目,它能够将电子…

3.5mm耳机接口硬件连接

结构 以最复杂的结构为例 简单的结构无非就是没有MIC(麦克风)接口 上图的5就是Detect的作用 上面这两款产品都为3.5mm的音频插座,图一 为连接4节的音频座,而且有两个开关,1接地,2接MIC,3接左声…

【贪心算法】贪心算法七

贪心算法七 1.整数替换2.俄罗斯套娃信封问题3.可被三整除的最大和4.距离相等的条形码5.重构字符串 点赞👍👍收藏🌟🌟关注💖💖 你的支持是对我最大的鼓励,我们一起努力吧!😃&#x1f…

一文大白话讲清楚CSS元素的水平居中和垂直居中

文章目录 一文大白话讲清楚CSS元素的水平居中和垂直居中1.已知元素宽高的居中方案1.1 利用定位margin:auto1.2 利用定位margin负值1.3 table布局 2.未知元素宽高的居中方案2.1利用定位transform2.2 flex弹性布局2.3 grid网格布局 3. 内联元素的居中布局 一文大白话讲清楚CSS元素…

30. 区间交集

题目描述 给定一组闭区间,其中部分区间存在交集。 任意两个给定区间的交集,称为公共区间(如:[1,2],[2,3]的公共区间为[2,2],[3,5],[3,6]的公共区间为[3,5])公共区间之间若存在交集,则需要合并(如:[1,3],[3,5]区间存在交集[3,3],需合并为[1,5]…

redis cluster实验详解

华子目录 实验环境准备部署redis cluster添加节点删除节点redis cluster集群维护 实验 环境准备 再开3台主机 先把之前3台源码编译的redis删除 [rootredis-node1 ~]# cd /usr/local/redis/ [rootredis-node1 redis]# make uninstall[rootredis-node2 ~]# cd /usr/local/redi…

微服务-服务保护和分布式事务

假如微服务中某个服务出现了故障,那我们需要为这个服务做好一些兜底的方案,健壮性的处理,这就是服务保护.以前我们写的是单体项目,不论项目多复杂,操作多少张表,最终都能够满足事务ACID的特性,但是我们分成了很多个服务之后,由于很多的服务是独立的,有各自的数据库,破坏了事务A…

【已解决】PDF文档有密码怎么办(2024新)免费在线工具PDF2Go

强大的解密工具PDF2Go使用指南 一、PDF2Go简介 PDF2Go是由德国QaamGo公司开发的在线PDF工具箱,以其强大的功能和用户友好的界面而闻名。它不仅免费,而且不需要用户注册或安装任何软件,只需打开浏览器即可使用。 二、功能特点 1. 免费且无需…

Ashy的考研游记

文章目录 摘要12.1112.2012.21 DAY1(政治/英语)政治英语 12.22 DAY2(数学/专业课)数学专业课 结束估分 摘要 在24年的12月里,Ashy完成了他的考研冲刺,顺利的结束了他本年度的考研之旅。 在十二月里&#…

Flutter-插件 scroll-to-index 实现 listView 滚动到指定索引位置

scroll-to-index 简介 scroll_to_index 是一个 Flutter 插件,用于通过索引滚动到 ListView 中的某个特定项。这个库对复杂滚动需求(如动态高度的列表项)非常实用,因为它会自动计算需要滚动的目标位置。 使用 安装插件 flutte…

XIAO Esp32 S3 轻松发送 HTTP 请求,打造智能物联网应用

让物联网更智能,连接更便捷! ESP32 是一款高性能的物联网开发平台,它不仅支持 Wi-Fi 和蓝牙,还是实现各种智能设备连接和控制的理想选择。今天,我们为你展示如何利用 ESP32 发送 HTTP 请求,轻松实现设备间的数据传输和远程控制。 为什么选择 ESP32 发送 HTTP 请求? 强大…

Unity中实现转盘抽奖效果(一)

实现思路: 旋转转盘的z轴,开始以角加速度加速到角速度最大值,结束的时候,以角加速度减速使角速度减少到0,然后转盘z轴旋转的角度就是加上每秒以角速度数值大小,为了使角度不能一直增大,对360度…

Postman[8] 断言

1.常见的断言类型 status code: code is 200 //检查返回的状态码是否为200 Response body: contain string //检查响应中包含指定字符串包含指定的值 response body:json value check/ /检查响应中其中json的值 Response body: is equal to string …