`
windytwang
  • 浏览: 50938 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

数据库快速统一地布署memcached

阅读更多

memcached是一款优秀的分布式key-value缓存框架。使用,集成简单方便。

但是对于如何优化数据库查询中,具体的使用方法网上相关的资源非常少。这里我给出自己摸索的经验方法与大家共享一下。

 

这里主要讲 如何给所有的表添加一种统一的使用缓存的办法,以及使用缓存使用中会为出现的问题,及统一的解决策略。

(以下是代码是基于python+Django,但其原理不限于此,但python语言的灵活强大在这里也可以得到很好的体现,试想要是在C++上实现这一切,就不是那么简单的一些事情)

 

首先我们假设创建了一个表User, id,name,password等荐,其中idprimary key,namekey.

 

1,基本的memcached使用方法

那么最简单的使用memcached的方法即为

cache.get('user_id_123')

cache.set('user_id_123', user )

 

2,何种查询使用memcached

这里只针对返回单条数据的查询做memcached,如果是返回集合的做cache,对于何时失效,如何失效的策略非常复杂,其开销也非常大,所以目前还没寻找到一个好的方法。所以这里只针对特定key的查询进行cache.

比如user这张表,可以定义按id进行查询,也可以按name进行查询。 又如有Item这张表,其构成为id,character_id,type,number. idprimary key, (character_id,type)key.那么可以按id进行查询,也可以按(character_id,type)进行查询。像(character_id,type)这样的,我们可以称做侯选key。这种查询更接近于我们数据库的使用情况,做缓存的意义更大一些,也更加复杂,我们主要就是对其进行讨论。

后面我再详细说如何以统一的接口来定义侯选key.

 

3,如何为查询生成key

 

def makeKey( classA,*args,**kwargs):

    endword = ""

    keys = kwargs.keys()

    keys.sort()

    for key in keys:

        endword += "_"+key

        endword += "%s"%(kwargs[key])

    return classA.__name__+endword

 

 

MakeKey( User,name='123')返回 User_name_123

MakeKey( Item,character_id=1,type=3)( Item,type=3,character_id=1)都返回Item_character_id_1_type_3

 

4,统一的get方法

 

def getFromDBWithId( className,*args, **kwargs ):

    key = makeKey(className,*args, **kwargs )

    value = cache.get(key )

    if( not value ):

        try:

            value = className.objects.get(*args,**kwargs )

        except:

            value = None

        cache.set( key, value )

    return value

 

 

5,何时添加缓存

get不命中时

insert

 

6,何时缓存失效

在任何对缓存进行操作时,缓存失效:delete, update

 

7,update的注意事项

首先这里会有一个前提假设,即数据库的主健id不会发生变化。

即不能user = User(id=123)

user.id = 124

user.save()

一般我们在使用数据库时,都不会修改主健ID。对于侯选健我们一般也不会这样做。

如果侯选健不发生变化,那么update时的操作非常简单:cache.set(key,newValue),重新赋值即可。

如果侯选健发生变化,那上面的办法就行不通了。

试想user = getFromDBWithId(User,name='xxx')

user.name ='ddd'

user.save()

如果用上面的方法,在查询 getFromDBWithId(User,name='xxx')时还会返回数据,而不是返回空

但即侯选健发生了变化,但主健id不会发生变化,我们也可以通过以下的方法来解决上面这个问题:

数据内容仅由idkey的来进行存储,侯选key存储的是与id的一个双向索引。

比如user = User( name='xxx'),其实在内存中有三部分构成:

1,cache.set('User_id_111',user)

2,cache.set('User_id_to_name_111','xxx')

3,cache.set('User_name_to_id_xxx',111)

这样我们再来看上面的情况

 

user = getFromDBWithId(User,name='xxx')

user.name ='ddd'

user.save()

 

save时,我们这样处理,就不会有问题了:

1,oldName = cache.get('User_id_to_name_%s'%user.id) # (oldName='xxx')

2,cache.invalide('User_name_to_id_%s'%oldName)

3,cache.set('User_id_to_name_%s'user.id,user.name)

4,cache.set('User_name_to_id_%s'%user.name,user.id)

5,cache.set('User_id_%s'%user.id,user)

 

8,统一加入缓存

上面我们给出了在User表上加入缓存的方法,当然我们不希望每个表都需要这样写一遍,高举DRY( do not reapeat yourself)的程序员肯定能想到更高明的办法。

切面编程?如果只需要写一个save()函数,然后注册的类,在更新表项时,都会被其改写,你只需要在外面配置哪些表需要加入cache,而完全不用从内部对其进行任务改写,这样会不会听上去很酷?

python切面编程的库有很多,我这里使用的aspects

1,这里我们需要每个表下定义一个CACHE_KEY(即我们的侯选key)

class User( models.Model ):

    name        = models.CharField( max_length=20 )

    password    = models.CharField( max_length=32 )

 

    CACHE_KEY = ["name"]

我们来定义我们想重用的delete

 

def newDelete(self):

    className = self.__class__.__name__

    key = className

    for subKey in self.__class__.CACHE_KEY :

       key += "_%s_"%subKey+str(getattr( self,subKey ))

    cache.delete(key)                                 #选移除缓存,再从数据库中移出

    retval = yield aspects.proceed(self)

    yield aspects.return_stop(retval)

 

定义新的Save(如果侯选key内容会变,可以参照第7点进行改动)

 

def newSave(self):

    etval = yield aspects.proceed(self)            #数据库执行update

    className = self.__class__.__name__

    key = className

    for subKey in self.__class__.CACHE_KEY :

       key += "_%s_"%subKey+str(getattr( self,subKey ))

    cache.set(key,self)

    yield aspects.return_stop(retval)

搜索所有的表项,添加上hook

import aspects

 

allClasses = dir()

def registerHook():

    global allClasses

    for elem in allClasses:

       if( globals().has_key(elem) ):

            if( "<class 'django.db.models.base.ModelBase'>" == str(type(globals()[elem]))):

                aspects.with_wrap(newSave, getattr(globals()[elem],"save"))

                aspects.with_wrap(newDelete, getattr(globals()[elem],"delete"))

 (当然你也可以手动定义好,给固定的类加上cache )

 

9,加起来不到100行代码,你已经给你所有的数据库表项添加上了缓存。现在你可以去敲你老板的门了:我刚给数据库讲了一个笑话,它现在冷静了很多

 


 

2
0
分享到:
评论
2 楼 simomo 2010-12-31  
感觉你说的aop和装饰器作用有点像~
1 楼 simomo 2010-12-06  
 
很受启发,受益匪浅~!

相关推荐

    分布式数据库面试专题系列:Memcached+Redis+MongoDB.zip

    分布式数据库在现代互联网行业中...通过深入研究这三个分布式数据库系统,你可以为面试做好充分准备,同时也能在实际工作中更好地应对各种挑战。无论是开发、运维还是DBA,掌握这些知识都将使你在IT行业中更具竞争力。

    memcached缓存数据库

    Memcached是一种基于内存的键值存储系统,设计的目标是快速、简单地存储和检索数据。它通过将数据保存在内存中,避免了硬盘I/O操作,从而实现了极高的读取速度。由于内存的限制,Memcached不适合长期存储大量数据,...

    分布式数据库面试专题系列:Memcached+Redis+MongoDB.rar

    它主要用于减轻数据库的负载,通过将数据暂存到内存中,实现快速读取。Memcached的特点包括轻量级、无持久化、单线程模型。在面试中,你可能需要了解其数据结构(如哈希表)、内存管理机制(如 slab allocator)以及...

    分布式数据库面试专题系列:Memcached+Redis+MongoDB-06.rar

    在这个面试专题系列中,我们将聚焦于三个广受欢迎的分布式数据库技术:Memcached、Redis和MongoDB。 1. **Memcached**: - **简介**:Memcached是一款高性能、分布式内存对象缓存系统,用于减轻数据库负载,提升...

    memcached分布式缓存数据库部署.doc

    《深入理解memcached分布式缓存数据库部署》 memcached,作为一款高性能的分布式缓存服务器,它的主要任务是缓存数据库查询结果,从而减少对数据库的访问,进而提升动态Web应用的响应速度。这一技术的广泛应用,...

    memcached缓存数据库jar包

    **memcached缓存数据库jar包** `memcached`是一种高性能、分布式内存对象缓存系统,它广泛用于减轻数据库负载,提高Web应用的响应速度。它通过在内存中存储数据,提供快速的数据访问,从而减少了对数据库的直接访问...

    memcached缓存数据库应用实践1

    它减轻了数据库的压力,提供了快速的数据访问,同时在session管理方面提供了安全且高效的解决方案。企业可以根据自身需求选择合适的应用场景,结合其他技术如Redis,实现更灵活、更强大的数据缓存策略。在使用...

    memcached-win32-1.4.4-14内存数据库

    Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载。它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提高动态、数据库驱动网站的速度。Memcached基于一个存储键/值对的...

    memcached 64位 window

    它设计用于通过网络在不同应用之间快速共享小块数据,如数据库查询结果。Memcached的工作原理是将数据存储在内存中,避免了频繁读写硬盘导致的I/O延迟,从而提高了数据访问速度。由于其简单的设计和高效的性能,...

    memcached服务器端memcached.exe 下载

    Memcached是一款高性能、分布式内存对象缓存系统,常用于减轻数据库负载,提高Web应用的性能。它通过在内存中存储数据来快速...通过合理地利用memcached,开发者可以优化Web应用性能,减少数据库压力,提高用户体验。

    Memcached 1.4.13(Windows 32/64)最新稳定版

    是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载。 以下是 memcached 在 Windows 系统下的 x86/x64 版本的安装方法。 命令提示符下运行 安装: memcached -d install memcached -d ...

    memcached安装软件 libevent magent memcached

    Memcached是一款高性能、分布式内存对象缓存系统,广泛应用于Web应用中,用于减轻数据库的负载。它通过在内存中存储数据来提供快速的数据访问,从而提高应用的性能。本篇文章将详细讲解如何安装和配置memcached,...

    oracle掉用memcached,得用oracle调用java,java调用memcached

    总之,这个解决方案展示了如何巧妙地利用Java作为桥梁,使Oracle数据库能够与Memcached缓存服务协同工作,优化数据访问效率。这种集成技术是现代企业级应用中常见的实践,有助于构建更加高效和可扩展的系统。

    memcached整合hibernate资源合集

    通过学习这些资源,开发者能够更好地掌握如何在实际项目中应用Memcached和Hibernate的整合,提升系统的响应速度和并发处理能力。 此外,了解如何整合Memcached和Hibernate也是提升系统架构设计能力的重要一步。在高...

    Memcached v1.5.7 For Windows (附带Memcached和libevent源码两个版本)

    Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载。它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提高动态、数据库驱动网站的速度。Memcached基于一个存储键/值对的...

    C#使用memCached实现缓存

    C#使用memCached实现缓存 Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载。它通过在内存中缓存数据和对象来...Memcached将数据库负载大幅度降低,更好的分配资源,更快速访问。

Global site tag (gtag.js) - Google Analytics