今日油价数据什么时候刷新?用 ct 字段判断缓存是否过期
约 11 分钟 进阶今日油价ct字段缓存刷新调价日
# 今日油价数据什么时候刷新?用 ct 字段判断缓存是否过期
接口/接入点:今日油价(apiCode=138)· 查询油价(138-46)/ 查询行情(138-49) · 免费 · 适用人群:中高级开发者 · 阅读时间:约 5 分钟 · 最后实测核对:2026-09-18
缓存设成固定 24 小时,起算时刻随用户访问时间漂移,过期点就会偏离数据刷新点。判断数据是否换批,用接口返回的 `ct` 比较更直接。
## 核心要点
- `ct` 是接口侧这批数据的生成时间,2026-09-18 实测返回 `2026-09-18 12:00:05.916`,同一批 31 条记录取值一致。
- 产品说明写的同步口径是每日凌晨 7 点,与实测 `ct` 不是同一个时点,因此不建议把 TTL 硬编码到某个整点。
- 查询行情(138-49)的 `next_change_time` 是下一次调价日,可用来在调价窗口前后主动刷新缓存。
## 两个时间字段的分工
| 字段 | 来源接入点 | 含义 | 实测值 |
|---|---|---|---|
| `ct` | 查询油价(138-46) | 这批数据的生成时间 | `2026-09-18 12:00:05.916` |
| `before_change_time` | 查询行情(138-49) | 最近一次调价日 | `20260912` |
| `next_change_time` | 查询行情(138-49) | 下一次调价日 | `20260925` |
`ct` 描述数据是什么时候生成并写入接口的,`next_change_time` 描述成品油调价窗口。两者不是一回事。
## 按 ct 判断是否换批
思路是缓存里一并存下 `ct`,回源后比对:变了就替换数据,没变就只续期。这样不依赖刷新时刻。
Python(requests + Redis):
```python
import json
import requests
import redis
rds = redis.Redis(host="localhost", port=6379, db=0)
KEY = "oil:138:46:snapshot"
def fetch():
resp = requests.post(
"https://route.showapi.com/138-46",
data={"appKey": "YOUR_APPKEY"},
timeout=5,
).json()
if resp.get("showapi_res_code") != 0:
raise RuntimeError(resp.get("showapi_res_error"))
body = resp["showapi_res_body"]
if body.get("ret_code") != 0:
raise RuntimeError(body.get("remark"))
return body["list"]
def refresh(ttl_seconds=3600):
"""回源后比较 ct:变化则替换数据,未变化只续期。"""
fresh = fetch()
fresh_ct = fresh[0]["ct"]
cached = rds.get(KEY)
if cached:
old = json.loads(cached)
if old.get("ct") == fresh_ct:
rds.expire(KEY, ttl_seconds) # 同一批数据,只延后过期
return old["list"], False
rds.setex(KEY, ttl_seconds,
json.dumps({"ct": fresh_ct, "list": fresh}, ensure_ascii=False))
return fresh, True
items, changed = refresh()
print(f"数据时间 {items[0]['ct']},本次{'已更新' if changed else '沿用缓存'}")
```
cURL:
```bash
# 取数据并观察 ct
curl -X POST "https://route.showapi.com/138-46?appKey=YOUR_APPKEY" \
-H "content-type: application/x-www-form-urlencoded" -d "prov=%E5%8C%97%E4%BA%AC"
# 取调价日,用于调价窗口前主动刷新
curl -X POST "https://route.showapi.com/138-49?appKey=YOUR_APPKEY" \
-H "content-type: application/x-www-form-urlencoded" -d "prov=%E5%8C%97%E4%BA%AC"
```
Node.js(fetch):
```javascript
const API = "https://route.showapi.com/138-46";
async function fetchWithCt() {
const resp = await fetch(API, {
method: "POST",
headers: { "content-type": "application/x-www-form-urlencoded" },
body: new URLSearchParams({ appKey: "YOUR_APPKEY" }),
signal: AbortSignal.timeout(5000),
});
const body = (await resp.json()).showapi_res_body;
if (body.ret_code !== 0) throw new Error(body.remark);
return { ct: body.list[0].ct, list: body.list };
}
const { ct, list } = await fetchWithCt();
console.log(`数据生成于 ${ct},共 ${list.length} 条`);
// 下一次回源时比较 ct 是否变化,决定是否替换缓存
```
## 调价窗口前主动刷新
调价日当天价格会变,这时按常规 TTL 等过期就会晚几个小时才更新。用查询行情(138-49)的 `next_change_time` 做补充:接近这个日期时清掉缓存,强制回源。
```python
from datetime import datetime, date
def cache_key(prov="__all__"):
return f"oil:138:46:{prov}"
def should_invalidate(prov="北京"):
"""临近调价日时返回 True,提醒清缓存。"""
resp = requests.post(
"https://route.showapi.com/138-49",
data={"appKey": "YOUR_APPKEY", "prov": prov},
timeout=5,
).json()
next_change = datetime.strptime(resp["showapi_res_body"]["next_change_time"], "%Y%m%d").date()
return (next_change - date.today()).days <= 1
if should_invalidate():
rds.delete(cache_key()) # 全量快照与单省缓存按你的 key 设计一并清理
```
## 适用条件与注意事项
- `ct` 是数据生成时间,不是调价公告时间,也有别于 `next_change_time`。
- 2026-09-18 实测同一批 31 条记录的 `ct` 集中在两个毫秒值,属同批写入,取第一条比较即可。
- 产品说明的同步口径为每日凌晨 7 点。实测 `ct` 落在中午,单日单次样本不足以推断长期规律,用比较 `ct` 变化的方式判断是否换批,不依赖具体时刻。
- 查询行情(138-49)的 `prov` 必填,只做调价日判断时随便传一个标准省名即可。
- 定时任务与实时请求共用同一档位额度,把回源收敛到一处更省。
## FAQ
**Q1:缓存设 24 小时为什么会拿到旧数据?**
从访问时刻起算的 24 小时与数据刷新时刻不对齐,过期点会落在刷新点之后。改用比较 `ct` 的方式判断,不依赖起算时刻。
**Q2:怎么知道数据已经是新的?**
看 `ct`。缓存与新回源结果的 `ct` 不同就说明换批了。
**Q3:定时任务放在几点跑?**
不必绑定某个整点。按小时级周期跑,每次比较 `ct`,变了才替换数据。
**Q4:调价日当天要不要特殊处理?**
建议处理。用查询行情(138-49)的 `next_change_time`,在临近调价日时清一次缓存。2026-09-18 实测北京、广西、重庆、吉林四省的 `next_change_time` 都是 `20260925`。
**Q5:`before_change_time` 有什么用?**
它是最近一次调价日。做「上次调价距今多少天」这类展示时用它,`ct` 不能替代。
## 相关能力 / 下一步阅读
- [今日油价调用量规划:缓存粒度与 TTL 的确定方式](https://www.showapi.com/guides/oilprice-cache-138)
- [今日油价涨跌幅怎么查?查询行情接入点的调价日与涨跌率用法](https://www.showapi.com/guides/oilprice-trend-138)
- [今日油价:一次调用取回全国 31 省油价的做法](https://www.showapi.com/guides/oilprice-province-list-138)
- **本系列共 13 篇**:查看[今日油价指南总目录](https://www.showapi.com/guides/oilprice-guides-138)





