英文对照 介绍Play Framework 框架 缓存

lyuehh 发布于 2010/08/08 13:48
阅读 1K+
收藏 5

使用缓存

h1. Use a cache

 

去创建一个高性能的系统,有时候你需要使用缓存数据。Play有一个缓存的库,当需要在分布式的系统中使用时,用的是memcached。

To create high-performance systems, sometimes you need to cache data. Play has a cache library and will use "memcached":http://www.danga.com/memcached/ when used in a distributed environment.

 

如果你不配置memcached,Play会使用独立的缓存,将数据存放在JVM的堆中。

将缓存存放在JVM的应用违反了Play的“无共享”假定:你不能在多个服务器上运行你的应用,期望这些应用的行为保持一致。

每一个应用实例会有一个不同的数据拷贝。

If you don’t configure memcached, Play will use a standalone cache that stores data in the JVM heap. Caching data in the JVM application breaks the "share nothing" assumption made by Play: you can’t run your application on several servers, and expect the application to behave consistently. Each application instance will have a different copy of the data.

 

了解缓存的特点很重要:当你把数据放进缓存里的时候,你不能期望数据永远保持在那里。实际上,你不应该期望。

缓存很快,但是数据会失效,而且缓存通常只存在在内存里(如果没有持久化备份的话)。

It is important to understand that the cache contract is clear: when you put data in a cache, you can’t expect that data to remain there forever. In fact you shouldn’t. A cache is fast, but values expire, and the cache generally exists only in memory (without persistent backup). 

 

所以使用缓存最好的办法是在你不需要它的时候清空它。

So the best way to use the cache is to repopulate it when it doesn’t have what you expect:

 

bc. public static void allProducts() {

    List<Product> products = Cache.get("products", List.class);

    if(products == null) {

        products = Product.findAll();

        Cache.set("products", products, "30mn");

    }

    render(products);

}

 

缓存API

h2. <a>The cache API</a>

 

缓存API是由类play.cache.Cache提供的,这个类包含了一系列的方法,可以设定,替换,得到缓存中的值。参考memcached文档区了解每个方法的确切行为。

The cache API is provided by the **play.cache.Cache** class. This class contains the set of methods to set, replace, and get data from the cache. Refer to the memcached documentation to understand the exact behavior of each method.

 

一些例子:

Some examples:

 

bc. public static void showProduct(String id) {

    Product product = Cache.get(id, Product.class);

    if(product == null) {

        product = Product.findById(id);

        Cache.set("product_"+id, product, "30mn");

    }

    render(product);

}

 

public static void addProduct(String name, int price) {

    Product product = new Product(name, price);

    product.save();

    showProduct(id);

}

 

public static void editProduct(String id, String name, int price) {

    Product product = Product.findById(id);

    product.name = name;

    product.price = price;

    Cache.set("product_"+id, product, "30mn");

    showProduct(id);

}

 

public static void deleteProduct(String id) {

    Product product = Product.findById(id);

    product.delete();

    Cache.delete("product_"+id);

    allProducts();

}

 

一些有前缀safe的方法,如safeDelete,safeSet等,这些方法是不闭塞的,意味着当你调用这些方法时,

Some methods start with the **safe** prefix - e.g. **safeDelete**, **safeSet**. The standard methods are non-blocking. That means that when you issue the call:

 

bc. Cache.delete("product_"+id);

 

delete方法会立即返回,不会等待,直到缓存对象实际上删掉。所以如果有个错误发生了,例如发生了一个IO错误,那么对象还会一直存在。

The **delete** method will return immediately and will not wait until the cached object is actually deleted. So if an error occurs - e.g. an IO error - the object may still be present.

 

当你需要在继续之前确认对象已经删掉了,你可以使用safeDelete方法。

When you need to make sure that the object is deleted before continuing, you can use the **safeDelete** method:

 

bc. Cache.safeDelete("product_"+id);

 

这个方法会被阻塞,并返回一个boolean值来表明对象是否被删掉了。所以完整的确认项是否从缓存中被删除的代码块是:

This method is blocking and returns a boolean value indicating whether the object has been deleted or not. So the full pattern that ensures an item is deleted from the cache is:

 

bc. if(!Cache.safeDelete("product_"+id)) {

    throw new Exception("Oops, the product has not been removed from the cache");

}

...

 

请注意这些被阻塞的方法,会减慢你的应用,所以只在需要的时候使用。

Note that those being blocking calls, **safe** methods will slow down your application. So use them only when needed.

 

不要将Session当做缓存

h2. <a>Don’t use the Session as a cache!</a>

 

如果你从一个使用内存储Session的实现的框架中过来,你可能会沮丧的看到Play只允许你使用一个很小的字符串集合存储在HTTP Session中。但是这样更好,因为session不是缓存你的应用的数据的地方。

If you come from a framework that uses an in-memory Session implementation, you may be frustrated to see that Play allows only a small set of String data to be saved in the HTTP Session. But this is much better because a session is not the place to cache your application data! 

 

如果你习惯于使用类似下面的事情:

So if you have been accustomed to doing things similar to:

 

bc. httpServletRequest.getSession().put("userProducts", products);

...

// and then in subsequent requests

products = (List<Product>)httpServletRequest.getSession().get("userProducts");

 

在Play中你需要获得同样的效果的方法有一点不同,我们认为那样更好

In Play you achieve the same effect a little differently. We think it’s a better approach:

 

bc. Cache.put(session.getId(), products);

...

// and then in subsequent requests

List<Product> products = Cache.get(session.getId(), List.class)

 

这里我们使用了一个唯一的UUID在缓存中为每一个用户保存唯一的信息,请记住,不同于session对象,缓存对于每一个用户是不受约束的。

Here we have used a unique UUID to keep unique information in the Cache for each user. Remember that, unlike a session object, the cache in not bound to any particular User!

 

配置memcached

h2. <a>Configure memcached</a>

 

但你需要激活memcached的实现时,修改你的application.conf文件。

When you want to enable a real memcached implementation, enable memcached and define the daemon address in your **application.conf**:

 

bc. memcached=enabled

memcached.host=127.0.0.1:11211

 

你可以连接到一个分布式的缓存系统中去定义多个地址

You can connect to a distributed cache by specifying multiple daemon addresses: 

 

bc. memcached=enabled

memcached.1.host=127.0.0.1:11211

memcached.2.host=127.0.0.1:11212

加载中
返回顶部
顶部