High-concurrency Redis-backed credential pool SDK.
Project description
credential-pool-sdk
一个基于 Redis 的高并发共享凭证池 SDK。
它的目标不是绑定某个具体业务,而是提供一套可复用的“凭证池基础设施”能力,适合在多进程、多节点环境下统一管理以下对象:
- Cookie
- JWT
- Token
- Nonce
- Session
- 其他需要共享、复用、并发控制的认证凭证
设计目标
本项目聚焦“池能力”,不耦合业务代码,不内置具体站点逻辑。
核心目标:
- 通过
pip install安装使用 - 只依赖 Redis 作为共享状态中心
- 提供统一的凭证池 API
- 支持高并发随机获取
- 支持独占获取与归还
- 支持失败计数、租约回收、统计查询
适用场景
适合以下场景:
- 多个 worker 共享一批 Cookie / JWT
- 某些凭证允许被重复并发使用
- 某些凭证同一时间只能被一个 worker 独占使用
- 多台机器共同消费同一池凭证
- 业务项目希望把“凭证共享与并发控制”抽成独立 SDK
架构图
下面这张图描述了 credential-pool-sdk 在业务项目中的典型位置:
flowchart LR
A[业务 Producer<br/>生成 Cookie / JWT / Token] --> B[credential-pool-sdk]
C[业务 Consumer 1<br/>Worker / Collector] --> B
D[业务 Consumer 2<br/>Worker / Service] --> B
E[业务 Consumer N<br/>多节点实例] --> B
B --> F[(Redis)]
subgraph SDK[credential-pool-sdk]
B1[RedisCredentialPool]
B2[CredentialItem]
B3[Lease / Failure / Stats]
end
B --- B1
B --- B2
B --- B3
架构说明
- Producer 负责生成凭证,并调用 SDK 写入池。
- Consumer 负责从池中获取凭证,并在使用后回写结果。
- SDK 只负责“共享池能力”,不负责业务调度。
- Redis 作为多节点之间的共享状态中心。
时序图
下面是“独占获取一个当前未被使用的凭证,并在使用后归还”的典型时序:
sequenceDiagram
participant Worker as 业务 Worker
participant SDK as credential-pool-sdk
participant Redis as Redis
participant Target as 目标站点
Worker->>SDK: acquire_available(owner, lease_ttl)
SDK->>Redis: Lua 原子脚本<br/>从 available 随机取一个 key<br/>写入 lease_owner / lease_expiry
Redis-->>SDK: 返回 credential key
SDK->>Redis: HGET items[key]
Redis-->>SDK: 返回 CredentialItem
SDK-->>Worker: 返回独占凭证
Worker->>Target: 使用凭证发起请求
Target-->>Worker: 返回结果
alt 成功
Worker->>SDK: record_success(key)
SDK->>Redis: HDEL failures[key]
Worker->>SDK: release(key, owner)
SDK->>Redis: Lua 原子脚本<br/>删除 lease<br/>放回 available
else 失败
Worker->>SDK: record_failure(key)
SDK->>Redis: HINCRBY failures[key]
Worker->>SDK: release(key, owner)
SDK->>Redis: Lua 原子脚本<br/>删除 lease<br/>放回 available
end
两种获取模式的区别
模式一:共享获取
item = await pool.random_get()
特点:
- 同一个凭证可以被多个调用方同时拿到
- 不会改变凭证当前可用状态
- 适合可共享复用的凭证
模式二:独占获取
leased = await pool.acquire_available(owner="worker-1", lease_ttl=60)
特点:
- 同一个凭证同一时间只能被一个调用方持有
- 获取后必须通过
release()归还 - 若调用方崩溃,可通过
reclaim_expired_leases()回收
核心能力
1. 统一对象模型
池中的元素不是裸字符串,而是统一对象,例如:
{
"key": "jwt:1",
"value": "token-1",
"kind": "jwt",
"status": "active",
"created_at": 1760000000,
"updated_at": 1760000000,
"meta": {}
}
这样后续扩展字段时,不需要改动使用方式。
2. 两种获取模式
本 SDK 提供两种不同的“取凭证”方式。
random_get()
随机获取一个凭证。
特点:
- 同一个凭证可以被多个调用方同时取到
- 适合“可共享复用”的场景
- 例如:某些 JWT、某些无状态 Cookie
acquire_available(owner, lease_ttl)
随机获取一个当前未被占用的凭证,并立即标记为“已被使用”。
特点:
- 同一时间,一个凭证只能被一个调用方独占获取
- 适合“同一时刻只能单独使用”的场景
- 获取后必须通过
release()归还 - 若调用方异常退出,也可以通过过期租约回收
3. 归还凭证
通过:
await pool.release(key, owner="worker-1")
将独占中的凭证重新放回可用池。
4. 基础 CRUD
支持:
- 添加单个凭证
- 批量添加凭证
- 查询单个凭证
- 列表查询
- 更新凭证
- 删除凭证
5. 失败计数
支持:
record_success(key)record_failure(key)get_failure_count(key)
适合业务层自行实现失败阈值策略。
6. 租约回收
支持:
await pool.reclaim_expired_leases()
用于回收超时未归还的独占凭证。
7. 统计能力
支持:
- 总凭证数
- 可用凭证数
- 已租约凭证数
- 失败计数条目数
安装
pip install credential-pool-sdk
如果是本地开发:
pip install -e .
快速开始
创建连接
from credential_pool_sdk import RedisCredentialPool
pool = RedisCredentialPool.from_url(
"redis://127.0.0.1:6379/0",
pool_name="vimeo_jwt",
)
凭证对象示例
from credential_pool_sdk import CredentialItem
item = CredentialItem(
key="jwt:1",
value="token-1",
kind="jwt",
meta={"source": "producer-a"},
)
添加凭证
from credential_pool_sdk import CredentialItem
await pool.add(
CredentialItem(
key="jwt:1",
value="token-1",
kind="jwt",
)
)
随机获取一个可共享凭证
item = await pool.random_get()
if item is not None:
print(item.key, item.value)
独占获取一个当前未使用凭证
leased = await pool.acquire_available(owner="worker-1", lease_ttl=60)
if leased is not None:
print("acquired:", leased.key)
归还独占凭证
await pool.release(leased.key, owner="worker-1")
失败计数
await pool.record_failure("jwt:1")
failures = await pool.get_failure_count("jwt:1")
print(failures)
回收超时未归还租约
reclaimed = await pool.reclaim_expired_leases()
print("reclaimed:", reclaimed)
完整示例
import asyncio
from credential_pool_sdk import CredentialItem, RedisCredentialPool
async def main() -> None:
pool = RedisCredentialPool.from_url(
"redis://127.0.0.1:6379/0",
pool_name="vimeo_jwt",
)
await pool.add(
CredentialItem(
key="jwt:1",
value="token-1",
kind="jwt",
)
)
shared_item = await pool.random_get()
print("shared:", shared_item)
leased_item = await pool.acquire_available(owner="worker-1", lease_ttl=60)
print("leased:", leased_item)
if leased_item is not None:
await pool.release(leased_item.key, owner="worker-1")
stats = await pool.stats()
print(stats)
await pool.close()
asyncio.run(main())
API 概览
池对象
RedisCredentialPool
主要方法:
add(item)add_many(items)get(key)list(limit=100)update(key, patch)remove(key)random_get()acquire_available(owner, lease_ttl=60, exclude_keys=None)release(key, owner=None)reclaim_expired_leases(now_ts=None)record_success(key)record_failure(key, amount=1)get_failure_count(key)count()count_available()count_leased()stats()close()
数据对象
CredentialItem
字段:
keyvaluekindstatuscreated_atupdated_atmeta
统计对象
PoolStats
字段:
totalavailableleasedfailures
Redis 数据模型
对于池名 {pool_name},当前版本使用以下 Redis Key:
credential_pool:{pool_name}:itemsRedis Hash,存储key -> jsoncredential_pool:{pool_name}:activeRedis Set,存储所有激活凭证 keycredential_pool:{pool_name}:availableRedis Set,存储当前可独占获取的凭证 keycredential_pool:{pool_name}:failuresRedis Hash,存储key -> failure_countcredential_pool:{pool_name}:lease_ownerRedis Hash,存储key -> ownercredential_pool:{pool_name}:lease_expiryRedis Sorted Set,存储key -> expiry_ts
数据结构关系
flowchart TD
A[items<br/>Hash: key -> json] --> B[active<br/>Set: 所有激活 key]
B --> C[available<br/>Set: 当前可独占获取 key]
A --> D[failures<br/>Hash: key -> failure_count]
A --> E[lease_owner<br/>Hash: key -> owner]
A --> F[lease_expiry<br/>ZSet: key -> expiry_ts]
说明
items是主数据存储。active表示凭证仍在池内。available表示该凭证当前未被独占持有。lease_owner与lease_expiry一起构成租约系统。failures用于业务层实现失败阈值控制。
推荐使用模式
适合使用 random_get()
- JWT 可被多个请求共享使用
- 无状态 Cookie
- 对单个凭证并发使用没有强限制的场景
适合使用 acquire_available()
- 单个凭证同一时间只能被一个 worker 使用
- 代理认证信息
- 有明显并发冲突风险的 Cookie / Token
- 需要“使用后归还”的场景
最佳实践
key设计成全局唯一且可读,例如jwt:1、cookie:user_001kind用于标识凭证类型,例如jwt、cookie、nonce- 独占获取后务必在
finally中执行release() - 对长时间运行任务,建议定期执行
reclaim_expired_leases() - 失败阈值删除策略建议由业务层自行控制,不要在 SDK 核心层写死
License
待补充。
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file credential_pool_sdk-0.1.0.tar.gz.
File metadata
- Download URL: credential_pool_sdk-0.1.0.tar.gz
- Upload date:
- Size: 11.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1a859fa48689858e513ee038d8cae846698151a2a2972103f4dc31ad9e68430b
|
|
| MD5 |
7c47210306f52005042122d823942453
|
|
| BLAKE2b-256 |
b17e731ccadf1ed8b2c89ae473f31720947e5b030abe6e85766d593614f12d24
|
File details
Details for the file credential_pool_sdk-0.1.0-py3-none-any.whl.
File metadata
- Download URL: credential_pool_sdk-0.1.0-py3-none-any.whl
- Upload date:
- Size: 8.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
132fdf8f9765dcec1566d65a0225c34ab1c2de0858efff10ae589c1dc8a61362
|
|
| MD5 |
4b11ed2f7b1418ec87539fa864c6d047
|
|
| BLAKE2b-256 |
5e3d75b29fe5533e6fbc794f117d047c0c0e97605e3d677d18129ed07cdd5b65
|