缓存

在项目中,合理使用缓存对性能有很大的帮助。thinkjs提供了方便的缓存方式,包括:内存缓存、文件缓存、memcache缓存等。同时提供了快捷的方法进行缓存的读取操作。

数据缓存

在thinkjs中进行缓存的读取操作,一般情况下不要直接操作缓存类,系统提供了快捷函数 S 来进行操作。

缓存配置

  1. //缓存配置
  2. cache_type: "File", //数据缓存类型
  3. cache_timeout: 6 * 3600, //数据缓存有效期,单位: 秒
  4. cache_path: CACHE_PATH, //缓存路径设置 (File缓存方式有效)
  5. cache_file_suffix: ".json", //File缓存方式下文件后缀名
  6. cache_gc_hour: [4], //缓存清除的时间点,数据为小时

缓存类型

内存缓存

使用Node.js的内存来缓存,如果使用cluster最好不要使用该方式。

  1. cache_type: "", //cache_type为空
文件缓存

基于文件的缓存

  1. cache_type: "File", //cache_type为File
Memcache缓存

使用Memache来缓存

  1. cache_type: 'Memcache', //cache_type为Memcache

使用Memache来缓存需要追加如下的配置:

  1. //memcache缓存
  2. memcache_host: "127.0.0.1", //memcache host
  3. memcache_port: 11211, //memecache端口
Redis缓存

使用Redis来缓存

  1. cache_type: 'Redis', //cache_type为Redis

使用Redis来缓存需要追加如下的配置:

  1. //redis缓存
  2. redis_host: "127.0.0.1", //redis host
  3. redis_port: 6379, //redis端口

缓存读写

  1. //写入缓存
  2. S("name", "welefen"); //返回一个promise
  3. //读取缓存
  4. S("name").then(function(value){
  5. //value为获取到的缓存值
  6. });
  7. //删除缓存
  8. S("name", null);
  9. //缓存写入时改变缓存类型和缓存时间
  10. S("name", "value", {
  11. type: "memcache",
  12. timeout: 100 * 10000
  13. });
  14. //修改缓存类型来获取缓存值
  15. S("name", undefined, {
  16. type: "memcache"
  17. }).then(function(value){
  18. })

缓存的读、写、删都是异步操作,都是返回一个promise。后续的操作如果有依赖,必须在promise then里执行。

文件快速缓存

如果有些数据不会过期,只会被新的数据覆盖。那么使用S函数就不太合适了,系统提供一种不会过期的数据快速存取方法。

可以通过函数 F 来对文件内容进行快速的读取和写入操作。文件快速写入和读取的根目录为 App/Runtime/Data/

  1. //数据快速写入
  2. F("name", {value: "xxx"}); //写入的文件为 App/Runtime/Data/name.json
  3. //数据读取
  4. var value = F("name");
  5. //重新指定数据写入的根目录
  6. F("name", {value: "xxx"}, "/tmp/data"); //写入的文件为 /tmp/data/name.json
  7. //数据读取
  8. var value = F("name", undefined, "/tmp/data");

文件快速缓存的读、写操作都是同步的。

数据库查询缓存

对于及时性要求不高的数据查询,可以使用查询缓存来提高性能。系统里提供了cache方法来对查询数据缓存,无需自己使用缓存方法进行缓存和读取。

数据库查询缓存有如下的配置:

  1. //数据库查询缓存配置
  2. db_cache_on: true, //是否启用查询缓存,如果关闭那么cache方法则无效
  3. db_cache_type: "", //缓存类型,默认为内存缓存
  4. db_cache_path: CACHE_PATH + "/db", //缓存路径,File类型下有效
  5. db_cache_timeout: 3600, //缓存时间,默认为1个小时
  1. //查询score>100的数据
  2. D('User').cache(true).where({score: ['>', 100]}).select().then(function(data){
  3. //开启查询缓存后,如果有缓存则直接读取缓存,不再从数据库查询
  4. })

如果使用了cache(true),则在查询的时候会根据当前拼装的sql生成md5值作为缓存key。也可以手工指定缓存key,如:

  1. D('User').cache('cache_name').select().then(function(data){
  2. //data
  3. })

也可以指定单条查询的的缓存时间,如:

  1. //手工将缓存时间修改为3个小时
  2. D('User').cache(3 * 3600).select().then(function(){});
  3. //手工指定缓存key并修改缓存时间
  4. D('User').cache('cache_name', 3 * 3600).select().then(function(){});

如果指定了缓存key,那么在外部可以通过S函数来读取缓存,如:

  1. //如果缓存类型和通用的缓存类型不同,那么这里需要带上缓存类型进行读取
  2. S('cache_name').then(function(data){
  3. })

页面静态化

对于项目中的有些数据,如:文章详细页,这些数据一旦生成后就不怎么修改了。为了更快的提高文章详细页的访问速度,可以将文章详细页面整个缓存起来,下次访问的时候如果还在缓存时间内,那么直接读取静态html返回即可。

这种方式下不用执行控制器、数据库查询、模版渲染等操作了,可以大大提高访问的性能。

如果页面中显示用登录信息,这种方式就不太适合了,除非用户登录信息通过异步接口来获取。

要使用页面静态化的功能,需要开启配置html_cache_on,并且配置html_cache_rules规则来控制哪些请求才启动页面静态化的功能。

详细配置

页面静态化缓存只能使用文件缓存的方式,详细的配置如下:

  1. //页面静态化配置
  2. html_cache_on: false, //HTML静态缓存
  3. html_cache_timeout: 3600, //缓存时间,单位为秒
  4. html_cache_rules: {}, //缓存详细的规则
  5. html_cache_path: CACHE_PATH + "/html", //缓存目录
  6. html_cache_file_callback: undefined, //由缓存key生成具体的缓存文件的回调函数
  7. html_cache_file_suffix: ".html", //缓存文件后缀名

缓存的规则如下:

  1. //缓存规则
  2. "html_cache_rules": [
  3. "静态地址": ["静态规则", "缓存时间", "生成缓存文件的回调函数"],
  4. "静态地址": "静态规则"
  5. ]

静态地址

静态地址是用来匹配当前的路由规则,匹配的静态地址列表为:

  1. //静态地址匹配列表
  2. var list = [
  3. group + ":" + controller + ":" + action,
  4. controller + ":" + action,
  5. action,
  6. "*"
  7. ];

如果这时候访问的url为group/detail?id=10,识别到的分组为home, 控制器为group,操作为detail,那么静态地址可以配置为home:group:detail,这样就命中了当前的请求。

当前也可以配置更泛的规则来匹配。

静态规则

静态地址是命中一组类似的请求,如果这组类似的请求生成的缓存文件是一样的,那肯定不行。

可以通过静态规则来区别不同的请求,静态规则里可以获取当前请求的动态数据。如:

  1. //静态规则
  2. //动态获取参数id的值
  3. "home:group:detail": "home_group_detail_{id}"

可以获取的动态数据有:

  • {key} 获取参数key的值,如:{id}, {page}
  • {:group} 获取分组
  • {:controller} 获取控制器
  • {:action} 获取操作
  • {cookie.key} 获取cookie下key的值,如:{cookie.skin}

通过这些动态数据就可以将每个不同的请求都区分开来。

缓存文件回调函数

静态规则一般都是一个较长的字符串,如果直接拿这个字符串当文件名去生成缓存文件,可以导致缓存目录下的文件数过多。这时候我们可能希望建立一些子目录来放这些缓存文件,通过回调函数可以确立详细的缓存文件存在路径。

默认的缓存文件存放路径对应的函数为:

  1. //生成缓存文件的函数
  2. var getCacheFilename = function(key){
  3. var value = md5(key);
  4. //这里生成一级子目录
  5. return value[0] + "/" + value;
  6. }

如果想重新定义生成缓存文件的函数,可以修改配置html_cache_file_callback, 如:

  1. 'html_cache_file_callback': function(key, http){
  2. var value = md5(key);
  3. //生成二级子目录
  4. return value[0] + "/" + value[1] + "/" + value;
  5. }

也可以修改某个特定的静态规则下的回调函数,直接配置规则里第二个参数即可。