07 秒杀系统 | 多级查询缓存 | 基于 Lua & Nginx 的 Shared Dic 做前置缓存

Shared Dic

  • Nginx 的 Shared Dic 是对所有 Worker 进程可见的,共享内存字典,当共享内存空间用完了之后,采用 LRU 淘汰算法;

配置 Shared Dic

  • 修改 nginx.conf,http 节点下添加:
lua_shared_dict my_cache 128m;

    
  • 创建脚本 itemshareddic.lua

    
  1. function get_from_cache(key)
  2. local cache_ngx = ngx.shared.my_cache
  3. local value = cache_ngx:get(key)
  4. return value
  5. end
  6. function set_to_cache(key, value, exptime)
  7. if not exptime then
  8. exptime = 0
  9. end
  10. local cache_ngx = ngx.shared.my_cache
  11. local succ, err, forcible = cache_ngx:set(key, value, exptime)
  12. return succ
  13. end
  14. local args = ngx.req.get_uri_args();
  15. local id = args[ "id"]
  16. local item_model = get_from_cache( "item_"..id)
  17. if item_model == nil than
  18. local resp = ngx.location.capture( "/item/get?id="..id)
  19. item_model = resp.body
  20. set_to_cache( "item_"..id, item_model, 1* 60)
  21. end
  22. ngx.say(item_model)
  • 修改 nginx.conf,在 server 节点下添加:

    
  1. location /luaitem/get {
  2. default_type "application/json";
  3. content_by_lua_file ../lua/itemshareddic.lua;
  4. }
  • 重启 nginx
sudo sbin/nginx -s reload

    

验证 Shared Dic

  • 多次访问 localhost/luaitem/get?id=2,只有第一次请求能打到 Tomcat;

性能提升

  • TPS 可以达到 3700(2核8G),和全部命中 Tomcat 的本地热点缓存比还慢了点,但是比 Nginx 的 proxy_cache 性能提升了很多;

设计考量

  • 采用 Shared Dic,可以免除 Nginx 到 Tomcat 的 RPC 调用,但是应用的负载全不到了 Nginx 上,并且会造成短时间的脏读,如果从后向前更新 Nginx 的 Shared Dic 会更加的麻烦;
  • 用 Nginx 的 Shared Dic 做前置缓存是当前的热点做法;
  • 用 Nginx 的 Shared Dic 做前置缓存的更新机制不太好,只能设置淘汰时间;