00:00
Hello,同学们,接下来呢,我们看看ofed的一些常用的模块,首先第一个呢,我们要看的就是在X里边去做缓存,Of提供的两种方式,比较方便的去在N的内存里边去操作一些缓存的这些数据,呃,也使这个并发量呢能够承载的更高。那第一种呢,就是使用这个共享字典shared Di。就这种方式,呃,Shed dit呢?呃,性能呢比较高效,呃,它在多个worker进程当中呢,可以去共享这份缓存数据啊,但是呢,呃,既然是多进程可以同时操作,那么想要保证这个数据的原子特性,那么就一定会有锁的产生啊,那这就是呃shared dit,那具体使用呢,我们带大家来看一下。还是在这个撸va脚本里,我们把这段代码给它粘上,然后我们再带着大家解读,然后保存一下,然后想要使用这个12的,在这儿呢,呃,需要调用N的变量,所有和N相互的,呃,和N的交互呢,都通过NGX来做,然后在这呢,我们需要先去明一个shed,并且明它的大小是多少,这个在N的配置文件里我们去明。
01:20
啊,在这儿HTTP模块下。这个Lu shared啊,Share的贝塔em,这代表我们申请一兆内存去做这个内存缓存啊,这个内存缓存是被所有的进程都能够共同访问,并且能够保证原子性的,然后在这儿声明完之后呢,呃,保存,然后接下来在这儿。我们去调用它,我们先看看效果,我们先跑一下啊,啊在这我们,嗯。还是呃,Stop这儿啊,这种呃和N相关的这种操作,比如说在这加了一个呃NG的配置,这个是必须得重启的啊不,你看现在我没重启,我们直接去访问一下。
02:05
嗯,这会儿就有可能会报错啊,你看来走这就报错了,你如果看错误信息的话啊,大概意思也就是这个share的data,呃,这个变量呢,我想从NGS的data里边去取,但它取不着,就是因为我们在这虽然已经呃代码已经入部署了,但是这个配置呢,它没有帮我们去,没有帮我们去热部署啊,所以在这得重启N几个S。能停掉,然后呢,再重新启动。然后这会儿我们再去刷新。大家注意看这第一次呢,他给我们提示lazy set I1,然后I等于二,这是啥意思,我们看这。呃。在这呢,到代码首先啊,我去获取这个缓存啊,然后接下来呢。12的data get I啊,从这个12的data里边,就相当于我的内存缓缓存里边呢,去取这个,呃,一个一个key啊,这里边也是KY6的这种间值对式的存储,呃,有点像小号的red在这个N里边跑了。
03:16
然后get I,然后if not I,就是这I,它没有没拿着ZI等于一,然后接下来呢,12的data塔调,继续调用这个12DATA这个变量,调用它的S的方法I,然后等于I,这个I等于I,就是I就已经等于一了,相当于这个给它重新赋值等于一,然后NG X c lazy sit,然后I等于啥,就是现在这个I等于一啊,或者是I等于二。这个I等于二,就是因为他之前有,然后加了一次,然后它就等于二了,如果要是呃。从这个12DATA里边get这个数据啊,拿到了这个Y6,接下来呢,12DATA。Increment就行,自增加再加一下加一啊,然后NGXC。
04:08
I等于啥?你看我们每次刷新呢,它都会。相加啊,在多线程或者或者多进程同时访问的时候,这份共享数据它是安全的,也就是我们可以通过呃N这个NG的内存去存储一些数据了,在之前咱们讲的NG去做缓存的时候呢,只能缓存这个静态的文件,缓存到磁盘上,这会儿呢,把我的上游服务器里边拉取来的这些数据,我甚至都可以直接给它写在这个。啊,内存当中让他去使用,那这样呃,肯定要比磁盘上这些存储的要简单高效,但这个的使用啊,一般来说存储的也都是少量的数据,比如说这种计数啊,或者是一些什么其他的,呃,大量的数据呢,还并不是特别适合这种方式。呃,一是由于它的这个内存容易被撑爆,第二呢,就是呃,Shared data,呃,或者叫shared吧。
05:05
这种呃,字典式的内存式的存储,它有缺点,它的缺点就是多进程共享,那么这份数据又保证的原子性,在在修改数据的时候呢,会有锁的产生,从而会呃,对咱们的QPS有影响啊,但也就是因为它这种特性,才能保证我这里边的数据呢,它的一致性比较强,也就不不会。因为呃,多个进程共同往这份内存区里边去写,造成这个数据错乱啊,有一些脏毒或者脏写的这种情况出生,这个这个这个出现啊,那么给大家介绍另外一种这个缓存的方式。呃,就是。这个Lu rus Lu l ru catch啊,它对比这个Sha来说呢,功能呢,会更强大一些,但是纯粹用由这个lur语言来实现的啊。
06:00
好,同学们好,接下来呢,我们带着大家一起来学习一下lua rest Lu ru catch,呃,这是lua官方提供的一个这个模块,这个模块呢,呃,也可以像这个share dit一样呢,在NG的内存里边呢,去使用缓存,它的区别就在于这是纯粹用lur语言来实现的,并且呢,它是在独个独立的这个进程里运行,那多个进程同时运行的时候呢,可能会有内存上的浪费。啊,再有就是呃,独立进程里边去运行的话,由于单进程呃去做这种增删操作,那么它就不需要再去加锁啊,再去呃做一些这种修改操作的时候呢,性能会略高一些,但是我们实际的使用的时候呢,其实是不太会感觉出来它和这个Sha。呃的性能上的太大的差异,反而那么可能会感觉到它使用上的差异,呃这个呃L呢,它可以做这个呃这种这个LRU算法,这种呃清理工作,另外就是它的这个对。
07:05
呃,对于这个存储的概念和s Di不一样,它是以k value的个数啊为单位来限制啊,12呢,它是以内存大小,内存占用大小来限制的,那12IC就能更有效的去控制呃,Lu的缓存啊,在系统当中的内存大小占用,那么这l catch呢,其实我们是没法预估呃它究竟能够它它究竟会占用我们系统的多少内存的,它只能去限制个数,那么对于这种预估呢,我们就需要对这个每一个k value6呃去有这个提前的这种感知才可以。呃,其实这样的话呢,反而带来了一种好处,就是它的内存呢,可以更加弹性化,不至于呢,我们往里边存东西之后,因为内存上占满了,导致他写不进去是吧。呃,那么这是它的官方官方的站点,大家可以看到啊,是github的项目在op的,呃,这个这个这个站点下啊,它的这个官方的地址是这个,我们看一下。
08:12
呃,这是它的所有的使用上的介绍啊,也是get set,相当于小red在内存里边直接去用,呃,功能呢,也没有太多啊,基本上就是常用的功能都有,那我们想要使用它的话。呃,去引入一下它的这个。模块就可以了,它默认呢,就已经在我们的这个open的目录下了,大家看啊在这。嗯。洛安利吧,啊叫做洛安利吧,然后在rest下。呃。Lu ru catch啊,还有好多其他用red my circle啊,这些可以去连接一些第三方这个组件,它完整的名字就是rest.my rested.lu ru cash。
09:00
啊,那我们接下来去使用一下它。呃,在使用它的时候啊,我们先看一下这个官方文档。嗯,他是比较推荐我们去这么去使用的啊,这相当于去自定义一个函数啊,这还不是面向对象,这只是呃,函数定义这个local m后边跟一大括号,这表示定义了一个数组,然后在这数组里边呢加一个方法啊,之前在演示这个语法的时候,我们给大家也简单的去实验了啊,就是数组里边呢是可以装方法的。然后在这个呃,这个这个方法和定义数组的过程当中,这一部分内容呢,呃,在我们的这个呃get编辑G编辑器的执行的过程当中呢,它只会执行一次。当我们的系统在处于l ru catch,不是Li ru catch这个,呃呃,Catch Lu啊,就是这个配置,我们的这个配置文件它属于打开的情况下。
10:05
我们现在不是把它已经关了吗?啊才可以这个改完代码,然后马上就能展示出来是吧。这个位置。嗯,这个。Lu扣的catch啊,在它打开的情况下,这部分代表呢,只会被执行一次,因为这个Lu语言呢,它是动态语言,它介于呃这种静态编译和动态脚本之间啊,就是它执行过一次之后呢,会有一层缓存。这一部分初属于初始化的部分,所以它执行一次就可以了,那这也能给我们带来额外的一个好处,就是我们看之前我们在使用shared Di的时候。我们在定义这个12DIG的对象是在NG格里,然后是在代码里边去调用NG格里的对象在NGX点12的,12的点12的得塔。那这一部分内容它属于由NG来管理,那么我们的这个lur代码即使再怎么改变,它就已经在之前或者在事先就已经初始化好了,它不会再去重新初始化,也就是我不会再去重新定义一遍这个share的share的data,它的大小是一兆,如果每次在执行的时候都需要解释。
11:22
比如说这段代码,我们,比如我们我们如果要是在运行的时候,它会从上往下去全部都给我们运行一遍啊,先去定义定义一个这个呃,数组,那接下来呢,去引入quiry这个l ru catch。那么这还没关系,那接下来就该有问题了,L Lu ru catch.new这相当于去初始化一下。我们的这个RA缓存,它初始化之后呢,传的参数是200,表示能够,呃,承载200个P啊,相同的也有Y6啊,这lo up啊,就初始化这个空间啊,搞出一个200大小的这么一个are catch准备去放,那么那么接下来再去往里边去,呃,Set往往外去get。
12:10
那如果要是每次都是动态直接动态解析的话,每次都会从头到尾来一遍。那这也就意味着每次他都会重新扭一遍,那么给大家来实验一下啊,你看这个效果。嗯,我们就还在这个hello里,我事先呢给大家准备好了一段代码,嗯。在这儿。这是自定义的一套函数啊。啊,同样这个问题啊,它也伴随在你去连接redis,连接这个MY啊,不然的话,它其实是用不上这个缓存的,或用不上这个你之前设置的数据库连接池,这也是用不上的,你一定要保证这段代码不能被重新初始化啊,就只能被执行一次。
13:01
呃,我们来保存一下。嗯。呃,在这儿呢,去调用一下这个呃构方法啊,这个怎么调呢,就不能在呃这个这个。我们的NGS里去直接引入这个文件了,因为你引入它之后这个。呃,我们的这个具体的这个函数啊,它并没有被执行,对吧,我们需要调取这个go这个函数的方法吧,对吧,那怎么去调用它呢?在这这么调。嗯。来看啊,我们用这个content by lua block啊,这个的意思是lua的block嘛,我这这全都是lua的代码,然后一个代码块,这是lua啊,当然你也可以再写一个这个lua file,然后去引引一下我们的这个刚刚定义的这个数组。呃,这content by Lu block这大括号里边呢,你可以无限的去写lur代码啊,在这儿呢,我们就去调用这个M里的这个go,这个就不要了,之前那个就不要了。
14:08
那quiry啊,呃,这个quiry啊,相当于引入这个呃lua的,呃这个这个代码文件这有几个,呃存储它的位置,我们先这样,我们先保存一下,然后呢。把这个日志我们看一下,把原来的这个日志呢,我们先不要了,把它给清掉。尤其错误日志啊,你就能看到他的默认的找的这个地儿在那儿了。呃,然后重写。Stop,然后启动,然后看这个错误日志,错误日志已经出来了,对吧,当然现在这应该是警告的这个错误日志,然后接下来我们访问一下。这有。你看他报错了。来,我们刷新一下。
15:02
他想要去找我们的这个麦下边的catch.lua这个文件,那么它默认情况下会从这么几个地儿去找。啊,比如当前的这个路径下找这个catch.lu然后在这个op的site lua力吧,Site下的lua力吧lua lua Li巴下的麦,然后以及一些其他的,这是默认的,呃,我们的这些,呃,Lua文件应该存在的地儿,当然呢,这个地儿呢,这些这个路径让他去哪去找,这个我们也能配置啊,这配置的方法呢,就在这最下边就有,我记得。这lua package pass可以在这儿去,呃,再去重新的去,呃,设置一个新的地儿啊,我们直接呢,就把它给挪到现有的地儿,就在这Lu Li下,我们新建一个目录叫麦。在这。萝力吧。新建文件夹,然后卖,然后把之前的那个文件呢,我把它给挪过来。
16:10
嗯。这儿呢哈是吧。这个这个小移动,这还得。一个一个来,我们走。再上去。然后挪挪到利巴里。然后再挪到。麦下。那我们这写的是cash。There,这样OK,那我们再访问一下。看看他找得着找不着了。呃,那这会儿呢,我们先不要慌,遇到这种问题呢,我们都可以通过它的这个a log,我们一步一步来排查,那我们先看一下这代码有没有什么问题啊。因为刚才他不是找不着嘛,那接下来这会儿找着了,然后并且嗯,他肯定是能找着,并且他报错了啊。
17:06
啊,你看啊,这有开没有关啊啊,而且这个这个and,这应该是我粘代码的时候少粘了,这个and呢,And到if,然后这个function这呢没有end。然后再加一个and,然后并且呃,少一个return。啊,这样呢,就应该没问题了,我们保存一下再看看。就是出现错误之后,你可以去那个error log里边去找它具体的原因啊,像这种就是就很明显一眼,你先看一眼代码,一眼就能看出来的错误呢啊,就自己补上就可以了,然后在这呢,我们看啊,我们写的这个代码在这刷新,你看count这边呢,我加了一个inite,相当于打了一个日志在这个位置。这就是l ru catch.new它每次都会去new,大家看到看到了吧,如果这段代码呢,不会被重复执行的话,那么这个呃,In ne这一部分它一定不会,每次我在刷新的时候呢,它都会打出来,这就是最严重的问题。
18:11
啊,这个问题一定要解决,不然的话这个缓存压根就没法用,我们看下边的代码,呃,IFC,然后Z,这是if not c,就是他没给我们赋值,然后接下来这报错了,然后接下来我们看看这个自己定义的这个。呃,这个这个这这个函数啊,然后count呢,我们先去还是老套路,先去get这个count。然后如果要是。这个没get出来,If not count,接下来给它里边set set一个,然后并且打印一行lazy set啊,然后把这个count值啊,再给它给拿出来,你看set set LA lazy lazy set。Count,然后这个值是啥?就是这个一,现在是一,然后并且加了一个换行,如果要是有值的话,直接把它给拿出来,然后并且加一,然后。
19:07
呃,再加一个NGC,然后然后把这个当前的这个呃统计的数呢给它给打出来,很明显现在我们怎么刷新它这个数呢,都不加,并且有一个巨大的问题,就是我们现在这个从呃缓存里边拿不出来这个count这个值,但明明明我们这这这一步呢已经塞进去了。这个的主要原因就是每次在访问的时候,他都会重新去一遍。同学们千万不要犯这个犯这个错误,不然的话,这一个问题你有你就有可能会搞一宿啊,就是写入的缓存为什么。它不生效啊,那么这会儿就一定要让这段代码只执行一次,就只拗一次,然后成为内存里的常驻对象啊,或者常常驻函数,然后接下来我们每次都去调它就可以了,在Java里的静态方法啊,就只拗一次,那这个怎么做呢?或者问题出在那儿了,其实它的主要的问题就出在我们的NG的配置文件里。
20:07
呃,其中的这一块。扣的catch,因为他每一次的这个呃,执行。Lua代码都会从头到尾重新的去给我们解释一遍,你你的这个Lu catch.new也都会被执行一遍,所以每次来都是新的,那你必须得把它给关掉。这才能成为这个静态的这种,呃,这个这个方法。然后保存,接下来要重启一下。这个N几个。Stop,然后再起啊,大家注意看啊,Init它还会不会再重复出现刷新,第一次inite一下,第二次就没有了。三四五六七八九十。啊,然后我们再开一个新的窗口。他还会继续给他加啊。
21:00
这就是这个Lu Lu ru catch在使用的时候一定要注意的点,其他的呢,倒没啥啊,嗯,对比这个shared dick来说呢,其实这两个。嗯,只是功能上使用上呢,稍微有一点点区别,呃,性能上的差异呢,并不是特别大啊,呃,差差别就在于一个有锁一个没有锁啊,这就是l catch。
我来说两句