补充一下,关于lua_shared_dict在内存还充足的情况下写入失败的概率较大的问题,可能是由于nginx的slab内存分配存在碎片严重的问题,导致实际可用内存越来越小。参考:https://groups.google.com/forum/#!topic/openresty/9F9_OBtiA2E 这里的解决方案,在我的nginx 1.4.7上打上 https://raw.githubusercontent.com/openresty/ngx_openresty/master/patches/nginx-1.7.0-slab_defrag.patch
这个patch后,通过nginx-systemtap-toolkit查看总大小50m的内存,写满后free memory基本保持在3M左右,内存碎片的问题基本解决,同时写入失败的概率大幅下降至 2% 左右。
目前的遗留的问题是: 这2%的失败原因是否是由于移除多个元素后空间仍然不够导致的?如下描述中:
When it fails to allocate memory for the current key-value item, then set will try removing existing items in the storage according to the Least-Recently Used (LRU) algorithm. Note that, LRU takes priority over expiration time here. If up to tens of existing items have been removed and the storage left is still insufficient (either due to the total capacity limit specified by lua_shared_dict or memory segmentation), then the err return value will be no memory and success will be false.
谢谢!
-----邮件原件-----
发件人: openresty@googlegroups.com [mailto:openresty@googlegroups.com] 代表 Ralin Yuan
发送时间: 2015年3月26日 11:42
收件人: openresty@googlegroups.com
主题: 答复: [openresty] 关于lua_shared_dict的问题
感谢 @agentzh 的答复,还有一个小疑问,lua_shared_dict是基于红黑树+自旋锁实现,看源码好像是每次set和get操作都会针对整棵树上锁,而不是基于插入的key的锁吧?
另外,我们在测试时发现,当内存写满后,再set时会存在有些失败的情况(ngx_slab_alloc() failed: no memory in lua_shared_dict zone),我们的统计:
1. 当memory未写满时,全部可以写入成功(包括大于page cache的元素,因此排除之前发现的nginx core的bug);
2. 写满再set,写入失败和写入成功的比例大概是1:2。
目前不太确定失败原因,我看到wiki上关于set操作的介绍 http://wiki.nginx.org/HttpLuaModule#ngx.shared.DICT.set,其中有一句:;
When it fails to allocate memory for the current key-value item, then set will try removing existing items in the storage according to the Least-Recently Used (LRU) algorithm. Note that, LRU takes priority over expiration time here. If up to tens of existing items have been removed and the storage left is still insufficient (either due to the total capacity limit specified by lua_shared_dict or memory segmentation), then the err return value will be no memory and success will be false.
好像是说:当通过LRU去淘汰数据时,如果remove掉10个元素内存还是不够的话仍然会抛出 no memory的异常,想确认下我上面写入失败的原因是否可能是由于这个策略导致的呢?谢谢!
-----邮件原件-----
发件人: openresty@googlegroups.com [mailto:openresty@googlegroups.com] 代表 Yichun Zhang (agentzh)
发送时间: 2015年3月26日 3:12
收件人: openresty
主题: Re: [openresty] 关于lua_shared_dict的问题
Hello!
2015-03-24 23:36 GMT-07:00 Ralin Yuan:
> 同时也提到过: “lua_shared_dict是通过紅黑树+自旋鎖来达成的,当并发增大或是更新量增大时,
> 自旋鎖可能有问题”。我们的业务数据在lua_shared_dict只有插入、高频访问和LRU自动淘汰、没有更新操作,
>
> 因此不太确定是否lua_shared_dict适用于我们的业务场景。各位是否有这方面的使用经验?
>
即使是较大的数据量(GB 级)和较多的 nginx worker
数(十几个),共享内存字典一般也不会成为真正的性能问题。最简单的验证方法是按照你们实际的数据量和访问模式进行 benchmark(同时使用
on-CPU 和 off-CPU 火焰图验证 benchmark 的结果,以避免低级错误)。
即使锁真的成为瓶颈,也可以通过对单个共享内存字典自己进行水平切分,在一个 nginx server 内部定义多个
lua_shared_dict 自己进行 hash 分发来规避。
Regards,
-agentzh
--
--