AppEngine py2.7应用迁py3时memcache替换为Redis相关疑问
解答
1. ndb Redis全局缓存配置规则
你不需要给每一个查询都套示例中的with上下文块,全局配置一次即可生效:
- 新版兼容py2.7/py3的
google-cloud-ndb库把缓存层做了抽象,Redis全局缓存的作用和旧版ndb内置的memcache完全一致,配置完成后所有ndb的get、put、查询操作都会自动走缓存、自动失效,和你之前用memcache时的ndb行为没有任何区别。 - 示例中的
with块只是演示单次上下文绑定的用法,实际生产可以在服务初始化入口(py2.7可以写在appengine_config.py中,py3可以写在flask请求中间件里)统一绑定缓存上下文,不需要修改原有业务查询代码。 - 缓存命中逻辑和旧版完全一致:单key查询的实体、普通查询结果都会自动存入Redis,有缓存时优先读缓存,写入实体时自动清理对应缓存。
2. 自定义业务缓存的迁移方案
你完全可以复用之前memcache的自定义缓存逻辑,包括缓存键规则、失效策略,只需要把memcache的API替换成Redis API即可:
你之前存用户游戏列表这类聚合数据的逻辑不需要改动,只需要解决ndb实体的序列化问题即可,示例如下:
import pickle from redis import Redis # 初始化Redis客户端,全局复用即可 redis_client = Redis(host="你的Redis实例内网地址", port=6379, db=0) # 读缓存逻辑,和之前的memcache写法几乎一致 cache_key = userskey.urlsafe() + "_gamesList" cached_data = redis_client.get(cache_key) if cached_data: # 反序列化得到ndb实体列表 games_list = pickle.loads(cached_data) else: # 查库重建缓存 games_list = Game.query(Game.user_key == userskey).fetch() # 序列化后存入Redis,过期时间和之前保持一致,指定protocol=2保证py2.7和py3序列化兼容 redis_client.setex(cache_key, 3600, pickle.dumps(games_list, protocol=2)) # 数据变更时失效缓存,和之前逻辑一致 redis_client.delete(cache_key)
单独缓存用户账号模型的逻辑和上面完全相同,用用户key作为缓存键即可。
3. 新旧服务并行的注意事项
只要两边保持两个规则统一,就可以实现缓存完全共用,支持流量拆分、beta用户测试:
- ndb全局缓存的key前缀保持一致
- 自定义缓存的键规则、pickle序列化协议(指定为2)保持一致
你原有的90%缓存命中率可以完全复刻到Redis上,不需要额外调整缓存策略。
内容的提问来源于stack exchange,提问作者Daniel
相关产品推荐
相关产品推荐

