跳转至

脚本开发 / 简易缓存 DFF.CACHE

DFF.CACHE 是基于 Redis 的临时缓存,结构为 scope + key -> value,适合计数器、队列、集合和轻量消息发布。

需要保留 JSON 类型或持久保存小规模应用状态时,应使用 DFF.STORE

关键差异

  • 读出的标量值通常是字符串,需要按业务类型调用 int(...)float(...)json.loads(...)
  • 默认 scope 是当前 Script ID;跨 Script 共享数据时必须显式传入相同的 scope
  • 每个 Key 和发布 Topic 都按 Scope 隔离,返回的 Key 名不包含内部 Scope 前缀。
  • hstrlenall(...) 返回 {field: value字节长度},长度单位是字节,不是 Unicode 字符数。

API 速查

Key

方法 说明
type(key, scope=None) 返回 Key 的数据类型
keys(pattern='*', scope=None) 返回匹配的 Key
exists(key, scope=None) 判断 Key 是否存在
expire(key, expires, scope=None) 设置剩余过期秒数
expireat(key, timestamp, scope=None) 设置 UNIX 秒时间戳形式的过期时间
ttl(key, scope=None) / pttl(key, scope=None) 返回剩余过期时间,单位分别为秒和毫秒
rename(key, new_key, scope=None) 重命名 Key
renamenx(key, new_key, scope=None) 仅当目标不存在时重命名 Key
delete(key, scope=None) 删除单个 Key,或传入列表 / 元组批量删除
delete_pattern(pattern, scope=None) 删除匹配的 Key;pattern 必填

String

方法 说明
set(key, value, expires=None, not_exists=False, exists=False, scope=None) 写入值,可限制 Key 存在状态和过期秒数
mset(key_values, scope=None) 批量写入;不支持同时设置过期时间
get(key, scope=None) / DFF.CACHE(key, scope=None) 读取单个值
mget(keys, scope=None) 批量读取
get_pattern(pattern, scope=None) 返回匹配的 {key: value}
getset(key, value, scope=None) 写入新值并返回旧值
incr(key, step=1, scope=None) / incrby(key, step, scope=None) 增加整数值

Hash

方法 说明
hkeys(key, pattern='*', with_values=False, scope=None) 返回匹配字段;with_values=True 时同时返回值
hset(key, field, value, not_exists=False, scope=None) 写入字段
hsetnx(key, field, value, scope=None) 仅在字段不存在时写入
hmset(key, field_values, scope=None) 批量写入字段
hget(key, field, scope=None) 读取字段
hstrlen(key, field, scope=None) / hstrlenall(key, scope=None) 返回一个或全部字段值的字节长度
hmget(key, fields, scope=None) 批量读取字段
hgetall(key, scope=None) 读取全部字段和值
hincr(key, field, step=1, scope=None) / hincrby(key, field, step, scope=None) 增加整数字段值
hdel(key, field, scope=None) 删除单个字段,或传入列表 / 元组批量删除

List

方法 说明
lpush(key, value, scope=None) / rpush(key, value, scope=None) 从左侧 / 右侧压入一个值或值列表
lpop(key, count=None, scope=None) / rpop(key, count=None, scope=None) 从左侧 / 右侧弹出一个或多个值
blpop(key, timeout=0, scope=None) / brpop(key, timeout=0, scope=None) 阻塞弹出
rpoplpush(key, dest_key=None, scope=None, dest_scope=None) 从源列表右侧弹出并压入目标列表左侧
brpoplpush(key, dest_key=None, timeout=0, scope=None, dest_scope=None) 阻塞执行弹出并压入
llen(key, scope=None) 返回列表长度
lrange(key, start=0, stop=-1, scope=None) 返回指定范围
ltrim(key, start, stop, scope=None) 只保留指定范围

blpop(...)brpop(...) 返回 [原始键名, value],超时返回 [None, None]rpoplpush(...)brpoplpush(...) 省略目标 Key 时会使用源 Key,dest_scope 可用于明确的跨 Scope 移动。

Set

方法 说明
sadd(key, member, scope=None) / srem(key, member, scope=None) 添加 / 删除一个成员或成员列表
scard(key, scope=None) 返回成员数
smembers(key, scope=None) 返回全部成员
sismember(key, member, scope=None) 判断成员是否存在

ZSet

方法 说明
zadd(key, member_scores, scope=None) / zrem(key, member, scope=None) 添加 / 删除成员
zcard(key, scope=None) 返回成员数
zrange(key, start=0, stop=-1, with_scores=False, scope=None) 按位置返回成员
zrangebyscore(key, min_score='-inf', max_score='+inf', with_scores=False, scope=None) 按分数返回成员
zpop_below_all(key, score, scope=None) / zpop_above_all(key, score, scope=None) 弹出不高于 / 不低于指定分数的全部成员
zpop_below_lpush_all(key, dest_key, score, scope=None) / zpop_above_lpush_all(key, dest_key, score, scope=None) 弹出符合分数条件的成员,并将其压入目标列表

执行 ZSet 弹出或移动扩展前,应确认源 Key、目标 Key 和分数边界。

发布与动态引用

方法 说明
publish(topic, message, scope=None) 向带 Scope 前缀的 Topic 发布消息
ref(key, scope=None, default=None) 为支持动态取值的 DFF.API 参数创建延迟引用

ref(...) 省略 scope 时使用专用的 REF Scope。String、List、Hash、Set 和 ZSet 会分别使用对应的读取操作解析引用。引用只用于 DFF.APIdelayed_cron_jobtimeoutexpiresqueue 参数。

示例

常用数据结构
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
import json

DFF.CACHE.set('count', 1, expires=60, scope='job')
count = int(DFF.CACHE.get('count', scope='job') or 0)

DFF.CACHE.hmset('user:001', {'name': 'Tom', 'age': 20}, scope='users')
age = int(DFF.CACHE.hget('user:001', 'age', scope='users') or 0)

DFF.CACHE.rpush('queue', json.dumps({'id': 1}), scope='jobs')
item = json.loads(DFF.CACHE.lpop('queue', scope='jobs'))

使用注意事项

  • 阻塞操作应设置合理的 timeout,避免 Func 超时。
  • 执行 delete_pattern(...) 前,应先使用 keys(...) 检查匹配项。
  • 避免对超大 Hash 调用 hstrlenall(...),以免阻塞共享缓存服务。
  • publish(...) 的 Topic 带有 Scope 前缀,订阅方必须使用一致的 Scope 约定。
  • 多个 Script 共享数据时,应显式传入 scope