Storing non-simple types in nginx shared memory

660 views
Skip to first unread message

Mindez

unread,
Jun 16, 2016, 3:46:32 PM6/16/16
to openresty-en
Hi all,

I have a question about storing lua tables in nginx shared memory. As part of the init_by_lua script, I created a complex object using a lot of nested tables, and need to be able to read from this object on each request.

I've defined an ngx.shared.dict called Foo and in the init script, I set Foo.thing equal to the table that I want to store in nginx shared memory:

Defining ngx.shared.dict:
lua_shared_dict Foo 1m;

In the init script:
local Foo = ngx.shared.Foo;
local newThing = Thing:create();
...
Foo.thing = newThing;

On request:
local Foo = ngx.shared.Foo;
...
Foo.thing:lookup(Bar);
...

All seems to work absolutely fine, and I can get ngx.shared.Foo.tree and lookup values from the worker processes on request, but having read up on it I realise that this is very much not how ngx.shared.dict is supposed to work, which is meant to just be simple key-value pair storage. So my question is: Is this supposed to work? And if not, is this highly likely to break at some point? As I say, all works perfectly as I'd expect, but wanted to know if there may be non-obvious subtleties that may break it.

Alternatively, is there a cleaner way to store non-simple lua types in nginx shared memory, since tables can't be stored in a key-value pair?

Please bear with me, I'm a little bit new to Lua. :)

Robert Paprocki

unread,
Jun 16, 2016, 4:26:48 PM6/16/16
to openre...@googlegroups.com
Hi,

You may want to take a look at https://github.com/openresty/lua-nginx-module#data-sharing-within-an-nginx-worker, particularly if this is read-only data.

Rather than rely on shared k/v storage, instantiate your data as part of a separate module, then access that when necessary (and if it's initialized by the master process as part of init_by_lua as opposed to init_worker, you'll enjoy COW memory benefits).

--
You received this message because you are subscribed to the Google Groups "openresty-en" group.
To unsubscribe from this group and stop receiving emails from it, send an email to openresty-en...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Mindez

unread,
Jun 17, 2016, 3:57:30 AM6/17/16
to openresty-en, rob...@cryptobells.com
Thanks for the response.

So if I create a FooThing module that does nothing but create a Foo object, and have:

local thing = require("FooThing");
thing
.createFoo();

in the init_by_lua script, does that mean it'll be initialized by the master process such that all worker processes will have access to it, or will each worker process then have to re-create it when they first handle a request? The object is quite costly performance-wise to create, which is why it has to be done as a one-off on reload.

Jim Robinson

unread,
Jun 17, 2016, 6:27:27 PM6/17/16
to openresty-en
Have you ever considered whether or not it'd make sense to use memcache?  I was building a custom caching solution and decided to use a memcache cluster to store the data, and to use the lua library cmsgpack to serialize the data structures I was storing.  The support the openresty has for memcache made it trival to handle that portion of the logic.

Robert Paprocki

unread,
Jun 17, 2016, 6:59:36 PM6/17/16
to openre...@googlegroups.com
Wouldn't using memcached be the exact same thing as using shared dict storage, except for latent and expensive? ;)

On Fri, Jun 17, 2016 at 3:27 PM, Jim Robinson <jim.ro...@gmail.com> wrote:
Have you ever considered whether or not it'd make sense to use memcache?  I was building a custom caching solution and decided to use a memcache cluster to store the data, and to use the lua library cmsgpack to serialize the data structures I was storing.  The support the openresty has for memcache made it trival to handle that portion of the logic.

Bojan Djulbic

unread,
Jun 7, 2019, 4:16:58 PM6/7/19
to openresty-en
Hi, I am having similar issue as you did. I know it has been 3 years since the message but there is not a lot in documentation about this.
Did you ever figure out this things - Is using a table across modules thread-safe?
Thanks

kip...@gmail.com

unread,
May 5, 2021, 7:23:37 AMMay 5
to openresty-en
For storing tables (nested or not) in Nginx shared memory to share them between workers - you can look at https://github.com/helloyi/ngx-lua-shrbtree-module

Note that it can only store numbers, strings, booleans and tables (not functions or userdata).
It is supposed to be thread-safe (so worker safe), because it locks the tree for every read and write. You may want to check performance, but from what i recall it is quite good. Also you should minimize calls to such APIs anyway, retrieve the data once per-request into your Lua code and then use it there.

Internally, when storing Lua data it does nested traversal of the provided Lua tables to copy data out of them into its internal red-black tree structure for storage. And when retrieving it copies it back out. Effectively for every retrieval you get a new Lua table, so there is a bit of overhead, but it isn't noticeable if your tables aren't super huge . YMMV.
Reply all
Reply to author
Forward
0 new messages