API 接口设计

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
云数据库 Tair(兼容Redis),内存型 2GB
简介: API 接口设计
6.jpeg

6.jpeg1、场景描述


 比如说我们要做一款 APP,需要通过 api 接口给 app 提供数据。假设我们是做商城,比如我们卖书的。我们可以想象下这个 APP 大概有哪些内容:


 1)首页:banner 区域(可以是一些热门书籍的图片做推广)、本周热卖书籍区域、本月好评书籍区域、活动打折的书籍区域。。。


 2)排行榜:比如第一季度热销榜、新书版。。。


 3)书单:管理后台运营添加的书单,比如《程序员从入门到放弃》系列书单。。。


 4)用户相关的:比如用户个人信息设置、订单管理、消息管理、收藏的书籍。。。


 数据是保存在数据库中,考虑到高并发数据库的瓶颈,采用 DB + 缓存的服务器架构。


2、重要接口汇总


 看似简单的一个 app,需要调用的 api 接口是非常多的,总结下大概有这几类接口:


1)列表接口:比如书单里面的书籍列表、排行榜的书籍列表;


2)详情接口:书籍的详细信息;


3)评论接口:书籍评论(这里可能要求购买了的才能评论)、星标;


4)点赞接口:给书籍点赞、给书单点赞;


5)收藏接口:收藏书籍、收藏书单;


6)“相关” 接口:比如书籍《php 从入门到放弃》相关的有哪些书籍;


7)关注接口:关注某本书或者书籍作者,一旦某本书有打折或者作者有新书,会推消息等等。或者是用户间互相关注;


8)发布接口:比如用户可以发布书单。A 用户发布了书单,B 用户可以关注 A 用户,A 用户再发布新书单,会给 B 用户推消息等等;


9)搜索接口:查询书籍、查询书单、查询用户等等


3、后台管理系统


1)书籍信息的来源:爬虫抓取的数据、运营人员在管理后台添加;


2)书籍的价格、库存等信息,是可以在后台设置;


3)书籍的分类、书籍的标签,像爬虫如果抓取不到的,运营可以手动设置;


4)书籍的排序:在管理后台设置,用于在 app 上展示的先后顺序;


5)书单管理:运营可以添加、可以设置展示 / 隐藏;用户提交的书单,在后台进行审核;


6)用户的评论:在后台审核;


备注:管理系统还有很多功能,简单先写这几个。


4、api 接口设计


接口设计要遵循的一个想法:可以先从缓存读取,读取不到,再去数据库读取,然后写回缓存。


1)banner 数据: key-value 类型(string 类型)


redis key 名: index:banners   这个 key 是首页上面的 banner 可以设置一个缓存时间:1 小时


里面保存的数据是从数据库获取出来的 banner 数据,json 之后保存的字符串。


2)实时性问题


比如数据是在管理设置的,比如 banner 数据添加了一条,或者某一个 banner 数据被删除了或者改为不展示了,但是缓存里面还没变化,怎么处理?


【方案一】不做处理,等待缓存自己过期,然后再有请求获取的就是新的数据。缓存要有个过期时间,这个要看业务需要设置相应的缓存过期时间,比如 5 分钟。


【方案二】管理后台对 banner 有添加删除修改操作时,修改成功的同时把缓存中的数据也更新。这个方案不太赞成,因为这样子数据就有 2 个地方维护了,


一个是 api 接口访问的时候,如果缓存过期会回源写缓存,一个是管理后台;


【方案三】解决方案二的缺点,就是管理后台有数据增加删除修改的时候,把对应的缓存删掉,这样子 api 接口从缓存读取不到 key 就会重新生成缓存。这样也是比较实时的。


3)详情数据


详情信息可以放在缓存里面,key-value 类型,设置一个过期时间


redis key 名: book:detail:{book_id}


4)列表数据:key-value 类型


【方案一】把每一页的数据缓存起来,这样 api 接口来获取的时候,直接把一页的数据从缓存取出来然后返回。


redis key 名:index:book_list:{page}    缓存时间根据实际业务设置


假设每一页 20 条数据,这里保存的就是 20 条数据的 json 后的字符串,key 名里面有页码,每一页的数据用不同的 key 名缓存起来。


这个方案有个问题,比如管理后台删除一条数据,刚好缓存重新生成了,那么第一页的 20 条数据肯定是最新的,但是第二页如果缓存没有重新生成的,


那么新的第一页和旧的第二页会有一条数据重复。当然,如果新增数据那么第一页的缓存和第二页的缓存数据中间有一条数据遗漏了。。。


【方案二】把 id 放入有序集合,每次获取列表,从集合中获取出 20 个 id,然后去缓存中获取详情数据,然后返回。


管理后台如果有新增删除,那么就在集合里面新增或删除。 这里相比方案一,就是每次要去缓存获取 20 条详情信息,虽然缓存中获取很快但是也有一定的开销,但是数据最实时。


还有一个问题,感觉就是有点耦合,就是万一集合失效,那么要重建集合,假如数据很多,比如有几十万几百万个 id,那么要去数据库获取,然后写入缓存,有这种隐患。


【方案三】不用缓存,采用像 spinx、es 这些搜索引擎。通常有些业务需要很多排序规则,比如 sort 字段、时间字段、销量字段等等等,这个时候如果硬是要用方案二,


就必须是把排好序的数据保存如有序集合,比如 id=1,序号 = 1;id=15,序号 = 2;id=8,序号 = 3,每次有新增、删除,就要重新生成集合,很不好维护。


使用搜索系统来辅助,可以应该解决方案一和方案二的问题。当然了,看业务,如果不要紧的,方案一即可。像新浪博客、今日头条,之前也看到他们有些分页数据有重复的。


5)点赞接口


根据不同的业务要求,有些业务是只有点赞,没有取消点赞,我们就讨论这个有取消点赞的。


首先,假设我们有个业务是对书籍点赞,点赞之后可以取消点赞。比如说 APP 首页的列表里面需要点赞数,而且要实时,怎么处理?


我们肯定有个数据表来存储点赞信息,比如 book_like 表,里面记录了用户对书籍的点赞信息。


鉴于点赞数如果每次用户接口请求都去数据库请求,会给数据库增加压力,我们使用 redis 来减压。这里使用 hash 类型,下面会讲为何。


redis key 名:  book:like:{hash_id}  内容: field =》 value


这里的 hash_id 是 book_id / 1000 的结果


field 的值是 book_id % 1000 的结果


value 的值是点赞数


为何这种设计:hash 相比 string 类型有个优势,在满足 2 个条件的时候会进行压缩,就是内存的占用会小很多。


这两个条件是 hash 里面的 field 的数量小于指定数量(貌似默认是 512 还是 1024),另外一个条件是 value 值的大小要小于 64 字节(这个也是可以调整的,配置信息里面改)。


举个例子:


book_id = 100, 那么 hash_id 就是 0,field 是 100,值是点赞数


book_id = 1001, 那么 hash_id 就是 1,field 是 1,值是点赞数


列表接口里面有点赞数,可以从 hash 中获取


多次 redis 的 get 请求(get、hget 等),可以用管道(pipeline)来一次性获取,也会提高速度


点赞的时候,数据肯定是要写入数据库的,有 2 种方案处理:


【方案一】


书籍表里面比如有个点赞数字段,每次点赞 / 取消点赞,就是往里面加 1 减 1。


点赞表就是往里面增加或删除数据(可以是软删除)。


像 php 的 laravel 的 eloquent 模型是支持直接给字段 +-1 这样,不需要先取出数据再加。


【方案二】


先写入缓存,然后定期把缓存的数据取出来然后写入数据库。这个方案的话有点耦合了,比如需要定时脚本去写回数据库。


【方案三】


不使用缓存,数据直接更新回 book 表,或者 book 表不需要这个字段,需要点赞数的时候去 book_like 表计算,如果是有搜索引擎系统,那么应该不成问题。


6)相关接口


比如根据分类关联书籍。《php 从入门到放弃》和《php 从入门到奔溃》关联。


数据库里面可以根据分类 id 查找。简单的业务可以通过集合存储分类 id 下有哪些书籍。


如果复杂的业务,比如书籍有多个分类,比如分类 id=1  , 分类名称:php,分类 id=2 ,分类名称:程序开发,假设这 2 个分类是同级的,


那么可能有一些书是同时属于这 2 个分类的。


又或者有些业务下,是根据标签来关联,一个书籍可以有多个标签,标签和书籍是多对多关系。


此时又要来一句搜索系统可以处理。。。缓存也不是不能处理,感觉有些场景缓存处理起来很费劲。


以上只是一些很肤浅的看法,肯定有更好的处理方案,待研究补充上。


5、api 接口设计总结


 考虑到高并发时数据库的瓶颈,所以需要把请求的结果缓存起来。这里的策略是:


1)从缓存中获取数据,缓存中有数据则直接返回,或者做简单处理然后返回;


2)缓存没有数据,则从 DB 中查找数据,然后写回缓存;这种情况叫做 “回源”。


3)缓存的 key 是需要设置过期时间的,避免数据一直占用内存;


4)过期时间的设计,最好是打乱,避免同一时间有大量的 key 过期导致请求集中去 DB 请求导致雪崩;


5)根据业务需求,“回源” 的时候考虑申请到缓存锁的请求去数据库获取数据并更新缓存,其他请求则 sleep 一段时间(比如 5 毫秒 10 毫秒)然后再去缓存请求,如果请求还是没数据,可以继续等待或者直接返回空数据。


6)没有必要缓存起来的字段,不要缓存;


7)APP 不需要用到的字段没有必要返回给 APP,比如评论的审核时间、审核者,返回给 APP 是没用的,因为这些数据不需要展示出来,不会被用到;


8)减少 api 请求的次数,比如多次请求,要看下能否合并,比如首页,有好几个区域,每个区域都有几条数据。当然多次请求一样可以实现,但是请求次数少,则服务器可以接受更多客户端的请求。


相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore     ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库 ECS 实例和一台目标数据库 RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
存储 缓存 安全
API接口设计规范
这个是目前第三方数据接口交互过程中常用的一些参数与使用示例,希望对大家有点帮助。 当然如果为了保证更加的安全,可以加上RSA,RSA2,AES等等加密方式,保证了数据的更加的安全,但是唯一的缺点是加密与解密比较耗费CPU的资源.
|
机器学习/深度学习 JSON 前端开发
RESTful API接口设计规范
近年来移动互联网的发展,前端设备层出不穷(手机、平板、桌面电脑、其他专用设备…),因此,必须有一种统一的机制,方便不同的前端设备与后端进行通信,于是RESTful诞生了,它可以通过一套统一的接口为 Web,iOS和Android提供服务。
3643 1
RESTful API接口设计规范
|
XML 域名解析 JSON
【RESTful】RESTful API 接口设计规范 | 示例
【RESTful】RESTful API 接口设计规范 | 示例
6896 0
【RESTful】RESTful API 接口设计规范 | 示例
|
2月前
|
缓存 监控 测试技术
接口设计的18条军规:打造高效、可靠的API
【10月更文挑战第2天】在软件开发中,接口设计是连接不同模块、系统乃至服务的桥梁。一个优秀的接口设计不仅能提升开发效率,还能确保系统的稳定性和可扩展性。以下是接口设计的18条军规,旨在帮助你在工作和学习中设计出更加高效、可靠的API。
78 1
|
5月前
|
缓存 JSON 算法
http【详解】状态码,方法,接口设计 —— RestfuI API,头部 —— headers,缓存
http【详解】状态码,方法,接口设计 —— RestfuI API,头部 —— headers,缓存
73 0
|
安全 API 数据安全/隐私保护
API 接口设计规范
API 接口设计规范
452 0
|
消息中间件 API 数据库
细谈商品详情API接口设计
随着互联网技术的发展,商品详情信息的展示和交互变得越来越重要。为了提供更好的用户体验,我们需要设计一套高效、稳定且易于扩展的商品详情API接口。本文将详细探讨商品详情API接口的设计,包括接口的通用性、安全性和扩展性等方面,并附有相应的代码实现。
|
JSON JavaScript 搜索推荐
商品详情接口设计:使用API调用获取淘宝商品数据的完整方案
在如今的电商时代,获取商品的详细信息是实现商业化应用的基础。本文将详细介绍如何通过API调用来获取淘宝商品数据,并提供一个完整的商品详情接口设计方案,包括代码示例。开发人员可以根据此方案快速实现商品详情功能,提升用户体验。
|
缓存 算法 安全
这才叫 API 接口设计!
一家公司的每个系统都会有各种各样的接口,但是大部分公司,特别是传统行业的公司的所谓接口文档更多是当每个系传统的 word 文本格式,这种传统的格式有着人尽皆知的痛点: 1. 维护不及时; 2. 与代码不同步; 3. 归档后“便束之高阁”; 4. 接口文档跟代码没有互动; 5. 文本检索无法建立全局搜索,需要额外借助工具。 为了解决上述的问题,需要建立一套行之有效的接口管理体系,该体系的目标是: 1. 能够进行接口文档管理,作为后续的接口治理的其中一部分; 2. 能作为接口测试的平台,这样能保证接口跟代码是同步的; 3. 支持文本检索。
|
JSON API 数据格式
细谈商品详情API接口设计
当我们构建电商网站或应用时,常常需要获取淘宝商品的详细信息。为了实现这个功能,我们可以利用淘宝提供的开放平台API接口来获取商品数据。在这篇文章中,我们将学习如何设计一个商品详情API接口,并提供相应的代码示例。