18 | worker间的通信法宝:最重要的数据结构之shared dict
该思维导图由 AI 生成,仅供参考
数据共享的几种方式
- 深入了解
- 翻译
- 解释
- 总结
OpenResty中的shared dict是一种重要的数据结构,支持存储、读取、原子计数和队列操作。在编写OpenResty Lua代码时,常见的数据共享方式包括Nginx中的变量、ngx.ctx、模块级别的变量和shared dict。shared dict基于红黑树实现,性能良好,可以在多个worker之间共享数据。然而,它只能缓存字符串类型的数据,不支持复杂的Lua数据类型。共享字典提供了20多个Lua API,包括字典读写类、队列操作类和管理类,这些API都是原子操作。队列操作类提供了类似Redis的接口,包括lpush/rpush、lpop/rpop和llen等操作。管理类API是后续新增的功能,包括get_keys、capacity和free_space等,用于管理共享内存的使用情况。了解shared dict的API和官方文档对工程师和架构师至关重要,通过shared dict可以实现worker间的缓存和通信,以及限流限速、流量统计等功能。
《OpenResty 从入门到实战》,新⼈⾸单¥59
全部留言(17)
- 最新
- 精选
- helloworld老师有两个问题请教: 1. ngx.var API是否是lua代码和Nginx C模块之间共享数据的唯一方法?有其他方法吗 2. 关于ngx.ctx,官方文档也提到说这个API 的查询也相对有点昂贵:"The ngx.ctx lookup requires relatively expensive metamethod calls and it is much slower than explicitly passing per-request data along by your own function arguments.",如果这样是否还能说ng.ctx速度很快呢 另外补充一个文中未提到的,ngx.var可以在子请求中有效,也就是说可以跨location使用,而ngx.ctx不可以。
作者回复: 其他的方式就是借助外部的储存了,比如 memcached 扥。 ngx.ctx 的快是相对于 ngx.var 而言的。 多谢补充,ngx.ctx 确实不能跨 location,有一个库 lua-resty-ctxdump 可以解决这个问题。
2019-07-2422 - HelloBug温铭老师,你好~有以下一些问题想请教一下~ 1.ngx.var变量的作用域在nginx C模块之间、nginx C和lua-nginx-module模块之间。这个不太理解,从请求的角度来看,是一个工作进程中的单个请求吗? 2.文中有描述ngx.ctx是一种昂贵的调用,是虽然ngx.ctx访问速度快,但ngx.ctx在每一个请求中都会占据内存空间的昂贵吗?还有一个问题,ngx.ctx占据的内存空间的大小是动态增长的还是有大小限制的呢? 3.操作模块内的变量时,如果两个操作之间有阻塞操作,可能出现竞争。如果两个操作之间没有阻塞操作,恰好CPU时间到,当前进程进入就绪队列,也可能产生竞争的对吧?
作者回复: 1. 是的,ngx.var 的生命周期和请求一致,请求结束它也就消失了。它的优势是数据可以在 C 模块和 Lua 代码中传递。 2. 原文中没有提到 ngx.ctx 是昂贵的操作吧?可能是我没有表达清楚,是我们会用 ngx.ctx 来替代 ngx.var 这种昂贵的操作,后者才是昂贵的。 3. 两个操作之间有 `yield 操作`,可能出现竞争,而不是`阻塞操作`,有阻塞操作是不会出现竞争的。只要不把主动权交给 Nginx 的事件循环,就不会有竞争。
2019-07-0722 - zyonlinelocal ngx = ngx local function bar() ngx_ctx.host = 'test.com' end 中 ngx_ctx.host = 'test.com' 是不是应该是ngx.ctx.host = 'test.com'
作者回复: 是的,本来想写的是: local ngx_ctx = ngx.ctx
2019-07-0542 - 阳光梦local ngx_ctx = ngx.ctx local function bar() ngx_ctx.host = 'test.com' end 上面内容放在access.lua中,比如access阶段包含此文件。为何不能执行第一句?
作者回复: 有什么报错吗?ngx.ctx 是可以在 access 阶段使用的
2019-07-0532 - helloworld老师,还有一个问题,local ngx_ctx = ngx.ctx 这个API缓存语句不能用于模块级别,要用于函数级别,那么local ngx_var = ngx.var 这个是不是也是同样的?
作者回复: 是的
2019-07-241 - manatee想请问老师现在很多基于插件来实现的网关里面的插件配置是怎么保存在or里的呢?是sharedict吗
作者回复: 有些是共享字典,有些是 lrucache
2019-07-051 - zhang老师,luajit最大可用内存是2g,在openrety中如何将它提高?
作者回复: 1.15.8 这个最新版本中,默认已经提高了,支持了 64 位
2019-07-0521 - Rye请教老师个问题,我想在请求返回给各户端前 拿到上游服务器的IP和端口,也就是upstream的具体哪个节点负责处理的请求,有什么办法么?我在 ngx.balancer 里看大部分是set的方法。
作者回复: 你在 ngx.balancer 的 set_current_peer 时,保存下上游的节点信息?
2019-07-052 - HelloBug关于ngx.ctx不要做模块级别的缓存,我做了以下的测试。 myctx.lua文件: local _M = {} local ngx_ctx = ngx.ctx function _M.bar() ngx_ctx.host = 'test.com' end return _M nginx.conf文件: worker_processes 1; server { listen 9999; location ~/(?<myurl>.*) { content_by_lua_block { local myctx = require "myctx" if ngx.var.myurl == "1" then ngx.say(ngx.ctx.host) ngx.ctx.host = "who" ngx.say(ngx.ctx.host) myctx.bar() ngx.say(ngx.ctx.host) else ngx.say(ngx.ctx.host) end } } } 测试结果如下: [root@localhost nginx]# curl localhost:9999/1 nil who test.com [root@localhost nginx]# curl localhost:9999/1 nil who who [root@localhost nginx]# curl localhost:9999/1 nil who who [root@localhost nginx]# curl localhost:9999/2 nil [root@localhost nginx]# curl localhost:9999/2 nil 第一个请求可以理解,第二、第三个请求证明不要做模块级别的缓存。但是为什么这样呢?即使此时ngx_ctx保留的是第一个请求的ngx.ctx,为什么再次设置变量的值ngx_ctx.host就不管用了呢?2019-07-0722
- Geek_xiaoer老师您好,`yield`有可能导致race。哪些API(比如ngx.sleep)或哪些操作(比如访问redis)会yield?请问这个有参考文档,或者整理吗,谢谢!2021-05-141