银行汇率查询:L0 档位每天 100 次,缓存该缓存什么

约 11 分钟 进阶银行汇率查询本地缓存免费档位Redis
# 银行汇率查询:L0 档位每天 100 次,缓存该缓存什么 接口:银行汇率查询(apiCode=105)· 免费接口(L0 基础版 100 次/天、1 QPS)· 请求方式:POST / GET · 返回格式:JSON · 适用人群:已接入、需要控制调用量的开发者 · 阅读时间:约 6 分钟 · 最后实测核对:2026-09-18 ## 核心要点 - 免费接口注册即享 L0 基础版,每日 100 次调用、并发 1 QPS,长期有效;100 次摊到一天约等于每 14.4 分钟一次。 - 接口返回的是银行上一周期或上两周期的数据,不是实时汇率,本地缓存几十秒到几分钟对展示效果没有实际影响。 - 缓存键按「接入点 + 货币代码 + 时间窗口」组合,币种列表可以缓存一整天,历史数据按查询参数缓存。 ## 100 次够不够用 先把额度算清楚。L0 档位每天 100 次,如果页面每次打开都请求一次牌价,第 100 个访客之后就没有额度了。做成 30 秒轮询更糟,一天就是 2880 次,用量是额度的 28 倍。 所以要决定的是缓存挡在哪一层。牌价本身是延迟数据,用户看不出 60 秒的差别,但调用量会差两个数量级。 ## 免费档位与调用限制 2026-09-18 从免费接口页读到的权益档位如下,银行汇率查询(#105)在免费接口列表内: | 等级 | 每日调用 | 并发 | 获取方式 | |------|----------|------|----------| | L0 基础版 | 100 次/天 | 1 QPS | 注册即享,长期有效 | | L1 进阶版 | 500 次/天 | 5 QPS | 5,000 积分/年 | | L2 高级版 | 2,000 次/天 | 10 QPS | 15,000 积分/年 | | L3 专业版 | 10,000 次/天 | 30 QPS | 50,000 积分/年 | | L4 旗舰版 | 50,000 次/天 | 50 QPS | 100,000 积分/年 | 积分可以通过消费(1 元 = 100 积分)、每日签到(100 积分)、提交反馈、邀请注册等方式获得。档位升级是按年计的,所以缓存策略仍然是第一道防线——升档解决的是上限,缓存解决的是浪费。 ## 数据的新鲜度到底是多少 缓存 TTL 定多长,取决于数据本身有多新。产品说明里的表述是:延迟时长无法固定,接口返回为银行上一周期或上两周期的数据,不返回实时汇率;因银行汇率更新无固定时间规则,延迟周期无法明确。接入点文档同时标注「数据源自网络,有数分钟延迟,非投资建议,数据分析参考」。 按这个口径,展示型场景把 TTL 设在 30 到 60 秒,用户看到的内容与不缓存时基本一致。判断缓存里那份数据有多旧,可以读 `list[].day` 和 `list[].time`——实测同一批返回的 46 条记录共用同一个时间戳。 ## 内存 TTL 缓存的实现 ```python import time import threading import requests API = "https://route.showapi.com/105-30" APPKEY = "YOUR_APPKEY" _cache = {} _lock = threading.Lock() # 牌价是延迟数据,30 秒缓存对展示无影响;币种列表可以放长 TTL_RATE = 30 TTL_LIST = 86400 def fetch_rate(code: str = "", ttl: int = TTL_RATE): key = f"rate:{code or 'ALL'}" now = time.time() with _lock: hit = _cache.get(key) if hit and now - hit["ts"] < ttl: return hit["data"] params = {"appKey": APPKEY} data = {"code": code} if code else {} try: js = requests.post(API, params=params, data=data, timeout=15).json() if js.get("showapi_res_code") == 0 and js["showapi_res_body"].get("ret_code") == 0: with _lock: _cache[key] = {"ts": now, "data": js["showapi_res_body"]} return js["showapi_res_body"] except requests.RequestException as exc: print("请求异常,使用旧缓存兜底:", exc) # 回源失败时返回上一次成功的结果,避免页面空白 with _lock: hit = _cache.get(key) return hit["data"] if hit else None ``` 调用 `fetch_rate("USD")` 与 `fetch_rate("USD")` 连续执行两次,只有第一次会真正发出请求。 ## 多实例部署用共享缓存 上面那份内存缓存只在单进程内有效。服务多实例部署时,每个实例各存一份,缓存命中率会除以实例数,额度照样被吃掉。把缓存换成 Redis: ```python import json import redis import requests r = redis.Redis(host="localhost", port=6379, db=0) API = "https://route.showapi.com/105-30" APPKEY = "YOUR_APPKEY" def fetch_rate_shared(code: str = "", ttl: int = 30): key = f"showapi:105-30:{code or 'ALL'}" cached = r.get(key) if cached: return json.loads(cached) params = {"appKey": APPKEY} data = {"code": code} if code else {} try: js = requests.post(API, params=params, data=data, timeout=15).json() except requests.RequestException as exc: print("请求异常:", exc) return None if js.get("showapi_res_code") != 0 or js["showapi_res_body"].get("ret_code") != 0: return None body = js["showapi_res_body"] # 缓存过期时间略短于 TTL,避免多个实例同时回源 r.setex(key, ttl - 5 if ttl > 10 else ttl, json.dumps(body, ensure_ascii=False)) return body ``` ## 三种数据的缓存建议 | 数据 | 建议 TTL | 缓存键 | 理由 | |------|----------|--------|------| | 实时牌价(105-30) | 30~60 秒 | `105-30:{code}` | 数据本身是延迟快照,秒级新鲜度无实际收益 | | 币种列表(105-35) | 1 天 | `105-35:list` | 货币集合变动不频繁 | | 历史牌价(105-34) | 按查询参数长期有效 | `105-34:{code}:{month}` 或 `{code}:{start}~{end}` | 同一天的返回结果不会变化 | 历史数据的关键是把查询参数拼进键里,`month=202608` 和 `month=202607` 是两份不同的缓存,避免相互覆盖。 ## FAQ **Q1:缓存会不会让用户看到过期牌价?** 会,差值就是 TTL 的长度。接口返回的是银行上一周期或上两周期的延迟数据,几十秒的缓存对展示场景没有实际影响。如果业务对新鲜度更敏感,把 TTL 调小即可。 **Q2:L0 档位每天具体能调多少次?** 100 次/天,并发 1 QPS,注册即享,长期有效。需要通过平台积分升级到 L1~L4 才能提高,具体额度见免费接口页。 **Q3:100 次以外的调用会怎样?** 超出当前档位的调用按官方档位说明处理。把缓存与限流做在前面,日常调用量就会留在档位以内。 **Q4:单机的内存缓存够用吗?** 单进程、小流量够用。多实例部署必须换成 Redis 这类共享缓存,否则每个实例各自回源,缓存等于没做。 **Q5:回源失败时怎么保证页面不空白?** 返回上一次成功缓存的结果,同时在界面上提示数据可能不是最新的。上面的 `fetch_rate` 已经包含这个兜底分支。 **Q6:缓存能省钱吗?** 本接口免费,不存在按次扣费,缓存省的是每日调用额度与并发占用。 ## 下一步阅读 - [银行汇率查询并发怎么控?纯同步模型下的限流思路](https://www.showapi.com/guides/exchange-rate-concurrency-105):缓存之外的另一个调用量控制手段。 - [银行汇率查询:数据延迟与「仅供参考」的四个适用范围](https://www.showapi.com/guides/exchange-rate-delay-caveat-105):TTL 该定多长的依据。 - [银行汇率查询历史汇率:按月取还是按区间取](https://www.showapi.com/guides/exchange-rate-history-guide-105):历史数据的查询参数与缓存键设计。 - **本系列共 13 篇**:查看[银行汇率查询指南总目录](https://www.showapi.com/guides/exchange-rate-guides-105)
加载中...