大厂报价查询系统性能优化之道!

news2024/12/22 22:30:25

0 前言

机票查询系统,日均亿级流量,要求高吞吐,低延迟架构设计。提升缓存的效率以及实时计算模块长尾延迟,成为制约机票查询系统性能关键。本文介绍机票查询系统在缓存和实时计算两个领域的架构提升。

1 机票搜索服务概述

1.1 机票搜索的业务特点

机票搜索业务:输入目的地,然后点击搜索,后台就开始卷了。基本1~2s将最优结果反给用户。这个业务存在以下业务特点。

1.1.1 高流量、低延时、高成功率

超高流量,同时,对搜索结果要求也很高——成功率要高,不能查询失败或强说成功,希望能反给用户最优最新数据。

1.1.2 多引擎聚合,SLA不一

机票搜索数据来源哪?很大一部分来源自己的机票运价引擎。为补充产品丰富性,还引入国际一些GDS、SLA,如联航。将外部引擎和自己引擎结果聚合后发给用户。

1.1.3 计算密集&IO密集

大家可能意识到,我说到我们自己的引擎就是基于一些运价的数据、仓位的数据,还有其他一些航班的信息,我们会计算、比对、聚合,这是一个非常技术密计算密集型的这么一个服务。同时呢,外部的GDS提供的查询接口或者查询引擎,对我们来说又是一个IO密集型的子系统。我们的搜索服务要将这两种不同的引擎结果很好地聚合起来。

1.1.4 不同业务场景的搜索结果不同要求

作为OTA巨头,还支持不同应用场景。如同样北京飞上海,由于搜索条件或搜索渠道不一,返回结果有所不同。如客户是学生,可能搜到学生特价票,其他用户就看不到。

2 公司基建

为应对如此业务,有哪些利器?

2.1 三个独立IDC

互相做灾备,实现其中一个IDC完全宕机,业务也不受影响。

2.2 DataCenter技术栈

SpringCloud+K8s+云服务(海外),感谢Netflix开源支撑国内互联网极速发展。

2.3 基于开源的DevOps

我们基于开源做了整套的DevOps工具和框架。

2.4 多种存储方案

公司内部有比较完善可用度比较高的存储方案,包括MySQL,Redis,MangoDB……

2.5 网络可靠性

注重网络可靠性,做了很多DR开发,SRE实践,广泛推动熔断,限流等,以保证用户得到高质量服务。

3 机票搜索服务架构

3.1 架构图

IDC有三个,先引入GateWay分流前端服务,前端服务通过服务治理,和后端聚合服务交互。聚合服务再调用很多引擎服务。

聚合服务结果,通过Kafka推到AI数据平台,做大数据分析、流量回放等数据操作。云上部署数据的过滤服务,使传回数据减少90%。

4 缓存架构

4.1 缓存的挑战和策略

4.1.1 为啥大量使用缓存应对流量高峰?

提高效率、速度的首选技术手段。

虽使用很多开源技术,但还有瓶颈。如数据库是分片、高可用的MySQL,但和一些云存储、云数据库比,其带宽、存储量、可用性有差距,通常需用缓存保护我们的数据库,不然频繁读取会使数据库很快超载。

很多外部依赖,提供给我们的带宽,QPS有限。而公司整体业务量是快速增长的,而外部的业务伙伴给我们的带宽,要么已达技术瓶颈,要么开始收高费用。此时,使用缓存就可保护外部的一些合作伙伴,不至于击穿他们的系统,也可帮我们降本。

4.1.2 本地缓存 VS 分布式缓存

整个架构的演进过程,一开始本地缓存较多,后来部分用到分布式缓存。

本地缓存的主要问题:

  • 启动时,有个冷启动过程,对快速部署不利
  • 与分布式缓存相比,本地缓存命中率太低

对海量的数据而言,单机提供命中率非常低,5%甚至更低。对此,现已全面切向Redis分布式缓存。本着对战failure的理念,不得不考虑失败场景。万一集群挂掉或一部分分片挂掉,这时需要通过限流客户端、熔断等,防止雪崩效应。

4.1.3 TTL
  • 命中率
  • 新鲜度
  • 动态更新

TTL生命周期跟业务强相关。买机票经常遇到:刚在报价列表页看到一个低价机票,点进报价详情页就没了,why?航空公司低价舱位票,一次可能只放几张,若在热门航线,可能同时几百人在查,它们都可能看到这几张票,它就会出现在缓存里。若已有10人订了票,其他人看到缓存再点进去,运价就已失效。对此,就要求权衡,不能片面追求高命中率,还得兼顾数据新鲜度。为保证新鲜度、数据准确性,还有大量定时任务去做更新和清理。

4.2 缓存架构演进

4.2.1 多级缓存

架构图的三处缓存:

  • 引擎级缓存
  • L1分布式聚合缓存,基本上就是用户看到的最终查询结果
  • L2二级缓存,分布式的子引擎结果

若聚合服务需多个返回结果,很大程度都是先读一级缓存,一级缓存没有命中的话,再从二级缓存里面去读中间结果,这样可以快速聚合出一个大家所需要的结果返回。

4.2.2 引擎缓存

引擎缓存:

  • 查询结果缓存
  • 中间产品缓存
  • 基础数据缓存

使用一个多级缓存模式。如下图,最顶部是指引前的结果缓存,储存在Redis,引擎内部根据产品、供应商,有多个渠道的中间结果,所以对子引擎来说会有个中间缓存。

这些中间结果计算,需要数据,这数据就来自最基础的一级缓存。

4.2.3 基于Redis的一级缓存

Pros:

  • 读写性能高
  • 水平扩展

Cons:

  • 固定TTL
  • 命中率和新鲜度的平衡

结果:

  • 命中率<20%
  • 高新鲜度(TTL<5m,动态刷新
  • 读写延迟<3ms

一级缓存使用Redis,是考虑其读写性能好,快速,水平扩展性能,能提高存储量及带宽。但当前设计局限性:

  • 为简单,使用固定TTL,这是为保证返回结果的相对新鲜
  • 为命中率和新鲜度,还在不断提高

目前解决方案还不能完美解决这俩问题。

分析下返回结果,一级缓存命中率小于20%,某些场景更低,就是为保证更高准确度和新鲜度。高优先度,一级缓存的TTL肯定低于5min,有些场景可能只有几十s;支持动态刷新,整体延迟小于3ms。整个运行过程可用性较好。

4.2.4 基于Redis的二级缓存(架构升级)

Pros:

  • 读写性能进一步提升
  • 服务可靠性提升
  • 成本消减

Cons:

  • 增加复杂性替代二级索引

结果:

  • 成本降低90%
  • 读写性能提升30%

4.2.5 基于MongoDB的二级缓存

二级缓存一开始用MongoDB:

  • 高读写性能
  • 支持二级缓存,方便数据清理
  • 多渠道共用子引擎缓存
  • TTL通过ML配置

会计算相对较优TTL,保证特定数据:

  • 有的可缓存久点
  • 有的可快速更新迭代

二级缓存基于MongoDB,也有局限性:

  • 架构是越简单越好,多引入一种存储会增加维护代价(强依赖)
  • 由于MongoDB的license模式,使得费用非常高(Ops)

结果:

  • 但二级缓存使查询整体吞吐量提高3倍
  • 通过机器学习设定的TTL,使命中率提升27%
  • 各引擎平均延时降低20%

都是可喜变化。在一个成熟的流量非常大的系统,能有个10%提升,就是个显著技术特点。

针对MongoDB也做了提升,最后将其切成Redis,通过设计方案,虽增加部分复杂性,但替代了二级索引,改进结果就是成本降低90%,读写性能提升30%。

5 LB演进

  • 系统首要目标满足高可用
  • 其次是高流量支撑

可通过多层的均衡路由实现,把这些流量均匀分配到多个IDC的多个集群。

5.1 目标

  • 高可用

  • 高流量支撑

  • 低事故影响范围

  • 提升资源利用率

  • 优化系统性能(长尾优化)

    如个别查询时间特长,需要我们找到调度算法问题,一步步解决。

5.2 LB架构

负载均衡

  • Gateway,LB,IP直连

  • DC路由规则

  • IP直连+Pooling

    • 计算密集型任务
    • 计算时长&权重
    • 部分依赖外部查询
  • Set化

LB的演进:

公司的路由和负载均衡的架构,非常典型,有GateWay、load、balance、IP直连,在IP基础上实现了一项新的Pooling技术。也实现了Set化,在同一IDC,所有的服务都只和该数据中心的节点打交道,尽量减少跨地区网络互动。

5.3 Pooling

为啥做 Pooling?有些计算密集的引擎,存在耗时长,耗CPU资源多的子任务,这些子任务可能夹杂一些实时请求,所以这些任务可能会留在线程里边,阻塞整个流程。

Pooling就负责:我们把这些子任务放在queue里边,将节点作为worker,总是动态的去取,每次只取一个,计算完了要么把结果返回,要么把中间结果再放回queue。这样的话如果有任何实时的外部调用,我们就可以把它分成多次,放进queue进行task的整个提交执行和应用结果的返回。

5.4 过载保护

有过载保护

  • 扔掉排队时间超过T的请求(T为超时时间),所有请求均超时,系统整体不可用
  • 扔到排队时间超过X的请求(X为小于T的时间),平均响应时间为X+m,系统整体可用。m为平均处理时间

Pooling设计需要一个过载保护,当流量实在太高,可用简单的过载保护,把等待时间超过某阈值的请求全扔掉。当然该阈值肯定小于会话时间,就能保证整个Pooling服务高可用。

虽可能过滤掉一些请求,但若没有过载保护,易发生滚雪球效应,queue里任务越来越多,当系统取到一个任务时,实际上它的原请求可能早已timeout。

img

压测结果可见:达到系统极限值前,有无Pooling两种case的负载均衡差异。如80%负载下,不采用Pooling的排队时间比有Pooling高10倍:

所以一些面临相同流量问题厂家,可考虑把 Pooling 作为一个动态调度或一个control plan的改进措施。

如下图,实现Pooling后平均响应时间基本没大变化,还是单层查询计算普遍60~70ms。但实现Pooling后,显著的键值变少,键值范围也都明显控制在平均时间两倍内。这对大体量服务来说,比较平顺曲线正是所需。

6 AI赋能

6.1 应用场景

6.1.1 反爬

在前端,我们设定了智能反爬,能帮助屏蔽掉9%的流量。

6.1.2 查询筛选

在聚合服务中,我们并会把所有请求都压到子系统,而是会进行一定的模式运营,找出价值最高实际用户,然后把他们的请求发到引擎当中。对于一些实际价值没有那么高的,更多的是用缓存,或者屏蔽掉一些比较昂贵的引擎。

6.1.3 TTL智能设定

整个TTL设定使用ML技术。

6.2 ML技术栈和流程

ML技术栈和模型训练流程:

6.3 过滤请求

开销非常大的子引擎多票,会拼接多个不同航空公司的出票,返给用户。但拼接计算昂贵,只对一部分产品开放。通过机器学习找到哪些查询可通过多票引擎得到最好结果,然后只对这一部分查询用户开放,结果也很不错。

看右上角图片,整个引擎能过滤掉超过80%请求,流量高峰时能把曲线变得平滑,效果显著。整个对于查询结果、订单数,都没太大影响,且节省80%产品资源。这种线上模型运算时间也短,普遍低于1ms。

7 总结

使用了多层灵活缓存,从而能很好的应对高流量的冲击,提高反应速度。

使用可靠的调度和负载均衡,这样就使我们的服务保持高可用状态,并且解决了长尾的查询延迟问题。最后内部尝试了很多技术革新,将适度的AI技术推向生产,从目前来看,机器学习发挥了很好的效果。带来了ROI的提升,节省了效率,另外在流量高峰中,它能够起到很好的削峰作用。以上就是我们为应对高流量洪峰所采取了一系列有针对性的架构改善。

  • 多层,灵活的缓存 -> 流量,速度
  • 可靠的调度和负载均衡 -> 高可用
  • 适度的AI -> ROI,削峰

8 Q&A

Q:啥场景用缓存?

A:所有场景都要考虑缓存。高流量时,每级缓存都能带来很好的保护系统,提高性能的效果,但要考虑到缓存失效的应对措施。

Q:缓存迭代过程咋样的?

A:先有L1,又加L2,主要因为流量越来越大,引擎外部依赖逐渐撑不住,不得不把中间结果也高效缓存,此即L1到L2的演进。二级缓存用Redis替代MongoDB,是出于高可用考虑,费用节省也是一个因素,但更主要是发现自运维的MongoDB比Redis,整体可用性要差很多,所以最后决定切换。

Q:分布式缓存的设计方式?

A:分布式缓存的关键在于它的KV怎么设定?须根据业务场景,如有的KV里加入IP地址,即Pooling,基于Redis建立了它的队列,所以我们queue当中是把这种请求方的IP作为建设的一部分放了进去,就能保证子任务能知道到哪查询它相应的返回结果。

Q:为什么redis的读写延迟能做到3ms以内呢?

A:读写延时低其实主要指读延时,读延时3ms内没问题。

Q:这队列是内存队列?还是MQ?

A:互联队列用Redis,主要是为保证其高可用性。

Q:缓存失效咋刷新,涉及分布式锁?

A:文章所提缓存失效,并非指它里边存的数据失效,主要指整个缓存机制失效。无需分布式锁,因为都是单独的KV存储。

Q:缓存数据一致性咋保证?

A:非常难保证,常用技巧:缓存超过阈值,强行清除。然后若有更精确内容进来,要动态刷新。如本可存5min,但第2min有位用户查询并下单,这时肯定是要做一次实时查询,顺便把还没过期的内容也刷新一遍。

Q:热key,大key咋监控?

A:对我们热区没那么明显,因为一般我们的一个key对应一个点,一个出发地和一个目的地,中间再加上各种渠道引擎的限制。而不像分片,你分成16或32片,可能某一分片逻辑设计不合理,导致那片过热,然后相应硬件直接到瓶颈。

Q:详解Pooling?

A:原理:子任务耗时间不一,若完全基于SOA进行动态随机分,肯定有的计算节点分到的子任务较重,有的较轻,加入Pooling,就好像加入一个排队策略,特别是对中间还会实时调用离开几s的case,排队策略能极大节省计算资源。

Q:监控咋做的?

A:基于原来用了时序数据库,如ClickHouse,和Grafana,然后现在兼容Promeneus的数据收集和API。

Q:二级缓存采用Redis的啥数据类型?

A:二级缓存存储中间结果,应该是分类型的数据类型。

Q;TTL计算应该考虑啥?

A:最害怕数据异常,如系统总返回用户一个已过期低票价,用户体验很差,所以这方面牺牲命中率,然后缩短TTL,只不过TTL控制在5min内,有时还要微调,所以还得用机器学习模型。

Q:IP直连和Pooling没明白,是AGG中涉及到的计算进行拆分,将中间结果进行存储,其他请求里若也需要这中间计算,可直接获取吗?

A:IP直连和PoolingIP直连,其实把负载均匀分到各节点Pooling,只不过你要计算的子任务入队,然后每个运算节点每次取一个,计算完再放回去,这样计算效率更高。中间结果没有共享,中间结果存回是因为有的子任务需要中间离开,再去查其他实时系统,所以就相当于把它分成两个运算子任务,中间的任务要重回队列。

Q:下单类似秒杀,发现一瞬间票抢光了,相应缓存咋更新?

A:若有第1个用户选择了一个运价,没通过,要把缓存数据都给杀掉,然后尽量防止第2个用户还会陷入同样问题。

Q:多级缓存数据咋保证一致?

A:因为我们一级缓存存的是最终的结果,二级缓存是中间结果,所以不需要保持一致。

Q:一级、二级、三级缓存,请求过来,咋提高吞吐量,按理说,每个查询过程都消耗时间,吞吐量应该下降?

A:是的,若无这些缓存,几乎所有都要走一遍。实时计算,时间长,而且部署的集群能响应的数很有限,然后一、二、三级每级都能拦截很多请求。一级约拦截20%,二级差不多40%~50%。此时同样的集群,吞吐量显然明显增加。

Q:如何防止缓存过期时刻产生的击穿问题,目前公司是定时任务主动缓存,还是根据用户请求进行被动的缓存?

A:对于缓存清除,我们既有定时任务,也有被动的更新。比如说用户又取了一次或者购票失败这些情况,我们都是会刷新或者清除缓存的。

Q:搜索结果会根据用户特征重新计算运价和票种吗?

A:为啥我的运价跟别人不一致,是不是被大数据杀熟?其实不是的,那为啥同样查询返回结果不一呢?有一定比例是因为缓存数据异常,如前面缓存的到后面票卖光了,然后又推给了不幸用户。公司有很多引擎如说国外供应商,尤其联航,他们系统带宽不够,可用性不高,延时也高,所以部分这种低价票不能及时返回到我们的最终结果,就会出现这种“杀熟”,这并非算法有意,只是系统局限性。

Q:Pooling 为啥用 Redis?

A:为追求更高读写速度,其他中间件如内存队列,很难用在分布式调度。若用message queue,由于它存在明显顺序性,不能基于KV去读到你所写的,如你发了个子任务,这时你要定时取其结果,但你基于MQ或内存队列没法拿到,这也是一个限制。

Q:多级缓存预热咋保证MySQL不崩?

A:冷启动问题更多作用在本地缓存,因为本地缓存发布有其他的情况,需要预热,在这之间不能接受生产流量。对多级缓存、分布式缓存,预热不是问题,因为它本就是分布式的,可能有部分节点要下线之类,但对整个缓存机制影响很小,然后这一部分请求又分散到我们的多个服务器,不会产生太大抖动。但若整个缓存机制失效如缓存集群完全下掉,还是要通过熔断或限流对实时系统作过载保护。

Q:Redis对集合类QPS不高,咋办?

A:Redis多加些节点,减少它的存储使用率,把整体throughput提上即可。若你对云业务有了解,就知道每个节点都有throughput限制。若单节点throughput成为瓶颈,那就降低节点使用率。

关注我,紧跟本系列专栏文章,咱们下篇再续!

作者简介:魔都技术专家兼架构,多家大厂后端一线研发经验,各大技术社区头部专家博主,编程严选网创始人。具有丰富的引领团队经验,深厚业务架构和解决方案的积累。

负责:

  • 中央/分销预订系统性能优化

  • 活动&优惠券等营销中台建设

  • 交易平台及数据中台等架构和开发设计

    目前主攻降低软件复杂性设计、构建高可用系统方向。

参考:

  • 编程严选网

    本文由博客一文多发平台 OpenWrite 发布!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1490073.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C++的类与对象(二)

目录 结构体内存对其规则 相关面试题 this指针 相关面试题 结构体内存对其规则 1、第一个成员在与结构体偏移量为0的地址处 2、其它成员变量要对齐到某个数字&#xff08;对齐数&#xff09;的整数倍的地址处 对齐数 编译器默认对齐数与该成员大小的较小值&#xff08;v…

学习记录12-单片机代码几种常见命名规则

良好的编程习惯&#xff0c;决定了今后代码的质量。 有很多人平时不注意自己的代码规范&#xff0c;函数和变量命命随心所欲&#xff0c;造成一个星期就不认识自己的代码&#xff0c;于是今天就来分享一点关于软件代码常见的几种命名规则。 匈牙利命名法 匈牙利命名法广泛应用…

RBAC实战

一、权限控制概述 1.1、访问控制目的 在实际的组织中&#xff0c;为了完成组织的业务工作&#xff0c;需要在组织内部设置不同的职位&#xff0c;职位既表示一种业务分工&#xff0c;又表示一种责任与权利。根据业务分工的需要&#xff0c;职位被划分给不同群体&#xff0c;各…

C++:Vector的模拟实现

创作不易&#xff0c;感谢三连 &#xff01;&#xff01; 一&#xff0c;前言 在学习string类的时候&#xff0c;我们可能会发现遍历的话下标访问特别香&#xff0c;比迭代器用的舒服&#xff0c;但是下标其实只能是支持连续的空间&#xff0c;他的使用是非常具有局限性的&am…

迷不迷糊?前后端、三层架构和MVC傻傻分不清

现在的项目都讲究前后端分离&#xff0c;那到底什么是前后端&#xff0c;前后端和以前的MVC以及三层架构啥关系呢&#xff1f;今天就这个问题展开一下&#xff0c;方面后面的学习&#xff0c;因为前面讲的jsp、servlet和javabean根据实例&#xff0c;基本上有一个框架的理解了&…

基于STC12C5A60S2系列1T 8051单片机的TM1638键盘数码管模块的按键扫描、数码管显示按键值、显示按键LED应用

基于STC12C5A60S2系列1T 8051单片机的TM1638键盘数码管模块的按键扫描、数码管显示按键值、显示按键LED应用 STC12C5A60S2系列1T 8051单片机管脚图STC12C5A60S2系列1T 8051单片机I/O口各种不同工作模式及配置STC12C5A60S2系列1T 8051单片机I/O口各种不同工作模式介绍TM1638键盘…

【如何在Docker中,修改已经挂载的卷(Volume)】

曾梦想执剑走天涯&#xff0c;我是程序猿【AK】 提示&#xff1a;添加投票&#xff01;&#xff01;&#xff01; 目录 简述概要知识图谱 简述概要 如何在Docker中&#xff0c;修改已经挂载的卷&#xff08;Volume&#xff09; 知识图谱 在Docker中&#xff0c;修改已经挂载…

消息队列-kafka-消息发送流程(源码跟踪)

官方网址 源码&#xff1a;https://kafka.apache.org/downloads 快速开始&#xff1a;https://kafka.apache.org/documentation/#gettingStarted springcloud整合 发送消息流程 主线程&#xff1a;主线程只负责组织消息&#xff0c;如果是同步发送会阻塞&#xff0c;如果是异…

安装Proxmox VE虚拟机平台

PVE是专业的虚拟机平台&#xff0c;可以利用它安装操作系统&#xff0c;如&#xff1a;Win、Linux、Mac、群晖等。 1. 下载镜像 访问PVE官网&#xff0c;下载最新的PVE镜像。 https://www.proxmox.com/en/downloads 2. 下载balenaEtcher balenaEtcher用于将镜像文件&#…

【Vue3】3-6 : 仿ElementPlus框架的el-button按钮组件实

文章目录 前言 本节内容实现需求完整代码如下&#xff1a; 前言 上节,我们学习了 slot插槽&#xff0c;组件内容的分发处理 本节内容 本小节利用前面学习的组件通信知识&#xff0c;来完成一个仿Element Plus框架的el-button按钮组件实现。 仿造的地址&#xff1a;uhttps://…

docker pull 拉取失败,设置docker国内镜像

遇到的问题 最近在拉取nginx时&#xff0c;显示如下错误&#xff1a;Error response from daemon: Get “https://registry-1.docker.io/v2/”: net/http: request canceled (Client.Timeout exceeded while awaiting headers)。 这个的问题是拉取镜像超时&#xff0c;通过检索…

基于Golang客户端实现Nacos服务注册发现和配置管理

基于Golang客户端实现Nacos服务注册发现和配置管理 背景 最近需要把Golang实现的一个web项目集成到基于Spring Cloud Alibaba的微服务体系中&#xff0c;走Spring Cloud Gateway网关路由实现统一的鉴权入口。 软件版本 组件名称组件版本Nacos2.2.0Go1.21.0Ginv1.9.1Nacos-s…

项目部署发布

目录 上传数据库 修改代码中的数据源配置 修改配置文件中的日志级别和日志目录 打包程序 ​编辑​编辑 上传程序 查看进程是否在运行 以及端口 云服务器开放端口(项目所需要的端口) 上传数据库 通过xshell控制服务器 创建目录 mkdir bit_forum 然后进入该目录 查看路…

【AI+CAD】(一)ezdxf 解析DXF文件

DXF文件格式理解 DXF文件格式是矢量图形文件格式&#xff0c;其详细说明了如何表示不同的图形元素。 DXF是一个矢量图形文件&#xff0c;它捕获CAD图形的所有元素&#xff0c;例如文本&#xff0c;线条和形状。更重要的是&#xff0c;DXF是用于在CAD应用程序之间传输数据的图形…

Java日志框架的纷争演进与传奇故事

在Java的世界里&#xff0c;日志记录是每一个应用不可或缺的部分。它帮助开发者了解应用的运行状态、调试问题、监控性能等。而在这背后&#xff0c;是一系列日志框架的发展与演进。今天&#xff0c;就让我们一起回顾这些日志框架的历史&#xff0c;探寻它们背后的故事。 1. Lo…

分布式数据库中全局自增序列的实现

自增序列广泛使用于数据库的开发和设计中&#xff0c;用于生产唯一主键、日志流水号等唯一ID的场景。传统数据库中使用Sequence和自增列的方式实现自增序列的功能&#xff0c;在分布式数据库中兼容Oracle和MySQL等传统数据库语法&#xff0c;也是基于Sequence和自增列的方式实现…

使用Visual Studio 2022 创建lib和dll并使用

概述&#xff1a;对于一个经常写javaWeb的人来说,使用Visual Studio似乎没什么必要&#xff0c;但是对于使用ffi的人来说&#xff0c;使用c或c编译器&#xff0c;似乎是必不可少的&#xff0c;下面我将讲述如何用Visual Studio 2022 来创建lib和dll&#xff0c;并使用。 静态库…

UNIapp实现局域网内在线升级

首先是UNIapp 生成apk 用Hbuilder 进行打包 可以从网站https://www.yunedit.com/reg?gotocert 使用自有证书&#xff0c;目测比直接使用云证书要快一些。 发布apk 网站 用IIS发布即可 注意事项中记录如下内容 第一、需要在 iis 的MiMe 中添加apk 的格式&#xff0c;否则无法…

Java架构之路-架构应全面了解的技术栈和工作域

有时候我在想这么简单简单的东西&#xff0c;怎么那么难以贯通。比如作为一个架构师可能涉及的不单单是技术架构&#xff0c;还包含了项目管理&#xff0c;一套完整的技术架构也就那么几个技术栈&#xff0c;只要花点心思&#xff0c;不断的往里面憨实&#xff0c;总会学的会&a…

UE4升级UE5 蓝图节点变更汇总(4.26/27-5.2/5.3)

一、删除部分 Ploygon Editing删除 Polygon Editing这个在4.26、4.27中的插件&#xff0c;在5.1后彻底失效。 相关的蓝图&#xff0c;如编辑器蓝图 Generate mapping UVs等&#xff0c;均失效。 如需相关功能&#xff0c;请改成Dynamic Mesh下的方法。 GetSupportedClass删…