业务场景: 我个人项目需要获取一个数据,需要大量调用网站的 api 去获取数据,然后他们一般都有调用次数限制,次数到了就返回错误或空.
情况: 所以我就找了多个网站的相同功能的 api,然后用一个循环链表连起来,当一个 api 响应失败的时候调用下一个链表的 api 如果还是失败就返回 error
问题: 然后现在问题来了,我需要并发情况下去调用这些 api,因为她们响应速度实在太慢,但是不加锁我怎么保证指向下一个链表的操作只执行一次. 我知道最简单的方法是 api 请求前加锁响应后释放,但是我一次请求估计要调用几十上百次 api 加了锁估计得等几分钟才能响应,所以有什么更好的方案去实现这个功能
补充一下我的项目是用 go 写的
1
seth19960929 2023-09-09 10:46:55 +08:00 1
你的描述有问题, 没有人能理解你说的是什么. 既然你是上一个失败, 才链式调用下一个. 那么何来并发只说. 也无上锁之说.
你要说你并发调用链表中所有, 任意一个成功就可以返回, 或者所有失败的话. 那么就用 ctx, 所有 request 公用一个 ctx ctx,cancel := context.WithCancel() 当有成功的一个, 主动调用 cancel() 函数, 其它 http client 就会取消 |
2
ccde8259 2023-09-09 12:49:50 +08:00 via iPhone
环状列表+头指针
读操作其实是可以 LockFree 的,所有请求拿一份环状列表+头指针的快照回来,存一个尾指针指向下一个对象,第一个请求失败以后就取尾指针,顺序调用第二个,尾指针下移直到尾指针指向头指针。 |
3
SmiteChow 2023-09-11 10:07:17 +08:00
还是用锁,但是要把这个锁暴露为 token ,因为你的 runner 需要并发请求。
实现一个 token 管理员服务,生成分发 token (注意加读写锁),比如生成如下 token 列表 [主,主,主,备,备] runner 随意并发,获取 token ,根据 token 请求即可。 |