最近有一个需求,通过django的admin后台,可以人工配置5张表的数据,这些数据进行一些业务规则处理后会统一成一份数据缓存在一个cache之中供服务端业务访问,因而任何一张表的数据更新(增、删、改),都要需要重新根据规则计算数据结果,并更新cache。
首先想到的方法就是覆盖每个表model子类中的save方法,在其中先调用父类的save方法走原有保存逻辑更新数据到数据库后,之后再单独调用一次cache的更新逻辑,这样每张表的任意数据被用户更新后,都将先触发model的数据库更新、而后执行cache的数据更新,其中Application表model的代码如下所示:
1 class Application(models.Model): 2 name = models.CharFIEld(max_length=128,blank=False,verbose_name=u'应用名') 3 description = models.TextFIEld(blank=False,1)">应用描述 4 status = models.IntegerFIEld(verbose_name=u状态',choices=APPliCATION_STATUS) 5 mtime = models.DateTimeFIEld(blank=False,1)">修改日期True) 6 ctime = models.DateTimeFIEld(blank=False,1)">创建日期 7 Meta: 8 db_table = application' 9 verbose_name_plural = u应用10 11 def save(self,*args,**kargs):12 super(Application,self).save(*args,1)">kargs)13 # 更新memcached逻辑实现函数,该函数为通用函数一部分,会单独建立MysqL连接,查询数据库数据,并更新到memcached14 update_memcached_from_MysqL()
这样每次在web上新增或者修改数据表记录时,都会先执行父类save *** 作,save完成后,又会执行update_memcached_from_MysqL函数,从mySQL查询到最新数据,而后更新到cache之中了。
然而实际测试的时候,发现每次修改数据时,更新到cache的并不是最新数据,而是未修改前的旧数据,比如当前name="test0",修改为name="test1"点击保存后,更新到cache之中的确还是test0,再次修改为name="test2",更新到cache之中的确实test1。
百思不得其解~怀疑是model执行save时,本地有cache会延迟更新,于是在super.save和update_memcached_from_MysqL之间增加了time.sleep(10),并多次调用update_memcached_from_MysqL函数,可是依然是每次修改保存时,更新到cache的数据都是修改前的取值:
1 2 super(Application,1)">3 4 update_memcached_from_MysqL()5 time.sleep(106 7 time.sleep(108 update_memcached_from_MysqL()
想不出好的解决方案,猜测model真正将数据更新到数据的时机是在save整个函数执行结束后,臆测了如下更新逻辑:
1 子类save执行前2 父类save执行3 更新memcached4 子类save执行结束5 真正更新到数据库
于是必须想办法将第3步的cache更新逻辑挪到save执行结束后,然后要保证每次执行save *** 作时更新cache,这个位置又不能动~~
于是考虑通过开启独立线程异步执行的方式实现,改写update_memcached_from_MysqL,在其中开启独立线程执行一个delay版本的更新函数,线程start后会先休眠n秒钟(n为可控参数,下例中为2),而后才执行从数据库读取数据并更新到cache的逻辑,改完后手动更新数据多次,验证已经能拉取到最新数据。
1 def update_memcached_from_MysqL():2 """ 3 猜测由于model的缓存机制,save函数执行完成前,新的数据可能未及时更新到数据库,4 此处开启独立线程执行memcache更新 *** 作,线程中会休眠数秒再从数据库拉取最新数据更新5 """6 td = threading.Thread(target=update_memcached_from_MysqL_delay,args=(2,))7 td.start()
然而之前的更新流程还仅仅是猜测而已,虽然采用线程异步延迟更新cache的方法后,多次修改验证避开了取不到新数据的问题,并不就说明猜测一定是正确的,而且即便猜测是正确的,如果save函数执行完后,model的数据更新没有在线程延迟时间结束前完成,理论上还是会有问题,考虑可以通过设置一个定时任务,比如每隔10分钟定时执行cache更新逻辑,来保证新数据最多延迟10分钟也能生效。
本来想深入探究model save更新机制~然而最近太忙了~~blog都两周没更新了,初步尝试了一下也还没有研究清楚这一块save逻辑的源码,这个数据修改平台也仅供内部使用~~暂时先这么修补一下~~以后有时间再深究这一块的问题~~加入Todo List。
总结
以上是内存溢出为你收集整理的覆盖Django mysql model中save方法时碰到的一个数据库更新延迟问题全部内容,希望文章能够帮你解决覆盖Django mysql model中save方法时碰到的一个数据库更新延迟问题所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)