精华内容
下载资源
问答
  • UE4获取深度缓存

    2020-07-25 20:45:17
    UE4对场景使用“反向”深度缓冲区。 获取 在任意tick函数或者其他函数添加以下的命令: struct DepthPixel //定义深度像素结构体 { float depth; char stencil; char unused1; char unused2; char unused...

    深度像素格式

    在这里插入图片描述

    键入命令vis scenedepthz uv0以查看实际使用的深度缓冲区。UE4对场景使用“反向”深度缓冲区。

    获取

    在任意tick函数或者其他函数添加以下的命令:

    struct DepthPixel	//定义深度像素结构体
    	{
    		float depth;
    		char stencil;
    		char unused1;
    		char unused2;
    		char unused3;
    	};
    
    	float* cpuDataPtr;	// Texture深度值数组首地址
    	TArray<DepthPixel> mydata;	//最终获取色深度值数据
    	FIntPoint buffsize;	//深度长宽大小X和Y
    
    	ENQUEUE_RENDER_COMMAND(ReadSurfaceFloatCommand)(	// 将读取深度数据的命令推给渲染线程进行执行
    		[&cpuDataPtr, &mydata, &buffsize](FRHICommandListImmediate& RHICmdList) //&cpuDataPtr, &mydata, &buffsize为传入的外部参数
    	{
    		FSceneRenderTargets::Get(RHICmdList).AdjustGBufferRefCount(RHICmdList, 1);
    		FTexture2DRHIRef uTex2DRes = FSceneRenderTargets::Get(RHICmdList).GetSceneDepthSurface();	
    		buffsize = uTex2DRes->GetSizeXY();
             uint32 sx = buffsize.X;
    		uint32 sy = buffsize.Y;
             mydata.AddUninitialized(sx * sy);
             uint32 Lolstrid = 0;
    		cpuDataPtr = (float*)RHILockTexture2D(uTex2DRes,0,RLM_ReadOnly,Lolstrid,true);	// 加锁 获取可读depth Texture深度值数组首地址
    		memcpy(mydata.GetData(), cpuDataPtr, sx * sy * sizeof(DepthPixel));		//复制深度数据
    		RHIUnlockTexture2D(uTex2DRes, 0, true);	//解锁
    		FSceneRenderTargets::Get(RHICmdList).AdjustGBufferRefCount(RHICmdList, -1);	
    
    	});
    	FlushRenderingCommands();	//等待渲染线程执行
    
    	mydata; 	//最终获取深度数据
    

    最终返回的mydata数据就是最终的深度值数组,其中每个深度值的结构是DepthPixel,其中一个成员为depth,另外四个不不使用。其中使用上面的几个命令需要添加"RHI.h"头文件

    展开全文
  • Unity 深度图片获取

    千次阅读 2017-03-07 20:07:07
    2、 深度缓存,或者深度纹理,其实就是一个包含有场景里物体离照相机的距离值的一张纹理图。 3、 为了让摄像机生成一张深度纹理,只需要设置Camera.depthTextureMode即可。但这个时候生成了纹理,还需要我们去获取...

    1、  在Unity中,要得到深度缓存(Depthbuffer),就需要用到一个RenderTexture纹理。

    2、  深度缓存,或者深度纹理,其实就是一个包含有场景里物体离照相机的距离值的一张纹理图。

    3、  为了让摄像机生成一张深度纹理,只需要设置Camera.depthTextureMode即可。但这个时候生成了纹理,还需要我们去获取。所以我们需要把它传到一个shader中,于是就用到OnRenderImage这个函数。

     

    于是我们得出下面一个例子:

    using UnityEngine;
    using System.Collections;
    
    //so that we can see changes we make without having to run the game
    
    [ExecuteInEditMode]
    public class PostProcessDepthGrayscale : MonoBehaviour {
    
       public Material mat;
    
       void Start () {
    //设置Camera的depthTextureMode,使得摄像机能生成深度图。
          Camera.main.depthTextureMode = DepthTextureMode.Depth;
       }
    
       void OnRenderImage (RenderTexture source, RenderTexture destination){
          Graphics.Blit(source,destination,mat);
          //mat就是包含shader的一个材质球,而这个shader就是我们要把
                 //destination这个render纹理传进去的shader。Shader的写法如下所示。
       }
    }


     

    接下来这个shader代码如下:

    Shader "Custom/DepthGrayscale" {
    SubShader {
    Tags { "RenderType"="Opaque" }
    
    Pass{
    CGPROGRAM
    #pragma vertex vert
    #pragma fragment frag
    #include "UnityCG.cginc"
    
    sampler2D _CameraDepthTexture;
    
    struct v2f {
       float4 pos : SV_POSITION;
       float4 scrPos:TEXCOORD1;
    };
    
    //Vertex Shader
    v2f vert (appdata_base v){
       v2f o;
       o.pos = mul (UNITY_MATRIX_MVP, v.vertex);
       o.scrPos=ComputeScreenPos(o.pos);
       //for some reason, the y position of the depthtexture comes out inverted
       //o.scrPos.y = 1 - o.scrPos.y;
       return o;
    }
    
    //Fragment Shader
    half4 frag (v2f i) : COLOR{
       float depthValue =Linear01Depth (tex2Dproj(_CameraDepthTexture,UNITY_PROJ_COORD(i.scrPos)).r);
       half4 depth;
    
       depth.r = depthValue;
       depth.g = depthValue;
       depth.b = depthValue;
    
       depth.a = 1;
       return depth;
    }
    ENDCG
    }
    }
    FallBack "Diffuse"
    }


     

    前面都好理解,而且需要注意的是,_CameraDepthTexture这个变量的值是Unityshader内部传进去的。

    float depthValue =Linear01Depth (tex2Dproj(_CameraDepthTexture,UNITY_PROJ_COORD(i.scrPos)).r);

    Linear01Depth这个是将其中的值转换成深度的01之间的值,tex2Dproj采样得到的颜色值为何只取r值,而且取gb值是全黑的。这需要再考虑一下。(对于这个问题,现测得RenderTexture如果它的Format改成Depth的话,就只有红色这一个通道颜色了。所以会出现上面的这个情况。)

    而且,这里的深度是受RenderQueue的值的影响,并不只z轴坐标。比如你的RenderQueue=3000,但是z轴坐标离摄像机很近,那它的深度值也是很大的。得到一幅深度图如下图:


    可见,离摄像机越近,深度越小,颜色值越深。

    展开全文
  • 点击上方蓝色字体,选择“设为星标”回复”666“获取面试宝典在我们实际的业务场景中,一定有很多需要做数据缓存场景,比如售卖商品的页面,包括了许多并发访问量很大的数据,它们可以称作是是“热点”数据,这些...

    点击上方蓝色字体,选择“设为星标”

    回复”666“获取面试宝典

    dc37173753db83ae5e4b34bfa25e523c.png

    在我们实际的业务场景中,一定有很多需要做数据缓存的场景,比如售卖商品的页面,包括了许多并发访问量很大的数据,它们可以称作是是“热点”数据,这些数据有一个特点,就是更新频率低,读取频率高,这些数据应该尽量被缓存,从而减少请求打到数据库上的机会,减轻数据库的压力。

    为何要使用缓存

    缓存是为了追求“快”而存在的。我们用代码举一个例子。

    我在自己的Demo代码仓库中增加了两个查询库存的接口getStockByDB和getStockByCache,分别表示从数据库和缓存查询某商品的库存量。

    随后我们用JMeter进行并发请求测试。

    需要声明的是,我的测试并不严谨,只是作对比测试,不要作为实际服务性能的参考。

    这是两个接口的代码

     /* 查询库存:通过数据库查询库存
     * @param sid
     * @return
     */

    @RequestMapping("/getStockByDB/{sid}")
    @ResponseBody
    public String getStockByDB(@PathVariable int sid) {
        int count;
        try {
            count = stockService.getStockCountByDB(sid);
        } catch (Exception e) {
            LOGGER.error("查询库存失败:[{}]", e.getMessage());
            return "查询库存失败";
        }
        LOGGER.info("商品Id: [{}] 剩余库存为: [{}]", sid, count);
        return String.format("商品Id: %d 剩余库存为:%d", sid, count);
    }

    /**
     * 查询库存:通过缓存查询库存
     * 缓存命中:返回库存
     * 缓存未命中:查询数据库写入缓存并返回
     * @param sid
     * @return
     */

    @RequestMapping("/getStockByCache/{sid}")
    @ResponseBody
    public String getStockByCache(@PathVariable int sid) {
        Integer count;
        try {
            count = stockService.getStockCountByCache(sid);
            if (count == null) {
                count = stockService.getStockCountByDB(sid);
                LOGGER.info("缓存未命中,查询数据库,并写入缓存");
                stockService.setStockCountToCache(sid, count);
            }
        } catch (Exception e) {
            LOGGER.error("查询库存失败:[{}]", e.getMessage());
            return "查询库存失败";
        }
        LOGGER.info("商品Id: [{}] 剩余库存为: [{}]", sid, count);
        return String.format("商品Id: %d 剩余库存为:%d", sid, count);
    }

    首先设置为10000个并发请求的情况下,运行JMeter,结果首先出现了大量的报错,10000个请求中98%的请求都直接失败了。让人很慌张~

    打开日志,报错如下:

    175d8938ccf2fd67f07ab7c5c020a131.png

    SpringBoot内置的Tomcat最大并发数搞的鬼,其默认值为200,对于10000的并发,单机服务实在是力不从心。当然,你可以修改这里的并发数设置,但是你的小机器仍然可能会扛不住。

    cfdd2e86b548e8a6d0e07771376e536d.png

    将其修改为如下配置后,我的小机器才在通过缓存拿库存的情况下,

    保证了10000个并发的100%返回请求:

    server.tomcat.max-threads=10000server.tomcat.max-connections=10000

    可以看到,不使用缓存的情况下,吞吐量为668个请求每秒

    fcf924f4f86b6d7b02762b9d4e07b76b.png

    使用缓存的情况下,吞吐量为2177个请求每秒

    0c84d723a4896bedd39c9839e6bdd21a.png

    在这种“十分不严谨”的对比下,有缓存对于一台单机,性能提升了3倍多,如果在多台机器,更多并发的情况下,由于数据库有了更大的压力,缓存的性能优势应该会更加明显。

    测完了这个小实验,我看了眼我挂着 MySQL 的小水管腾讯云服务器,生怕他被这么高流量搞挂。这种突发的流量,指不定会被检测为异常攻击流量呢~

    1ad7fbad5e83149a0c092713839bbee7.png

    我用的是腾讯云服务器1C4G2M,活动买的,很便宜。这里打个免费的广告,请腾讯云看到后联系我给我打钱 ;)

    60d854ed6d91bf04a66cf21fad5d9d01.png

    哪类数据适合缓存

    缓存量大但又不常变化的数据,比如详情,评论等。对于那些经常变化的数据,其实并不适合缓存,一方面会增加系统的复杂性(缓存的更新,缓存脏数据),另一方面也给系统带来一定的不稳定性(缓存系统的维护)。

    但一些极端情况下,你需要将一些会变动的数据进行缓存,比如想要页面显示准实时的库存数,或者其他一些特殊业务场景。这时候你需要保证缓存不能(一直)有脏数据,这就需要再深入讨论一下。

    缓存的利与弊

    我们到底该不该上缓存的,这其实也是个trade-off(权衡)的问题。

    上缓存的优点:

    • 能够缩短服务的响应时间,给用户带来更好的体验。
    • 能够增大系统的吞吐量,依然能够提升用户体验。
    • 减轻数据库的压力,防止高峰期数据库被压垮,导致整个线上服务BOOM!

    上了缓存,也会引入很多额外的问题:

    • 缓存有多种选型,是内存缓存,memcached还是redis,你是否都熟悉,如果不熟悉,无疑增加了维护的难度(本来是个纯洁的数据库系统)。
    • 缓存系统也要考虑分布式,比如redis的分布式缓存还会有很多坑,无疑增加了系统的复杂性。
    • 在特殊场景下,如果对缓存的准确性有非常高的要求,就必须考虑缓存和数据库的一致性问题

    本文想要重点讨论的,就是缓存和数据库的一致性问题,各位看官且往下看。

    如何保证缓存和数据库一致性

    说了这么多缓存的必要性,那么使用缓存是不是就是一个很简单的事情了呢,我之前也一直是这么觉得的,直到遇到了需要缓存与数据库保持强一致的场景,才知道让数据库数据和缓存数据保持一致性是一门很高深的学问。

    从远古的硬件缓存,操作系统缓存开始,缓存就是一门独特的学问。这个问题也被业界探讨了非常久,争论至今。我翻阅了很多资料,发现其实这是一个权衡的问题。值得好好讲讲。

    以下的讨论会引入几方观点,我会跟着观点来写代码验证所提到的问题。

    不更新缓存,而是删除缓存

    大部分观点认为,做缓存不应该是去更新缓存,而是应该删除缓存,然后由下个请求去去缓存,发现不存在后再读取数据库,写入缓存。

    观点引用:《分布式之数据库和缓存双写一致性方案解析》孤独烟

    原因一:线程安全角度

    同时有请求A和请求B进行更新操作,那么会出现

    (1)线程A更新了数据库

    (2)线程B更新了数据库

    (3)线程B更新了缓存

    (4)线程A更新了缓存

    这就出现请求A更新缓存应该比请求B更新缓存早才对,但是因为网络等原因,B却比A更早更新了缓存。这就导致了脏数据,因此不考虑。

    原因二:业务场景角度

    有如下两点:

    (1)如果你是一个写数据库场景比较多,而读数据场景比较少的业务需求,采用这种方案就会导致,数据压根还没读到,缓存就被频繁的更新,浪费性能。

    (2)如果你写入数据库的值,并不是直接写入缓存的,而是要经过一系列复杂的计算再写入缓存。那么,每次写入数据库后,都再次计算写入缓存的值,无疑是浪费性能的。显然,删除缓存更为适合。

    其实如果业务非常简单,只是去数据库拿一个值,写入缓存,那么更新缓存也是可以的。但是,淘汰缓存操作简单,并且带来的副作用只是增加了一次cache miss,建议作为通用的处理方式。

    先操作缓存,还是先操作数据库

    那么问题就来了,我们是先删除缓存,然后再更新数据库,还是先更新数据库,再删缓存呢?

    先来看看大佬们怎么说。

    《【58沈剑架构系列】缓存架构设计细节二三事》58沈剑:

    对于一个不能保证事务性的操作,一定涉及“哪个任务先做,哪个任务后做”的问题,解决这个问题的方向是:如果出现不一致,谁先做对业务的影响较小,就谁先执行。

    假设先淘汰缓存,再写数据库:第一步淘汰缓存成功,第二步写数据库失败,则只会引发一次Cache miss。

    假设先写数据库,再淘汰缓存:第一步写数据库操作成功,第二步淘汰缓存失败,则会出现DB中是新数据,Cache中是旧数据,数据不一致。

    沈剑老师说的没有问题,不过没完全考虑好并发请求时的数据脏读问题,让我们再来看看孤独烟老师《分布式之数据库和缓存双写一致性方案解析》:

    先删缓存,再更新数据库

    该方案会导致请求数据不一致

    同时有一个请求A进行更新操作,另一个请求B进行查询操作。那么会出现如下情形:

    (1)请求A进行写操作,删除缓存

    (2)请求B查询发现缓存不存在

    (3)请求B去数据库查询得到旧值

    (4)请求B将旧值写入缓存

    (5)请求A将新值写入数据库

    上述情况就会导致不一致的情形出现。而且,如果不采用给缓存设置过期时间策略,该数据永远都是脏数据。

    所以先删缓存,再更新数据库并不是一劳永逸的解决方案,再看看先更新数据库,再删缓存这种方案怎么样?

    先更新数据库,再删缓存这种情况不存在并发问题么?

    不是的。假设这会有两个请求,一个请求A做查询操作,一个请求B做更新操作,那么会有如下情形产生

    (1)缓存刚好失效

    (2)请求A查询数据库,得一个旧值

    (3)请求B将新值写入数据库

    (4)请求B删除缓存

    (5)请求A将查到的旧值写入缓存

    ok,如果发生上述情况,确实是会发生脏数据。

    然而,发生这种情况的概率又有多少呢?

    发生上述情况有一个先天性条件,就是步骤(3)的写数据库操作比步骤(2)的读数据库操作耗时更短,才有可能使得步骤(4)先于步骤(5)。可是,大家想想,数据库的读操作的速度远快于写操作的(不然做读写分离干嘛,做读写分离的意义就是因为读操作比较快,耗资源少),因此步骤(3)耗时比步骤(2)更短,这一情形很难出现。

    先更新数据库,再删缓存依然会有问题,不过,问题出现的可能性会因为上面说的原因,变得比较低!

    (补充说明:我用了“先更新数据库,再删缓存”且不设过期时间策略,会不会有问题呢?由于先缓存和更新数据库不是原子的,如果更新了数据库,程序歇逼,就没删缓存,由于没有过期策略,就永远脏数据了。)

    所以,如果你想实现基础的缓存数据库双写一致的逻辑,那么在大多数情况下,在不想做过多设计,增加太大工作量的情况下,请先更新数据库,再删缓存!

    我非要数据库和缓存数据强一致怎么办

    那么,如果我非要保证绝对一致性怎么办,先给出结论:

    没有办法做到绝对的一致性,这是由CAP理论决定的,缓存系统适用的场景就是非强一致性的场景,所以它属于CAP中的AP。

    所以,我们得委曲求全,可以去做到BASE理论中说的最终一致性

    最终一致性强调的是系统中所有的数据副本,在经过一段时间的同步后,最终能够达到一个一致的状态。因此,最终一致性的本质是需要系统保证最终数据能够达到一致,而不需要实时保证系统数据的强一致性

    大佬们给出了到达最终一致性的解决思路,主要是针对上面两种双写策略(先删缓存,再更新数据库/先更新数据库,再删缓存)导致的脏数据问题,进行相应的处理,来保证最终一致性。

    缓存延时双删

    问:先删除缓存,再更新数据库中避免脏数据?

    答案:采用延时双删策略。

    上文我们提到,在先删除缓存,再更新数据库的情况下,如果不采用给缓存设置过期时间策略,该数据永远都是脏数据。

    那么延时双删怎么解决这个问题呢?

    (1)先淘汰缓存

    (2)再写数据库(这两步和原来一样)

    (3)休眠1秒,再次淘汰缓存

    这么做,可以将1秒内所造成的缓存脏数据,再次删除。

    那么,这个1秒怎么确定的,具体该休眠多久呢?

    针对上面的情形,读者应该自行评估自己的项目的读数据业务逻辑的耗时。然后写数据的休眠时间则在读数据业务逻辑的耗时基础上,加几百ms即可。这么做的目的,就是确保读请求结束,写请求可以删除读请求造成的缓存脏数据。

    如果你用了mysql的读写分离架构怎么办?

    ok,在这种情况下,造成数据不一致的原因如下,还是两个请求,一个请求A进行更新操作,另一个请求B进行查询操作。

    (1)请求A进行写操作,删除缓存

    (2)请求A将数据写入数据库了,

    (3)请求B查询缓存发现,缓存没有值

    (4)请求B去从库查询,这时,还没有完成主从同步,因此查询到的是旧值

    (5)请求B将旧值写入缓存

    (6)数据库完成主从同步,从库变为新值

    上述情形,就是数据不一致的原因。还是使用双删延时策略。只是,睡眠时间修改为在主从同步的延时时间基础上,加几百ms。

    采用这种同步淘汰策略,吞吐量降低怎么办?

    ok,那就将第二次删除作为异步的。自己起一个线程,异步删除。这样,写的请求就不用沉睡一段时间后了,再返回。这么做,加大吞吐量。

    所以在先删除缓存,再更新数据库的情况下,可以使用延时双删的策略,来保证脏数据只会存活一段时间,就会被准确的数据覆盖。

    在先更新数据库,再删缓存的情况下,缓存出现脏数据的情况虽然可能性极小,但也会出现。我们依然可以用延时双删策略,在请求A对缓存写入了脏的旧值之后,再次删除缓存。来保证去掉脏缓存。

    删缓存失败了怎么办:重试机制

    看似问题都已经解决了,但其实,还有一个问题没有考虑到,那就是删除缓存的操作,失败了怎么办?比如延时双删的时候,第二次缓存删除失败了,那不还是没有清除脏数据吗?

    解决方案就是再加上一个重试机制,保证删除缓存成功。

    参考孤独烟老师给的方案图:

    方案一:

    43e40d83e011a38948f79ce6d3c15275.png

    流程如下所示

    (1)更新数据库数据;

    (2)缓存因为种种问题删除失败

    (3)将需要删除的key发送至消息队列

    (4)自己消费消息,获得需要删除的key

    (5)继续重试删除操作,直到成功

    然而,该方案有一个缺点,对业务线代码造成大量的侵入。于是有了方案二,在方案二中,启动一个订阅程序去订阅数据库的binlog,获得需要操作的数据。在应用程序中,另起一段程序,获得这个订阅程序传来的信息,进行删除缓存操作。

    方案二:

    d9eb6c3b6b9821f38a418b5839350aaf.png

    流程如下图所示:

    (1)更新数据库数据

    (2)数据库会将操作信息写入binlog日志当中

    (3)订阅程序提取出所需要的数据以及key

    (4)另起一段非业务代码,获得该信息

    (5)尝试删除缓存操作,发现删除失败

    (6)将这些信息发送至消息队列

    (7)重新从消息队列中获得该数据,重试操作。

    扩展阅读

    更新缓存的的Design Pattern有四种:

    • Cache aside
    • Read through
    • Write through
    • Write behind caching,这里有陈皓的总结文章可以进行学习。

    https://coolshell.cn/articles/17416.html

    小结

    引用陈浩《缓存更新的套路》最后的总结语作为小结:

    分布式系统里要么通过2PC或是Paxos协议保证一致性,要么就是拼命的降低并发时脏数据的概率

    缓存系统适用的场景就是非强一致性的场景,所以它属于CAP中的AP,BASE理论。

    异构数据库本来就没办法强一致,只是尽可能减少时间窗口,达到最终一致性

    还有别忘了设置过期时间,这是个兜底方案

    结束语

    本文总结并探讨了缓存数据库双写一致性问题。

    文章内容大致可以总结为如下几点:

    • 对于读多写少的数据,请使用缓存。
    • 为了保持数据库和缓存的一致性,会导致系统吞吐量的下降。
    • 为了保持数据库和缓存的一致性,会导致业务代码逻辑复杂。
    • 缓存做不到绝对一致性,但可以做到最终一致性。
    • 对于需要保证缓存数据库数据一致的情况,请尽量考虑对一致性到底有多高要求,选定合适的方案,避免过度设计。
    来源 | 后端技术漫谈4e93195a9618e14fcebffe2bea20877b.gif
    • 面试官问:MySQL的自增ID用完了,怎么办?

    • ArrayList插入1000w条数据之后,我怀疑了jvm...

    • 蚂蚁二面,面试官问我零拷贝的实现原理,当场懵了…

    2b778736ed5731c5e8b015c731490779.png

    最近面试BAT,整理一份面试资料Java面试BAT通关手册,覆盖了Java核心技术、JVM、Java并发、SSM、微服务、数据库、数据结构等等。

    获取方式:点“在看”,关注公众号并回复 666 领取,更多内容陆续奉上。

    明天见(。・ω・。)ノ♡
    展开全文
  • 基于OpenGL环境,提出利用场景渲染结果即帧缓存数据(主要包括颜色缓存及深度缓存)进行局部三维场景重构的方法。根据投影变换原理和深度缓存特点研究了逆投影变换,得到了三维点元的重构方法。在此基础上,利用帧...
  • 深度解构分布式缓存技术原理及其在电商、社交、广告等典型场景中的应用。本书围绕分布式缓存的基础概念、开源框架、应用案例三方面进行讲解,从理论到实战,循序渐进,深入浅出。 总目录 因为笔记内容...

    来自蚂蚁金服、京东、网联、新浪微博、同程旅游等公司的10位一线架构师用心之作;深度解构分布式缓存技术原理及其在电商、社交、广告等典型场景中的应用。本书围绕分布式缓存的基础概念、开源框架、应用案例三方面进行讲解,从理论到实战,循序渐进,深入浅出。

    总目录

    阿里大牛纯手撸深入分布式缓存笔记(基础+开源框架+应用案例)

     

    阿里大牛纯手撸深入分布式缓存笔记(基础+开源框架+应用案例)

     

    阿里大牛纯手撸深入分布式缓存笔记(基础+开源框架+应用案例)

     

    因为笔记内容太多,下面只截取部分内容展示。需要获取完整笔记的小伙伴帮忙一键三连后,见下图加小助理VX(gyhycx7980)即可免费获取到!

    内容展示:

    阿里大牛纯手撸深入分布式缓存笔记(基础+开源框架+应用案例)

     

    阿里大牛纯手撸深入分布式缓存笔记(基础+开源框架+应用案例)

     

    阿里大牛纯手撸深入分布式缓存笔记(基础+开源框架+应用案例)

     

    阿里大牛纯手撸深入分布式缓存笔记(基础+开源框架+应用案例)

     

    阿里大牛纯手撸深入分布式缓存笔记(基础+开源框架+应用案例)

     

    阿里大牛纯手撸深入分布式缓存笔记(基础+开源框架+应用案例)

     

    阿里大牛纯手撸深入分布式缓存笔记(基础+开源框架+应用案例)

     

    阿里大牛纯手撸深入分布式缓存笔记(基础+开源框架+应用案例)

     

    阿里大牛纯手撸深入分布式缓存笔记(基础+开源框架+应用案例)

     

    阿里大牛纯手撸深入分布式缓存笔记(基础+开源框架+应用案例)

     

    章节太多这里就不一一展示了。需要获取完整笔记的小伙伴可以直接转发+关注后私信【学习】即可获取!

    阿里大牛纯手撸深入分布式缓存笔记(基础+开源框架+应用案例)

     

    阿里大牛纯手撸深入分布式缓存笔记(基础+开源框架+应用案例)

     

    阿里大牛纯手撸深入分布式缓存笔记(基础+开源框架+应用案例)

     

    阿里大牛纯手撸深入分布式缓存笔记(基础+开源框架+应用案例)

     

    阿里大牛纯手撸深入分布式缓存笔记(基础+开源框架+应用案例)

     

    阿里大牛纯手撸深入分布式缓存笔记(基础+开源框架+应用案例)

     

    阿里大牛纯手撸深入分布式缓存笔记(基础+开源框架+应用案例)

    限于平台篇幅原因,更多内容展示不了,有需要获取完整版的小伙伴帮忙一键三连后,见下图加小助理VX(gyhycx7980)即可免费获取到!

    展开全文
  • 是计算属性,依赖其他属性值,并且computed的值有缓存,只有它依赖的属性值发生改变,下一次获取comoputed的值时才会重新计算。 watch: 没有缓存,更多的是‘观察’的作用,类似于某些数据的监听回调,每当监听的...
  • Kafka连接器深度解读之JDBC源连接器

    千次阅读 2019-03-18 09:29:17
    在现实业务中,Kafka经常会遇到的一个集成场景就是,从数据库获取数据,因为关系数据库是一个非常丰富的事件源。数据库中的现有数据以及对该数据的任何更改都可以流式传输到Kafka主题中,在这里这些事件可用于驱动...
  • 在现实业务中,Kafka经常会遇到的一个集成场景就是,从数据库获取数据,因为关系数据库是一个非常丰富的事件源。数据库中的现有数据以及对该数据的任何更改都可以流式传输到Kafka主题中,在这里这些事件可用于驱动...
  • 当它依赖的属性值发生改变时,下一次获取computed的值时才会重新计算。 watch:观测属性,无缓存,更多的作用在于 观察 ,类似于某些数据的监听回调,当监听的属性值发生改变时会触发其绑定的回调函数来进行后续...
  • 当我们需要进行数值计算,并且依赖于其它数据时,应该使用 computed,因为可以利用 computed 的缓存特性,避免每次获取值时,都要重新计算。 当我们需要在数据变化时执行异步或开销较大的操作时,应该使用 watch,使用 ...
  • 介绍了基于OpenGL深度缓存的二维屏幕坐标向三维空间坐标的转换算法,实现了对三维空间坐标和空间距离查询,以及查询标识设置的程序设计;最后讲解了基于键盘和鼠标联合控制的三维场景照相机程序模块的实现,实现三维...
  • 介绍了基于OpenGL深度缓存的二维屏幕坐标向三维空间坐标的转换算法,实现了对三维空间坐标和空间距离查询,以及查询标识设置的程序设计;最后讲解了基于键盘和鼠标联合控制的三维场景照相机程序模块的实现,实现三维...
  • Python数据挖掘工程师(机器学习、深度学习、算法专家) Python爬虫工程师 Python测试工程师(自动化测试、测试开发) 说明:目前,数据分析是一个非常热门的方向,因为不管是互联网行业还是传统行业都已经积累了...

空空如也

空空如也

1 2 3
收藏数 58
精华内容 23
关键字:

获取场景深度缓存