打造高性能站点

http://robbin.iteye.com/  ---Robbin的博客
http://robbin.iteye.com/blog/77338  ---为什么ORM性能比iBatis好?
http://bentley.blogbus.com/logs/22138875.html  --Django缓存

CACHE_BACKEND = 'memcached://127.0.0.1:11211/'
Memcached的一个极好的特性是它在多个服务器分享缓存的能力,这意味着你可以在多台机器上运行Memcached进程,程序将会把这组机器当作一个单独的缓存,而不需要在每台机器上复制缓存值
CACHE_BACKEND = 'memcached://172.19.26.240:11211;172.19.26.242:11211/'
Memcached的是基于内存的缓存有一个重大的缺点,因为缓存数据只存储在内存中,则如果服务器死机的话数据会丢
失,显然内存不是为持久数据存储准备的

==
数据库缓存
  在你的数据库创建缓存表,并在表里指出Django的缓存系统来使用数据库表作为缓存后端

文件系统缓存
   CACHE_BACKEND = 'file:///var/tmp/django_cache'
本地缓存器缓存
   CACHE_BACKEND = 'locmem:///'
简单缓存(开发用)
   CACHE_BACKEND = 'simple:///'
假缓存(开发用)
   CACHE_BACKEND = 'dummy:///'

CACHE_BACKEND = "locmem:///?timeout=30&max_entries=400"

整站点缓存

视图缓存
一个更细粒度的使用缓存框架的方式是缓存单独视图的输出.
from django.views.decorators.cache import cache_page  
 
@cache_page(60 * 15)  
def my_view(request, param):

视图缓存和URL有关,如果多个URLs指向同一视图,则每个URL将被单独缓存,
    urlpatterns = ('',  
        (r'^foo/(\d{1,2})/$', my_view),  
    ) 
则对/foo/1/和/foo/23/的请求将像你期望的那样被单独缓存,但是一旦一个特别的URL(例如/foo/23/)被请求,则该URL后续
的请求将使用缓存. 在URL配置里指定视图缓存而不是在视图方法本身附近,你可能想重用视图方法到另一个很少缓存的站点,或者你可能想发布视图给那些可
能想不用缓存来使用它们的人.

urlpatterns = ('',  
    (r'^foo/(\d{1,2})/$', cache_page(my_view, 60 * 15)),  
)  

低级缓存API:
from django.core.cache import cache 
>>> cache.set('my_key', 'hello, world!', 30)  
>>> cache.get('my_key') 

如果缓存中对象不存在,或者缓存后端不可得到,则cache.get()返回None:

# Wait 30 seconds for 'my_key' to expire...  
 
>>> cache.get('my_key')  
None

建议不要在缓存中存储字面上的None,因为你不能区别你存储的None值和通过返回None值表示的缓存缺失
cache.get()可以使用一个default参数,它指定了如果对象在缓存中不存在时的返回值:
    >>> cache.get('my_key', 'has expired')  
    'has expired' 

    >>> cache.set('a', 1)  
    >>> cache.set('b', 2)  
    >>> cache.set('c', 3)  
    >>> cache.get_many(['a', 'b', 'c'])  
    {'a': 1, 'b': 2, 'c': 3} 

====
from django.views.decorators.vary import vary_on_headers
# Python 2.4+ decorator syntax.  
@vary_on_headers('User-Agent')  
def my_view(request):  
    # ... 

这种情况下,缓存机制(例如Django自己的缓存中间件)将对每个唯一的user-agent缓存单独版本的页面
使用vary_on_headers装饰器而不是手动设置Vary头部(使用类似于response['Vary'] = 'user-agent')的优势是装饰器添加
到Vary头部(可能已经存在)而不是从零开始设置它并潜在的覆盖已经在那里的东西
你可以传递多个头部到vary_on_headers():

这两个视图是相等的:
    @vary_on_cookie 
    def my_view(request):  
        # ...  
     
    @vary_on_headers('Cookie')  
    def my_view(request):  
        # ... 

===缓存使用策略
在项目中的具体应用策略(也就是哪些数据应该缓存?怎么样缓存?过 期策略?)
总原则是将经常需要从数据库读取的数据缓存在memcached中。
这些数据也分为几类:
一、经常被读取并且实时性要求不强可以等到自动过期的数据。例如网站首页最新文章列表、某某排行等数据。也就是虽然新数据产生了,但对用户体验不会产生任何影响的场景。
这类数据就使用典型的缓存策略,设置一过合理的过期时间,当数据过期以后再从数据库中读取。当然你得制定一个缓存清除策略,便于编辑或者其它人员能马上看到效果。
二、经常被读取并且实时性要求强的数据。比如用户的好友列表,用户文章列表,用户阅读记录等。
这类数据首先被载入到memcached中,当发生更改(添加、修改、删除)时就清除缓存。在缓存的时候,我将查询的SQL语句md5()得到它的 hash值作为key,结果数组作为值写入memcached,并且将该SQL涉及的table_name以及hash值配对存入memcached中。 当更改了这个表时,我就将与此表相配对的key的缓存全部删除。
三、统计类缓存,比如文章浏览数、网站PV等
此类缓存是将在数据库的中来累加的数据放在memcached来累加。获取也通过memcached来获取。但这样就产生了一个问题,如果 memcached服务器down掉的话这些数据就有可能丢失,所以一般使用memcached的永固性存储,这方面我们新浪使用memcachedb。
四、活跃用户的基本信息或者某篇热门文章。
此类数据的一个特点就是数据都是一行,也就是一个一维数组,当数据被update时(比如修改昵称、文章的评论数),在更改数据库数据的同时,使用Memcache::replace替换掉缓存里的数据。这样就有效了避免了再次查询数据库。
六、session数据
使用memcached来存储session的效率是最高的。memcached本身也是非常稳定的,不太用担心它会突然down掉引起session数据的丢失,即使丢失就重新登录了,也没啥。见[多服务器session共享之memcache共享]
【总结】
通过以上的策略数据库的压力将会被大大减轻。检验你使用memcached是否得当的方法是查看memcached的命中率。有些策略好的网站的命中率可以到达到90%以上。

猜你喜欢

转载自dlooto.iteye.com/blog/1458849