关于后端:一座打渔小岛上的经济学-读小岛经济学

书中形容了一座小岛上三个人从徒手捕鱼开始,经济是如何一步步倒退演变的。出发点是以小见大,从一座小岛这个放大精简的模型中,论述经济学的原理。 一个奇妙的比喻能够起到十分好的成果,而不失当比喻往往会减少了解的老本,书中的比喻越到前面,就越偏向于偏差后者,但对于一些概念的解释还是很值得学习的。 资本的定义: 在经济学术语中,资本指的是一种设施,这种设施的建设和应用自身没有什么意义,其意义在于利用设备建设和制作其余须要的货色。艾伯想要的不是那张网,而是鱼。这张网或者能够给他带来更多的鱼。因而,这张网就是一种资本,是有价值的。 经济增长的起因: 找到了生产人类所需物品的更好形式。不论一个经济体最初变得如许弱小,这个起因是不会扭转的。 生产率和价格的关系: 生产效率晋升能够扩充生产规模,升高单位商品老本,升高售价,扩充销量。长期来看随着生产力晋升,价格广泛会降落。 对银行降利率的一种可能: 银行降低利率的一种可能,有时生产率大幅提高,岛上的存鱼量也随之大大增加。如果储藏室里堆满了鱼,银行就会被动升高贷款利率。因为此时银行接受损失的能力较强,而且衰弱的经济也为新企业的倒退提供了良好的环境。 低利率的“益处”: 美联储的决定总是基于政治考量而非经济因素。因为低利率可能使经济外表上体现更好,升高还款压力,还能帮金融公司赚钱,所以很多人都喜爱低利率。谋求连任的总统往往宣扬更低的利率,并对美联储施压。对于美联储的决策者来说,他们天然也心愿本人被看作援救经济的坏蛋,而不愿被当作将经济推向低谷的吝啬鬼。 而且,绝对于储蓄供应来说,过低的利率会向借款人传播谬误的信号,即经济状况良好、投资可行。因为生产并没有真正延后(如果利率适应市场下滑,生产就应该延后),用于满足将来需要的投资就很难胜利。后果就是虚伪的凋敝过后紧接着呈现微小的危机,正如咱们刚刚在股票和房地产市场上经验的那样。 简言之,对政客、公司、资本家都有益处,即可能让游戏继续下去。但对投资人来说可不是好景象,会被短期的增长蒙蔽,在虚伪的凋敝之后会呈现微小的危机。 私人公司和政府来经营公共设施的效率问题: 举例来说,纽约地铁基本上就是由私营公司建设的,而且在近 40 年的工夫里都是由私营公司负责经营。尽管地铁的造价不菲,但还是实现了赢利。更值得一提的是,40 年里车票价格从未上涨。现如今,选民很容易置信大型公共设施都应该由政府经营,比方下水道、高速公路、运河和桥梁这些能够为所有人提供方便的设施。政治家们胜利地让民众置信,唯利是图的私营公司一有机会就会榨取民众的血汗钱。他们用来证实这些论点的证据多半都是从情感上鼓动,引起民众的共鸣。其实咱们更能确定的是,政府对于公共设施和服务的垄断简直必然会造成效率低下和贪污腐败。如果政府工程入不敷出且服务质量很差,自由市场的准则也无奈帮忙其走出窘境。政府通常会通过进步税收填补破绽。这样一来,不仅节约了社会资源,也升高了人们的生存程度。 对于高老本低效率的产业的认识: 比方,如果进口的 T 恤衫比美国外乡生产的 T 恤衫便宜,那么美国人就能够在 T 恤衫上少花一些钱。省下来的钱能够用于生产别的货色,比方滑板。这对于美国国内的公司,比方优良滑板制造商,是很无利的,对那些可能输送其最有价值产品的公司也是无利的。可是美国国内那些制作 T 恤衫的失业工人怎么办呢?如果他们的雇主不能在生产 T 恤衫上找到竞争劣势,这些工人只能去找别的工作。然而,提供待业岗位并非经济的目标。经济的目标是一直进步生产力。保留无效率的劳动力和资本应用形式对整个社会是没有益处的。如果美国在 T 恤衫生产方面没有竞争劣势,那么它就应该找到本人具备劣势的行业。 想借贷,必须先有储蓄。 银行贷款的多少和利率高下,影响最大的应该是银行的储蓄的多少。 多年来,经济学家对美中关系的了解始终是谬误的。大多数人认为那是一种互利互惠的双边关系:美国失去便宜商品和贷款,中国失去制造业的就业机会。然而,这真的是一种双赢的安顿吗?美国人占了便宜:他们不必生产就能够失去商品,不用储蓄就能够失去贷款。而对于中国人来说,他们辛勤工作却不能生产本人生产的产品,他们致力储蓄却得不到贷款。这有什么益处呢?美国的低利率很大水平上是由国外的高储蓄率造成的,大多数当代经济学权威都没有意识到这一点。要记住,想要借贷,就必须先储蓄。所幸,对于美国来说,寰球经济使得借与存的关系能够不受国境的限度。到目前为止,美国手中的王牌始终是美元的位置。作为世界的官网储备货币,美元是所有国际贸易的结算货币。也就是说,不仅仅是美国的贸易搭档,所有人交易时都须要应用美元。所以,即使没有人购买美国的产品,人们也须要美元。而其余任何国家都没有这种运气。外国人持有的美元很多都存在美国的银行里,因此又能够借贷给美国人。这么一来,美国人即便不储蓄也能够取得贷款。人民币和美元严密挂钩,这就要求中国公民至多要将储蓄的一部分兑换成美元。如果没有中国和其余国家的储蓄,美国人以及美国政府想要借钱就会很艰难,他们将不得不承当高额的贷款利率。对于靠贷款推动的美国经济而言,利率偏高和信贷吃紧是一个致命的组合。目前美国领导人和中国的抵触一直降级,在他们决定与中国划清界限之前,须要好好认清这条生命线。当然,既然这种关系不可能永远继续上来,完结得越早,苦楚就越小,对美国人来说尤其如此。白食吃得越久,有朝一日没得吃时,就越是难以自食其力。 本文由mdnice多平台公布

September 7, 2023 · 1 min · jiezi

关于后端:PHP-Composer-的自动加载

PHP 的 autoload 机制,能够在应用一个未导入的类时动静加载该类,从而实现提早加载和治理依赖类文件的目标。 一、没有 composer 时 PHP 是怎么做的__autoload 主动加载器 PHP 中想要应用一个类,必须通过 require (指代 require_once, include_once 等) 的形式在文件结尾申明要应用的类。当我的项目中类较多时,一个个申明加载显然不可行。 在 PHP5 版本,PHP 反对通过 __autoload 定义一个主动加载器,尝试加载未定义的类。 如: // we've writen this code where we needfunction __autoload($classname) { $filename = "./". $classname .".php"; include_once($filename);}// we've called a class ***$obj = new myClass();但 __autoload 函数毛病比拟显著:他只能定义一次,这样就会耦合所有依赖的类的主动加载逻辑,通通写到这个办法里,这时候就须要用到 spl_autoload_register 函数了。 应用 spl_autoload_register 注册多个主动加载器 spl 是 standard php library 的缩写。spl_autoload_register 最大的特点是反对注册多个主动加载器,这样就能实现将各个类库的主动加载逻辑离开,本人解决本人的加载逻辑。 function my_autoloader($class) { var_dump("my_autoloader", $class);}spl_autoload_register('my_autoloader');// 静态方法class MyClass1 { public static function autoload($className) { var_dump("MyClass1 autoload", $className); }}spl_autoload_register(array('MyClass1', 'autoload'));// 非静态方法class MyClass2 { public function autoload($className) { var_dump("MyClass2 autoload", $className); }}$instance = new MyClass2();spl_autoload_register(array($instance, 'autoload'));new \NotDefineClassName();/*输入string(32) "my_autoloader NotDefineClassName"string(36) "MyClass1 autoload NotDefineClassName"string(36) "MyClass2 autoload NotDefineClassName"*/二、PSR 标准PSR 即 PHP Standards Recommendation 是一个社区组织:https://www.php-fig.org/psr/,申明一系列标准来对立开发格调,缩小互不兼容的困扰。标准中的 PSR-4 代表:Autoloading Standard,即主动加载标准。 ...

September 7, 2023 · 4 min · jiezi

关于后端:tornado-的协程调度原理

本文探讨 tornado 的协程实现原理,简略做了一份笔记。 首先看一段最常见的 tornado web 代码: import tornadoimport tornado.webimport tornado.genfrom tornado.gen import coroutinefrom tornado.httpclient import AsyncHTTPClientclass GenHandler(tornado.web.RequestHandler): @coroutine def get(self): url = 'http://www.baidu.com' http_client = AsyncHTTPClient() response = yield http_client.fetch(url) yield tornado.gen.sleep(5) self.write(response.body)class MainHanler(tornado.web.RequestHandler): def get(self): self.write('root')if __name__ == "__main__": application = tornado.web.Application([ (r"/", MainHanler), (r"/gen_async/", GenHandler), ], autoreload=True) application.listen(8888) tornado.ioloop.IOLoop.current().start()其中最初一行代码 tornado.ioloop.IOLoop.current().start() 启动服务。带着几个问题往下看: 晓得 yield 能够暂存执行状态,等「适合的机会」从新复原执行,那么保留的状态到哪去了?上一个问题中「适合的机会」是到底是什么时候?持续接上一个问题,具体是怎么复原执行的?IOLoop 类相当于是对多路复用的封装,起到事件循环的作用,调度整个协程执行过程。 查看 IOLoop 的源码,能够看到 IOLoop 继承自 Configurable,PollIOLoop 又继承自 IOLoop。当 IOLoop 启动时,会确定应用哪一种多路复用形式,epoll、kqueue 还是 select? ...

September 7, 2023 · 4 min · jiezi

关于后端:好奇是开启智慧的钥匙-读朝闻道

本文是刘慈欣的短篇科幻小说,讲述了将来世界人类科学家们围绕赤道制作了一台盘旋加速器,目标是为了做粒子减速试验从而探寻宇宙的神秘,而就在举办试验的当天,试验设施,也就是围绕赤道的减速安装不胫而走了,之后一位外星人来到地球,与科学家们探讨迷信的真谛的故事。 印象粗浅的一段是,当外星人将环赤道的试验安装蒸发掉之后来到地球与科学家见面时,外星人自称是排险者,来到地球是为了阻止人类的试验从而防止宇宙被覆灭的。人类问排险者这是怎么一回事,排险者说,为了防止宇宙文化在探索宇宙的神秘的过程中引发真空衰变导致宇宙覆灭,排险者的文化在宇宙搁置了大量的传感器监督已有生命呈现的世界,当这些世界中呈现有能力产生创世能级能量的文化时,传感器会收回警报,这样排险者就会来到这里亲自监督,而除非文化真的要制作创世能级的试验,否则排险者是不会干涉的。 人类问排险者,地球的传感器是什么时候收回警报的,排险者答复说,传感器第一次收回警报是在距今 37 万年前,非洲大陆上一个原始人俯视星空的工夫超过了预警阈值。地球人不解为什么,排险者说:当生命意识到宇宙神秘的存在时,距它最终解开这个神秘只有一步之遥了。 朝闻道,夕死可矣。出自《论语》,示意对真谛的渴望比生命更重要。构想如果真的存在这样一个真谛祭坛,下来之后你能够晓得所有你想晓得的机密,但晓得后必须死去,你会下来么。抉择下来则明确所有但生命终止,抉择不下来则持续迷茫但仍旧活着。由此引发对生命的意义的思考,活着到底是为了什么?宇宙的意义又是什么?本书并没有给出答案,而且文中提出这个疑难的人是霍金,霍金也成为惟一一个因为没有失去排险者的答案而从真谛祭坛中回到地球的提问者。 另外书中还有一句话:所有的生存都是正当的,咱们没必要相互理解。看着这句话再回头看方才的问题或者生命的意义能够有这么一种解释:如果问人们生命的意义是什么,有的可能答不上来,有的可能说就是柴米油盐,有的答案可能听起来很好笑,有的答案可能让你无奈了解,但正像后面这句话所说的一样,为什么肯定要失去一个所谓精确的、共识性、普适性的答案呢?或者每个人的答案都是正当的,这就是属于每个人本人的生命的意义。 本文由mdnice多平台公布

September 7, 2023 · 1 min · jiezi

关于后端:京沪永远涨是否会涨到永远-读菜场经济学

微博财经博主「财上海」所著,财上海是「京沪永远涨」论调动摇的支持者,本书也不例外,通篇都是以一种论坛式的语气从各种角度一再证实京沪永远涨是如许的正确,倒也算是接地气,全都是大瞎话。 文中对 08 年 4 万亿前因后果和引发的一系列问题谈的比拟清晰,为了提振国内经济缩小美国次贷危机的影响,这笔钱大部分流入到了基建和房地产相干产业,比方在过后的市场环境下本来就产能过剩的钢铁制作,反倒因为大兴土木而变得供不应求。 另外基建和地产带动了一系列行业,更间接的解决了相当大一部分的人员待业,也就是农民工兄弟们。为了这些农民工的生存,为了保待业维稳固,也必须投资放水搞建设。4 万亿之后一片汪洋,钱越来越不值钱,那些原本就没什么贷款的人,相比之下反倒没受什么伤,而吃亏最大的是本来工薪阶层、没买房子、没有投资、每个月老老实实把钱存银行的人。 本书是 2016 年的书,在本书出版后的几年里,不光是京沪,全国的房价都在继续上涨。如果作者站在 2021 年再议论房价,不晓得还会不会保持「京沪永远涨」的论调。不过能够确定的是,将来通胀会越来越重大,钱会越来越不值钱,而房子至多是一种保值的硬通货。 本文由mdnice多平台公布

September 7, 2023 · 1 min · jiezi

关于后端:前辈从业多年的心得分享-读这就是软件工程师

这本书一开始是从左耳朵耗子的推特上看到的出版音讯,是耗子叔和郄小虎等几位前辈分享的各自从业多年的教训和心得,在书中失去的启发: 看书看文档能让你晓得 why,而看代码写代码会让你晓得 how。多看牛人代码,多看牛人的解决办法和思路能够发现门道。和身边的人散伙学习。防止 X-Y 问题: 本想要解决问题 X,私认为能够用 Y 来解决,但又不晓得 Y 怎么做,所以去问他人 Y 怎么做,当大家精力全都放到了 Y 上时,回头发现 Y 并不能很好的解决问题 X,造成大量节约内耗。防止的办法:要一直拼命诘问做这件事的初衷是什么,到底为了解决什么问题。应用常识树或图谱零碎学习,从知识点到知识面的扩大。被动学习与被动学习效率差很多,被动学习个别都是输出的,如浏览,视听。被动学习个别都是输入的,如写博客文章实际和教给别人。豆瓣链接:https://book.douban.com/subject/35313199/ 本文由mdnice多平台公布

September 7, 2023 · 1 min · jiezi

关于后端:2020-年书单

分享一下 2020 年读的一些值得举荐的书: 《上帝掷骰子吗·量子物理史话》 副标题曾经概括的很清晰了,理解量子物理必读书目。《编码·隐匿在计算机软硬件背地的语言》 从灯泡的亮和灭,到电报和继电器;从盲文是怎么传递信息的,到一个加法器的实现。一步步讲述20世纪最平凡的创造计算机是如何产生的。文笔风趣,娓娓道来,理解计算机组成的原理的不二之选。《从一到无穷大》天然科普经典之作,对空间伸缩那里讲的挺有意思的,总体来说还有点费脑子。《图解算法》疾速领略算法的力量,是享受算法盛宴的不错的开胃菜。《Head First 设计模式》看着总如同差点意思,有点啰嗦。《图解 HTTP》起到了一点疾速回顾 HTTP 是怎么回事的书,感觉算个科普,亮点不太突出。《SQL 必知必会》帮女朋友入门 SQL,一起看了这本书,1 小时疾速看一遍,整本书算是个根底 SQL 的索引。本文由mdnice多平台公布

September 7, 2023 · 1 min · jiezi

关于后端:13分钟聊聊并发包中常用同步组件并手写一个自定义同步组件

前言上篇文章10分钟从源码级别搞懂AQS(AbstractQueuedSynchronizer)说到JUC并发包中的同步组件大多应用AQS来实现 本篇文章通过AQS本人来实现一个同步组件,并从源码级别聊聊JUC并发包中的罕用同步组件 本篇文章须要的前置常识就是AQS,如果不理解AQS的同学能够看上一篇文章哈~ 浏览本篇文章大略须要13分钟 自定义同步组件为了更容易了解其余同步组件,咱们先来应用AQS本人来实现一个罕用的可重入锁 AQS模板办法流程是固定的,咱们次要只须要来实现它的尝试获取同步状态和尝试开释同步状态办法即可 首先咱们先规定要实现的可重入锁是独占式的 规定同步状态一开始为0,当有线程获取锁胜利同步状态就为1,当这个线程重入时就累加同步状态 规定开释同步状态时每次扣减1个同步状态,只有当同步状态扣减到0时,才是真正的开释独占锁 咱们应用一个外部类Sync 来继承AQS 并重写tryAcquire尝试获取同步状态、tryRelease 尝试开释同步状态、isHeldExclusively判断以后线程是否持有同步状态(期待、告诉时会用到该办法) static class Sync extends AbstractQueuedSynchronizer { /** * 判断以后线程是否持有同步状态 * * @return */ @Override protected boolean isHeldExclusively() { return getExclusiveOwnerThread() == Thread.currentThread(); } }在获取同步状态中 先判断是否有同步状态(即同步状态是否为0),如果有同步状态就用CAS去获取(0->1),胜利就设置以后线程为获取同步状态的线程如果没有同步状态(即同步状态不为0) ,就查看获取同步状态的线程是否为以后线程,如果是以后线程则阐明此次是重入,累减轻入次数其余状况阐明未获取到同步状态,返回false 后续走AQS流程(构建节点退出AQS) /** * 尝试获取同步状态 * * @param arg 获取同步状态的数量 * @return */ @Override protected boolean tryAcquire(int arg) { //1.获取同步状态 int state = getState(); //2.如果有同步状态则CAS替换 0->1 if (state == 0) { if (compareAndSetState(state, 1)) { //替换胜利 阐明获取到同步状态 设置以后获取同步状态线程 setExclusiveOwnerThread(Thread.currentThread()); return true; } } else if (getExclusiveOwnerThread() == Thread.currentThread()) { //3.没有同步状态 查看获取同步资源的线程是否为以后线程 可重入 累减轻入次数 setState(state + arg); return true; } //其余状况就是没获取到同步状态 return false; }在开释同步状态中 ...

September 7, 2023 · 5 min · jiezi

关于后端:多进程与多线程

Golang Golang的GPM调度模型,多个G即goroutine,是建设在线程之上还是过程之上? 据材料,P为逻辑处理器,M为机器cpu外围数(不是物理外围数,如果有超频,则是超频后的cpu数量),两者数量统一。 用代码验证: package mainimport ( "fmt" "sync")func main() { var wg sync.WaitGroup wg.Add(1) go func() { defer wg.Done() for { fmt.Println("A:", 1) } }() wg.Wait()}运行上述代码go run t.go,而后查看流动监视器 应用runtime.GOMAXPROCS(num)来设置容许该程序应用的cpu数量,最早版本默认为1,起初改为机器的(逻辑)cpu数。所以不设置,就等同于runtime.GOMAXPROCS(runtime.NumCPU())。 查看过程的线程列表: 参考: mac 过程和线程工具 故而,GPM中的M理论指线程。通过形象,在用户级别实现了m个goroutine和n个线程之间的对应(个别m远远大于n) 更多对于golang的调度,可参考: 6.5 调度器 Go goroutine了解 nginx 典型的多过程解决模型 启动ngnix后,查看 流动监视器 如下: 此处的2个用户为nobody的工作过程,在nginx.conf中设置: php 同nginx一样,php-fpm也是多过程模式: 能够查看并批改PHP-CGI过程的数量 redis服务端 面试常问,redis(服务端) 的所谓单线程,指的仅仅是网络申请模块应用了一个线程,即一个线程解决所有网络申请,其余模块仍用了多个线程。且最新版本中,网络申请模也反对多线程 参考: 为什么 Redis 抉择单线程模型 ...

September 7, 2023 · 1 min · jiezi

关于后端:git亲测体验rebase与merge

rebase与merge异同与最佳应用场景 这个dev-cui分支从devlop分支切出后,始终都只有我一个人在开发&保护. 如果还有一位共事张三, 在devlop分支切出的分支dev-zhangsan上进行开发,他增加了一个glossary.md,而后进行了add & commit 此时我的项目开发实现,须要将两个分支合并到devlop分支上: develop分支先合并了dev-cui,(即切到develop分支, 执行git merge命令) git merge接着去合并dev-zhangsan,如果应用git merge, 绿色示意dev-cui分支,紫色示意dev-zhangsan,每一个点代表一次提交. 可见呈现了分叉,且merge操作会主动有一次commit(此处为快进式提交,参看文首链接),见下图: gir rebase先回退到7f8ccb37fdcced4bd4766c8192a6e27fc5f02730, 接着切换到dev-zhangsan分支, 执行git rebase develop, 此刻对于dev-zhangsan分支,曾经有了develop分支的其余提交 而后切回develop分支,执行git merge dev-zhangsan 此时的develop分支的提交log为: git rebase个别称为变基或换基, 这篇blog 将其称为衍合,区别于git merge的合并 其实git rebase后,还是要执行一次git merge. 即有个骨干分支A,有个次分支B,二者切分后,都有许多次提交. 这时想再合并到一起,且心愿commit log是一条直线, 那切到次分支B上,执行git rebase A, 这时就基于A,而后把B的改变"拔掉",而后放到最后面.(B的提交历史此时是一条直线) 而后须要切回骨干分支A,执行git merge B,肯定是一个"快进式提交". 此时对于A,它的commit log就也是一条干线了 本文由mdnice多平台公布

September 7, 2023 · 1 min · jiezi

关于后端:行为型设计模式访问器-Visitor

简介在不扭转原有类的前提下,能够新增不同的拜访器,每种拜访器都可自定义拜访策略。 如超市购物车里什么物品都有,顾客遍历拜访商品次要查看商品是否过期,包装是否残缺,收银员遍历商品次要查看价格。顾客和收银员能够了解为两种Visitor,各自关注的重点就是Visitor中的visit办法实现逻辑。 原始数据构造就像数据库,而拜访器就像基于该数据库的业务逻辑,不同拜访器依照不同业务规定应用数据。 角色形象Visitor 定义拜访每一种Element的办法签名visit 具体Visitor 实现具体拜访办法visit 形象Element 定义accept办法,反对将visitor做参数,通过调用accept办法,实现accept→visitor→visit的调用 具体Element 实现具体方法 类图如图,Element中的accept办法以Visitor做参数,其中调用visitor.visit办法,将主动权交给Visitor去解决。实现每新增一种visitor,对原Element无感知 代码interface Component{ public function accept(Visitor $visitor): void;}class ConcreteComponentA implements Component{ public function accept(Visitor $visitor): void { $visitor->visitConcreteComponentA($this); } public function exclusiveMethodOfConcreteComponentA(): string { return "A"; }}class ConcreteComponentB implements Component{ public function accept(Visitor $visitor): void { $visitor->visitConcreteComponentB($this); } public function specialMethodOfConcreteComponentB(): string { return "B"; }}interface Visitor{ public function visitConcreteComponentA(ConcreteComponentA $element): void; public function visitConcreteComponentB(ConcreteComponentB $element): void;}class ConcreteVisitor1 implements Visitor{ public function visitConcreteComponentA(ConcreteComponentA $element): void { echo $element->exclusiveMethodOfConcreteComponentA() . " + ConcreteVisitor1\n"; } public function visitConcreteComponentB(ConcreteComponentB $element): void { echo $element->specialMethodOfConcreteComponentB() . " + ConcreteVisitor1\n"; }}class ConcreteVisitor2 implements Visitor{ public function visitConcreteComponentA(ConcreteComponentA $element): void { echo $element->exclusiveMethodOfConcreteComponentA() . " + ConcreteVisitor2\n"; } public function visitConcreteComponentB(ConcreteComponentB $element): void { echo $element->specialMethodOfConcreteComponentB() . " + ConcreteVisitor2\n"; }}function clientCode(array $components, Visitor $visitor){ foreach ($components as $component) { $component->accept($visitor); }}$components = [ new ConcreteComponentA(), new ConcreteComponentB(),];echo "The client code works with all visitors via the base Visitor interface:\n";$visitor1 = new ConcreteVisitor1();clientCode($components, $visitor1);echo "It allows the same client code to work with different types of visitors:\n";$visitor2 = new ConcreteVisitor2();clientCode($components, $visitor2);output: ...

September 7, 2023 · 1 min · jiezi

关于后端:行为型设计模式模板方法-Template-Method

简介父类抽象类定义大的解决流程,局部细节做成形象办法,留给子类去实现。 如Java的JUnit中, setUp tearDown办法都是留给具体的测试用例来写,Servlet中service解决了一个申请的大部分工作,留下doGet和doPost给业务自定义解决。 另外callback个别分两种形式:同步回调、异步回调,其中同步回调相似于模板办法模式,异步回调相似于观察者模式。 模板办法要基于继承,而回调更相似组合, 角色形象模板类 定义大的解决流程,留出局部办法给具体类实现 具体模板类 实现具体的解决逻辑 类图如图,ConcreteClass实现了一些具体逻辑 代码abstract class AbstractClass{ final public function templateMethod(): void { $this->baseOperation1(); $this->requiredOperations1(); $this->baseOperation2(); $this->hook1(); $this->requiredOperation2(); $this->baseOperation3(); $this->hook2(); } protected function baseOperation1(): void { echo "AbstractClass says: I am doing the bulk of the work\n"; } protected function baseOperation2(): void { echo "AbstractClass says: But I let subclasses override some operations\n"; } protected function baseOperation3(): void { echo "AbstractClass says: But I am doing the bulk of the work anyway\n"; } abstract protected function requiredOperations1(): void; abstract protected function requiredOperation2(): void; protected function hook1(): void { } protected function hook2(): void { }}class ConcreteClass1 extends AbstractClass{ protected function requiredOperations1(): void { echo "ConcreteClass1 says: Implemented Operation1\n"; } protected function requiredOperation2(): void { echo "ConcreteClass1 says: Implemented Operation2\n"; }}class ConcreteClass2 extends AbstractClass{ protected function requiredOperations1(): void { echo "ConcreteClass2 says: Implemented Operation1\n"; } protected function requiredOperation2(): void { echo "ConcreteClass2 says: Implemented Operation2\n"; } protected function hook1(): void { echo "ConcreteClass2 says: Overridden Hook1\n"; }}function clientCode(AbstractClass $class){ $class->templateMethod();}echo "Same client code can work with different subclasses:\n";clientCode(new ConcreteClass1());echo "Same client code can work with different subclasses:\n";clientCode(new ConcreteClass2());output: ...

September 7, 2023 · 2 min · jiezi

关于后端:行为型设计模式策略-Strategy

简介一组实现了同一个策略接口的策略,能够随时指定用哪一种策略实现业务。 策略模式其实跟桥接模式很像,都是通过持有另一个对象,达到组合的成果。 角色Context 上下文 可设置应用的 Strategy 形象 Strategy具体 Strategy类图如图,Context应用setStrategy办法设置以后应用的策略,在doSomething中,调用策略的execute办法,实现动静应用策略。 代码class Context{ private $strategy; public function __construct(Strategy $strategy) { $this->strategy = $strategy; } public function setStrategy(Strategy $strategy) { $this->strategy = $strategy; } public function doSomeBusinessLogic(): void { echo "Context: Sorting data using the strategy (not sure how it'll do it)\n"; $result = $this->strategy->doAlgorithm(["a", "b", "c", "d", "e"]); echo implode(",", $result) . "\n"; }}interface Strategy{ public function doAlgorithm(array $data): array;}class ConcreteStrategyA implements Strategy{ public function doAlgorithm(array $data): array { sort($data); return $data; }}class ConcreteStrategyB implements Strategy{ public function doAlgorithm(array $data): array { rsort($data); return $data; }}$context = new Context(new ConcreteStrategyA());echo "Client: Strategy is set to normal sorting.\n";$context->doSomeBusinessLogic();echo "Client: Strategy is set to reverse sorting.\n";$context->setStrategy(new ConcreteStrategyB());$context->doSomeBusinessLogic();output: ...

September 7, 2023 · 1 min · jiezi

关于后端:行为型设计模式状态-State

简介跟状态机密切相关。无限状态机 FSM 蕴含 状态、事件、动作三个元素。 当产生一个事件时,引发老状态变成新状态,并执行一个动作。 状态和行为间个别是有限度的,如某些行为只能再某些状态下进行,某些状态只能触发某些行为。 简略的状态间转换可应用 if else。 更有条理的能够用查表法:二维表中纵向是状态,横向是事件,value则是新状态和动作。做成二维数组配置,事件产生时联合以后状态,组成老状态索引去查二维表,得出value是新状态和动作,如果没有value则不变换 再简单一些之后,可应用状态模式。 角色Context 上下文 可视为状态机,其外部持有State援用 可通过扭转State的值,来达到扭转Context行为的目标 形象 State具体 State类图如图,Context/Machine中能够changeState来扭转以后的状态,其中doThis和doThat签名与State统一,这样看起来就像扭转状态的同时,扭转了Context的行为。 代码class Context{ private $state; public function __construct(State $state) { $this->transitionTo($state); } public function transitionTo(State $state): void { echo "Context: Transition to " . get_class($state) . ".\n"; $this->state = $state; $this->state->setContext($this); } public function request1(): void { $this->state->handle1(); } public function request2(): void { $this->state->handle2(); }}abstract class State{ protected $context; public function setContext(Context $context) { $this->context = $context; } abstract public function handle1(): void; abstract public function handle2(): void;}class ConcreteStateA extends State{ public function handle1(): void { echo "ConcreteStateA handles request1.\n"; echo "ConcreteStateA wants to change the state of the context.\n"; $this->context->transitionTo(new ConcreteStateB()); } public function handle2(): void { echo "ConcreteStateA handles request2.\n"; }}class ConcreteStateB extends State{ public function handle1(): void { echo "ConcreteStateB handles request1.\n"; } public function handle2(): void { echo "ConcreteStateB handles request2.\n"; echo "ConcreteStateB wants to change the state of the context.\n"; $this->context->transitionTo(new ConcreteStateA()); }}$context = new Context(new ConcreteStateA());$context->request1();$context->request2();output: ...

September 7, 2023 · 1 min · jiezi

关于后端:行为型设计模式备忘录-Memento

简介容许在不裸露对象实现细节的状况下保留和复原对象之前的状态,该状态保留在对象之外,这样就能够不毁坏原有对象的封装性了。 角色Originator 原发器 即须要被保留状态的类 形象 Memento 备忘录类 定义备忘录根本接口 能够看做成是快照 Snapshot 具体 Memento 备忘录类 实现接口 Caretaker 负责人 即连贯Originator和Memento的类,保护一个Memento队列,通过操作队列实现undo redo的操作 类图图中,ConcreteOriginator通过save办法,生成一个Memento,Caretaker 的history属性保留这些Memento,实现undo操作。 代码class Originator{ private $state; public function __construct(string $state) { $this->state = $state; echo "Originator: My initial state is: {$this->state}\n"; } public function doSomething(): void { echo "Originator: I'm doing something important.\n"; $this->state = $this->generateRandomString(30); echo "Originator: and my state has changed to: {$this->state}\n"; } private function generateRandomString(int $length = 10): string { return substr( str_shuffle( str_repeat( $x = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', ceil($length / strlen($x)) ) ), 1, $length ); } public function save(): Memento { return new ConcreteMemento($this->state); } public function restore(Memento $memento): void { $this->state = $memento->getState(); echo "Originator: My state has changed to: {$this->state}\n"; }}interface Memento{ public function getName(): string; public function getDate(): string;}class ConcreteMemento implements Memento{ private $state; private $date; public function __construct(string $state) { $this->state = $state; $this->date = date('Y-m-d H:i:s'); } public function getState(): string { return $this->state; } public function getName(): string { return $this->date . " / (" . substr($this->state, 0, 9) . "...)"; } public function getDate(): string { return $this->date; }}class Caretaker{ private $mementos = []; private $originator; public function __construct(Originator $originator) { $this->originator = $originator; } public function backup(): void { echo "\nCaretaker: Saving Originator's state...\n"; $this->mementos[] = $this->originator->save(); } public function undo(): void { if (!count($this->mementos)) { return; } $memento = array_pop($this->mementos); echo "Caretaker: Restoring state to: " . $memento->getName() . "\n"; try { $this->originator->restore($memento); } catch (\Exception $e) { $this->undo(); } } public function showHistory(): void { echo "Caretaker: Here's the list of mementos:\n"; foreach ($this->mementos as $memento) { echo $memento->getName() . "\n"; } }}$originator = new Originator("Super-duper-super-puper-super.");$caretaker = new Caretaker($originator);$caretaker->backup();$originator->doSomething();$caretaker->backup();$originator->doSomething();$caretaker->backup();$originator->doSomething();echo "\n";$caretaker->showHistory();echo "\nClient: Now, let's rollback!\n\n";$caretaker->undo();echo "\nClient: Once more!\n\n";$caretaker->undo();output: ...

September 7, 2023 · 2 min · jiezi

关于后端:COMP-3704-网络安全

COMP 3704 NETWORK SECURITY:ASSIGNMENT 1 Submission deadline: Friday 1st September, 2023, 5:00pm AETSubmission Procedure: see Wattle page for this course.This assignment will be worth 30% of the total marks for this course. 1. OverviewThe assignment takes the form of a CTF. You are given an ip address from which you canobtain up to 12 flags. You are not told beforehandany information about problems thoughcan expect the vulnerabilities will have been covered in the lectures. Please be careful tofollow the assignment instructions when preparing your report for submission. ...

September 7, 2023 · 3 min · jiezi

关于后端:ToplingDB-CSPP-MemTable-设计精要

(一)背景ToplingDB,尽管 fork 自 RocksDB 并且兼容其 API,但实现了本性难移的改良,最重要的就是实现了性能更高的 CSPP MemTable(Rep) 和 SST。CSPP MemTable 基于 Topling CSPP Trie,无论读写,CSPP Trie 的单线程性能都很高,并且多线程性能近乎线性扩大。本文具体介绍如何将 CSPP Trie 的能力利用到 MemTable。在 RocksDB 中,MemTable 设计上分两层,下层叫 MemTable, 上层叫 MemTableRep,下层是 MemTable 公共代码,间接与 DB 进行交互,MemTableRep 是凋谢的接口层,能够有不同的实现,仅被 MemTable 应用,不间接与 DB 进行交互。(二)CSPP MemTableRepCSPP Trie 的构造函数:MainPatricia::MainPatricia(size_t valsize, intptr_t maxMem, ConcurrentLevel, fstring fpath_or_conf) {...}其中 valsize 参数指该 CSPP Trie 的所有 Value(此 Value 非 DB 的 Value) 其长度都是定长 valsize,当 valsize == 0 时,CSPP Trie 相当于是个 std::set<string>,非 0 时,相当于 std::map<string, FixLenValue>(FixLenValue 必须是 POD 类型)。在 MemTable 中,一个 UserKey 会有多个版本,咱们实现该性能对应的逻辑等效品是:std::map<string, vector<pair<Tag, string> > // Tag is uint64{Seq(56 bits), ValueType(8 bits)}这与 RocksDB 的 SkipList MemTable 不同,SkipList 通过 InternalComparator 来实现该性能,其逻辑等效品是:// InternalComparator 先比拟 UserKey,再比拟 Tag,Seq 从大到小std::map<pair<string, Tag>, string, InternalComparator> 在 CSPP Trie 的单块内存中,不能用原始指针,而应用 uint32 整数代替指针,并且咱们对齐到 4 字节,于是最低 2 bit 都是 0,所以咱们将 uint32 转化为 uint64 再左移 2 位,从而就能够用 32 位的整数来实现 16G 的寻址范畴。这样做最大的益处是该单块内存能够 memmove,能够存储到文件再间接 mmap……麻烦之处在于,咱们要手工进行将偏移转化为内存地址,还要手工实现这种 vector 的追加、搜寻等等,一个繁难的实现计划就像这样:VecMeta 相似于 std::vector 对象自身(蕴含 data_ptr, size, capacity),咱们同时把 size/num 的最高位作为 lock bit,作为 UserKey 级别的锁——多个线程并发写同一个 UserKey 时。前面的逻辑就都比较简单了:应用 VecMeta 实现逻辑 std::vector<Entry>,其中 Entry 是:struct alignas(uint32) Entry { uint32 value_offset; uint64 tag;};而后再顺着 Entry.value_offset 拜访 Value 内容,Value 内容跟 SkipList 完全相同,都是以变长编码 value length 的作为前缀,前面跟 value 的数据内容。RocksDB 的 MemTable/MemTableRep 本来 Key 和 Value 都是变长 len 前缀编码的,因为其所有的 MemTableRep 都是基于比拟的容器,保留了 Key 的原始内容,这样的设计很正当。而 CSPP Trie 并不保留原始 Key,而是在搜寻过程中重建 Key,RocksDB 的接口设计就不适合了,所以咱们对其进行了重构,将 Key 的类型泛化为 Slice,对其本来的 MemTableRep,转调一下即可。Value 的编码方式咱们没有必要改变,仍放弃原样,以缩小代码批改,并放弃兼容性。(三)Copy On WriteCSPP Trie 在多线程并发插入的时候,应用了 Copy On Write,从而后面的 FixLenValue(具体为 VecMeta) 局部就可能会被 Copy On Write,如果线程 A 和 B 并发执行,A 正在 Copy On Write VecMeta,线程 B 正在批改 VecMeta.num,这就完蛋了,线程 B 批改的是旧的 num(线程 A 执行 Copy On Write 之前的 num)!每到这种时候,咱们都会想到一个计划:退出一个中间层!于是咱们失去:退出这个高亮的中间层,它就是简略的 uint32,作为一个指针,指向 VecMeta,这个 uint32 一旦调配,永不扭转,所以听凭 CSPP Trie 怎么 Copy On Write,都不会有影响。首次插入一个 UserKey 时,在 CSPP MemTable 中,牵涉到 3 块内存的调配(在 CSPP Trie 的 mempool 中):len 前缀编码后的 ValueEntryVec 中的 Entry(此时只有一个 Entry)VecMeta这 3 块内存咱们最后为每块内存独自调用调配函数,起初意识到,这些内存大多时候会一起拜访,特地是大多数 UserKey 都只有一条 Entry。所以这三个内存调配就合成了一次调配,而后三块内存各取所需,所以,逻辑上它们是三块内存,但物理上紧紧相邻,改善了空间局部性,从而进步 CPU cache 命中率。(四)ConvertToSSTCSPP Trie 外部的 mempool 能够是文件 mmap,咱们利用这个能力,能够将 MemTable 间接“转化”成 SST,防止了通过 MemTable Flush 遍历 MemTable 将所有 KeyValue 逐条写入 SST。既优化了 IO,又升高了 CPU 和内存的耗费。具体内容,能够看:对于共享内存shm和内存映射mmap的区别是什么? - 知乎 (zhihu.com)【完】 ...

September 7, 2023 · 2 min · jiezi

关于后端:终于产完了Zookeeper-打怪升级进阶成神之路2023最新版

大家好,我是民工哥! 后面给大家介绍了:关系型数据库 MySQL 、 NoSQL 数据库 Redis 、 MongoDB 、搜索引擎 ElasticSearch 、大数据 Hadoop 框架、PostgreSQL 数据库、消息中间件 Kafka 等常识体系学习的文章。 在当今这样的待业大背景下,卷是必定的,弱小本人也是必须的。所以,学习不能停,必须始终卷上来。截止明天,又一个常识体系的学习之旅: 分布式协调中间件 Zookeeper 系列 卷完了。 明天 ,终终终于卷完了!!!! 如有帮忙,请点在赞、转发反对一波!!! 什么是 ZookeeperzooKeeper 是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,是Hadoop和Hbase的重要组件。官网文档上这么解释zookeeper,它是一个分布式协调框架,是 Apache Hadoop 的一个子项目,它次要是用来解决分布式应用中常常遇到的一些数据管理问题,如:对立命名服务、状态同步服务、集群治理、分布式应用配置项的治理等。是一个为分布式应用提供一致性服务的软件。zooKeeper的指标就是封装好简单易出错的要害服务,将简略易用的接口和性能高效、性能稳固的零碎提供给用户。 官网:https://zookeeper.apache.org/ 为什么要应用Zookeeper在大型企业的开发中,服务的数量是非常宏大的。如果咱们想要增加一个服务的话,那么就须要对文件进行从新笼罩,把整个容器重启。这样导致的后果是就是:波及影响太大,保护十分困难。 此时,便须要一个可能动静注册服务和获取服务信息的中央,来对立治理服务,这个中央便称为称为服务配置核心。而zookeeper不仅实现了对cusumer和provider的灵便治理,平滑过渡性能,而且还内置了负载平衡、被动告诉等性能,使咱们可能简直实时的感应到服务的状态。可能很好的帮咱们解决分布式相干的问题,至今仍是市面上支流的分布式服务注册核心技术之一。 进阶分布式系统架构系列(一):Zookeeper 根底概念、性能与利用场景 进阶分布式系统架构系列(二):Zookeeper 典型利用场景详解 进阶分布式系统架构系列(三):Zookeeper 部署(单机与集群)实际 进阶分布式系统架构系列(四):Zookeeper 罕用治理命令 进阶分布式系统架构系列(五):Zookeeper 节点(znode)详解 进阶分布式系统架构系列(六):Zookeeper 选举机制 进阶分布式系统架构系列(七):Zookeeper 监听机制 进阶分布式系统架构系列(八):Zookeeper 集群 ZAB 协定 进阶分布式系统架构系列(九):Zookeeper 配置核心 进阶分布式系统架构系列(十):Zookeeper 注册核心 进阶分布式系统架构系列(十一):Zookeeper 数据与存储管理 进阶分布式系统架构系列(十二):Zookeeper 会话与事务管理 进阶分布式系统架构系列(十三):Zookeeper 分布式锁原理与实现 进阶分布式系统架构系列(十四):Zookeeper 开源客户端工具 进阶分布式系统架构系列(十五):Zookeeper 可视化工具 进阶分布式系统架构系列(十六):Zookeeper 实战(基于 kafka 实现的日志收集平台) 进阶分布式系统架构系列(十七):Zookeeper 运维实际经验总结 明天 ,终终终于卷完了!!!! 心愿大家可能从中播种多多!如有帮忙,请点在赞、转发反对一波!!!

September 7, 2023 · 1 min · jiezi

关于后端:如何在大众点评或高德地图上找到附近的餐馆

如何在公众点评或高德地图上找到左近的餐馆?咱们如何在公众点评或高德地图上找到左近的餐馆? 这里须要设计两个要害服务 (见下图): 业务服务增加、删除和更新餐厅信息顾客查看餐厅详细信息定位服务 (LBS, Location-Based Service)给定半径和地位,返回左近的餐馆列表 那么咱们如何在数据库中存储餐厅的地位,以便定位服务能够高效地返回后果呢? 在数据库中间接存储餐厅的经度和纬度?这样咱们须要计算与每家餐厅之间的间隔,查问效率非常低。 放慢搜寻速度的办法之一是应用Geohash算法。 首先,沿本初子午线和赤道将地球划分为四个象限: 纬度范畴[-90,0];纬度范畴[-90,0]。 纬度范畴 [-90, 0] 用 0 示意纬度范畴 [0, 90] 用 1 示意经度范畴 [-180, 0] 用 0 示意经度范畴 [0, 180] 用 1 示意其次,将每个网格划分为四个较小的网格。每个网格能够用经度位和纬度位交替编码。 因而,当你想在红色高亮区块中搜寻左近的餐馆时,能够编写如下 SQL 语句 SELECT * FROM geohash_index WHERE geohash LIKE `01%`Geohash有一些局限性。一个区域可能有很多餐厅 (比方大城市核心城区),而另一个区域却一家也没有 (比方陆地或农田)。因而,还有其余更简单的算法来优化这一过程。 如果你对细节感兴趣,欢送留言通知我。 【关注公众号:ByteByteGo】 本文由mdnice多平台公布

September 7, 2023 · 1 min · jiezi

关于后端:quarkus依赖注入之四选择注入bean的高级手段

欢送拜访我的GitHub这里分类和汇总了欣宸的全副原创(含配套源码):https://github.com/zq2599/blog_demos本篇概览本文是《quarkus依赖注入》系列的第四篇,在利用中,一个接口有多个实现是很常见的,那么依赖注入时,如果类型是接口,如何精确抉择实现呢?前文介绍了五种注解,用于通过配置项、profile等伎俩抉择注入接口的实现类,面对复杂多变的业务场景,有时候仅靠这两种伎俩是不够的,最好是有更自在灵便的形式来抉择bean,这就是本篇的内容,通过注解、编码等更多形式抉择bean本篇波及的抉择bean的伎俩有以下四种:修饰符匹配Named注解的属性匹配依据优先级抉择写代码抉择对于修饰符匹配为了阐明修饰符匹配,先来看一个注解<font color="blue">Default</font>,其源码如下@Target({ TYPE, METHOD, PARAMETER, FIELD })@Retention(RUNTIME)@Documented@Qualifierpublic @interface Default { public static final class Literal extends AnnotationLiteral<Default> implements Default { public static final Literal INSTANCE = new Literal(); private static final long serialVersionUID = 1L; }}Default的源码在这里不重要,要害是它被注解<font color="blue">Qualifier</font>润饰了,这种被<font color="blue">Qualifier</font>润饰的注解,咱们权且称之为<font color="red">Qualifier修饰符</font>如果咱们新建一个注解,也用<font color="blue">Qualifier</font>来润饰,如下所示,这个MyQualifier也是个<font color="red">Qualifier修饰符</font>@Qualifier@Retention(RUNTIME)@Target({TYPE, METHOD, FIELD, PARAMETER})public @interface MyQualifier { @Nonbinding String value();}在quarkus容器中的每一个bean都应该有一个<font color="red">Qualifier修饰符</font>在润饰,如下图红框,如果没有,就会被quarkus增加<font color="blue">Default</font>注解依赖注入时,间接用<font color="red">Qualifier修饰符</font>润饰注入对象,这样quarkus就会去寻找被这个<font color="red">Qualifier修饰符</font>润饰的bean,找到就注入(找不到报错,找到多个也报错,谬误逻辑和之前的一样)所以用<font color="blue">修饰符匹配</font>来抉择bean的实现类,一共分三步:假如有名为<font color="blue">HelloQualifier</font>的接口,有三个实现类:HelloQualifierA、HelloQualifierB、HelloQualifierC,业务需要是应用HelloQualifierA第一步:自定义一个注解,假如名为<font color="blue">MyQualifier</font>,此注解要被<font color="red">Qualifier</font>润饰第二步:用<font color="blue">MyQualifier</font>润饰HelloQualifierA第三步:在业务代码的注入点,用<font color="blue">MyQualifier</font>润饰HelloQualifier类型的成员变量,这样成员变量就会被注入HelloQualifierA实例仅凭文字描述,很难把信息精确传递给读者(毕竟欣宸文化程度极其无限),还是写代码实现上述场景吧,聪慧的您一看就懂编码演示修饰符匹配:筹备工作先依照后面的假如将接口和实现类筹备好,造成一个接口有多个实现bean的事实,而后,再用修饰符匹配来精确选定bean首先是接口<font color="blue">HelloQualifier</font>,如下所示package com.bolingcavalry.service;public interface HelloQualifier { String hello();}实现类<font color="blue">HelloQualifierA</font>,返回本人的类名package com.bolingcavalry.service.impl;import com.bolingcavalry.service.HelloQualifier;import javax.enterprise.context.ApplicationScoped;@ApplicationScopedpublic class HelloQualifierA implements HelloQualifier { @Override public String hello() { return this.getClass().getSimpleName(); }}实现类HelloQualifierB、HelloQualifierC的代码和下面的HelloQualifierA雷同,都是返回本人类名,就不贴出来了对于应用HelloQualifier类型bean的代码,咱们就在单元测试类中注入吧,如下所示:package com.bolingcavalry;import com.bolingcavalry.service.HelloQualifier;import com.bolingcavalry.service.impl.HelloQualifierA;import io.quarkus.test.junit.QuarkusTest;import org.junit.jupiter.api.Assertions;import org.junit.jupiter.api.Test;import javax.inject.Inject;@QuarkusTestpublic class QualifierTest { @Inject HelloQualifier helloQualifier; @Test public void testQualifier() { Assertions.assertEquals(HelloQualifierA.class.getSimpleName(), helloQualifier.hello()); }}下面的代码中,成员变量<font color="blue">helloQualifier</font>的类型是HelloQualifier,quarkus的bean容器中,HelloQualifierA、HelloQualifierB、HelloQualifierC等三个bean都合乎注入要求,此时如果执行单元测试,应该会报错:同一个接口多个实现bean的问题执行单元测试,如下图,黄框中给出了两个线索:第一,谬误起因是注入时发现同一个接口有多个实现bean,第二,这些bean都是用<font color="blue">Default</font>润饰的,而后是绿框,外面将所有实现bean列出来,不便开发者定位问题 ...

September 7, 2023 · 2 min · jiezi

关于后端:MySQL为什么不推荐使用in

有的时候博客内容会有变动,首发博客是最新的,其余博客地址可能会未同步,认准https://blog.zysicyj.top首发博客地址 系列文章地址 当应用IN语句时,MySQL可能会遇到以下问题: 索引问题:MySQL应用索引来减速查问,但在应用IN语句时,MySQL可能无奈无效地应用索引。这是因为IN语句中的值列表可能是动静的,无奈提前确定索引的应用状况。当MySQL无奈应用索引时,它将执行全表扫描,逐行比拟每个值,这会导致查问性能降落。内存耗费:当应用IN语句时,MySQL须要将值列表中的所有值加载到内存中进行比拟。如果值列表很大,可能会导致内存耗费过高,甚至引发内存溢出的问题。这对于内存无限的零碎来说尤其重要。查问优化器的限度:MySQL的查问优化器在解决IN语句时可能会遇到一些限度。例如,优化器可能无奈精确预计IN语句的选择性,从而导致抉择不适合的查问打算。这可能导致性能降落,因为抉择了不适合的索引或执行形式。为了解决这些问题,咱们能够思考应用其余查问操作符来代替IN语句,例如: JOIN语句:应用JOIN语句能够将多个表连接起来,依据关联条件进行查问。JOIN语句通常可能更好地利用索引,并且在解决大量数据时更高效。子查问:子查问是将一个查问嵌套在另一个查问中。通过应用子查问,咱们能够将IN语句拆分为多个较小的查问,从而进步查问性能。当然,每个具体的状况都是不同的,所以在抉择查问操作符时,咱们须要依据具体的需要和数据状况进行评估和测试。在优化查问性能时,咱们能够应用MySQL的查问剖析工具来帮忙咱们了解查问的执行打算和性能瓶颈,从而做出更好的决策。 本文由mdnice多平台公布

September 6, 2023 · 1 min · jiezi

关于后端:Java中有哪些方式能实现锁某个变量

有的时候博客内容会有变动,首发博客是最新的,其余博客地址可能会未同步,认准https://blog.zysicyj.top首发博客地址 系列文章地址 在Java中,有几种形式能够实现对某个变量的锁定: 应用synchronized关键字:synchronized关键字是Java中最罕用的实现锁的形式之一。通过在办法或代码块中应用synchronized关键字,能够确保同一时间只有一个线程能够拜访被锁定的变量或代码块。例如:synchronized void synchronizedMethod() { // 代码块被锁定,只能被一个线程执行 // ...}void someMethod() { synchronized (this) { // 代码块被锁定,只能被一个线程执行 // ... }}应用ReentrantLock类:ReentrantLock是Java提供的一个可重入锁实现类。与synchronized关键字相比,ReentrantLock提供了更多的灵活性和性能,例如可定时的、可中断的、偏心的锁等。应用ReentrantLock能够通过lock()和unlock()办法来手动管制对变量的锁定和开释。例如:import java.util.concurrent.locks.ReentrantLock;ReentrantLock lock = new ReentrantLock();void someMethod() { lock.lock(); // 锁定变量 try { // 代码块被锁定,只能被一个线程执行 // ... } finally { lock.unlock(); // 开释锁 }}应用Atomic类:Java提供了一系列的原子类,如AtomicInteger、AtomicLong等,它们提供了一种线程平安的形式来操作变量。这些原子类应用了底层的CAS(Compareand Swap)操作,能够实现对变量的原子性操作,防止了应用锁的开销。例如:import java.util.concurrent.atomic.AtomicInteger;AtomicInteger counter = new AtomicInteger();void increment() { counter.incrementAndGet(); // 原子性地减少变量的值}应用volatile关键字:volatile关键字用于润饰变量,确保对该变量的读写操作具备可见性,即一个线程对该变量的批改对其余线程是可见的。尽管volatile关键字不能实现像锁那样的互斥拜访,但它能够用于确保变量的一致性。例如:volatile boolean flag = false;void someMethod() { flag = true; // 对volatile变量的写操作}void anotherMethod() { if (flag) { // 对volatile变量的读操作 // ... }}应用Lock接口的实现类:除了ReentrantLock,Java还提供了其余实现了Lock接口的类,如ReadWriteLock、StampedLock等。这些类提供了更多的锁定机制和性能,例如读写锁、乐观锁等。依据具体的需要,能够抉择适合的Lock实现类来实现对变量的锁定。应用synchronized关键字的Lock对象:除了应用synchronized关键字锁定办法或代码块外,还能够应用synchronized关键字锁定一个特定的对象,即应用synchronized关键字的Lock对象。这种形式能够更细粒度地管制对变量的锁定。例如:Object lock = new Object();void someMethod() { synchronized (lock) { // 代码块被锁定,只能被一个线程执行 // ... }}除了后面提到的形式,还有其余一些形式能够在Java中对变量进行锁定: ...

September 6, 2023 · 2 min · jiezi

关于后端:本地开发环境大小写不敏感引发的问题

举荐浏览 大小写敏感知多少 文件大小写与文件系统无关,与操作系统无关。 血泪教训--拿到新移动硬盘该做的第一件事 MacOS 默认的文件系统APFS,如果没有手动更改,默认不辨别大小写(能够在初始化时设置为大小写敏感)。 而公司测试/生产环境多为 Linux 零碎,个别应用EXT3/EXT4 文件系统, 辨别大小写。 <font size=1>Windows 应用的 NTFS 和 FAT 系列文件系统,默认大小写不敏感但大小写保留</font> 因而可能呈现Mac开发&自测时合乎预期,但一到测试/正式环境等后续环节就出bug的状况。 以下为工作中实在遇到的一例case: Go中 一个文件夹下只能有一个package, package名称和文件夹名称不须要一样。go语言中package和文件夹的关系 但在想import这个package时,须要指定到文件夹名称。 还能够参照了解go import时的下划线--举荐浏览,对援用的package的名称做各种trick 我的项目用到一个第三方库(此处为自行mock), package mainimport ( "fmt" "github.com/cuishuang/utils/strOpt")// 验证大小写不敏感导致的问题func main() { rawStr := "($666789$ && $888123$) || $31415$" rs := stringOpt.GetObjFromTwoSymbol(rawStr) fmt.Println("两头的数字为:", rs)}go.mod为: module blogggo 1.16require github.com/cuishuang/utils v0.0.2本地运行失常 如果在开发过程中,不小写将"github.com/cuishuang/utils/strOpt"写成了"github.com/cuishuang/utils/stropt",能够理论批改试验,在Mac上没有任何问题,能够失常找到这个package 但在Linux上(此处是在Mac上的Docker中模仿),则会报错 go get: module github.com/cuishuang/utils@upgrade found (v0.0.2), but does not contain package github.com/cuishuang/utils/stropt ...

September 6, 2023 · 1 min · jiezi

关于后端:Linux进程间通信IPC的几种方式

概述: 过程间通信(IPC,Inter-Process Communication),指至多两个过程或线程间传送数据或信号的一些技术或办法。过程是计算机系统分配资源的最小单位(过程是分配资源最小的单位,而线程是调度的最小单位,线程共用过程资源)。每个过程都有本人的一部分独立的系统资源,彼此是隔离的。为了能使不同的过程相互拜访资源并进行协调工作,才有了过程间通信。 次要办法: <font color="LightSeaGreen">管道:</font>分为两种, 软管道: 如 ps -ef | grep xxxx, 硬管道: <font color="LightSeaGreen"> 音讯队列:</font>内核创立一个音讯队列,操作系统中的多个过程都能够操作这个音讯队列.能够向其发送音讯,也可从中接管音讯. <font color="LightSeaGreen"> 共享内存:</font>每个过程都有一个虚拟内存地址和物理内存地址的映射,个别两个过程的映射的物理内存地址是不同的,共享内存即是将其映射的物理内存地址变成一样的.这样两个过程就能够拜访雷同的物理内存,也就能够实现过程之间的通信. <font color="LightSeaGreen"> 套接字:</font>十分常见,如通过3306端口拜访某个近程mysql服务, 我拜访mysql的这个过程,和近程的这个mysql服务的过程之间的通信,就是通过3306端口创立的TCP的套接字. 如果是拜访本机的mysql服务,则不会走TCP套接字,而是走Linux底层的套接字 <font color="LightSeaGreen"> 信号量:</font>相似一个计数器.管制多个过程对一个共享资源的拜访. <font color="LightSeaGreen"> 信号:</font>一个过程能够向另一个过程发送一个信号.通过kill -l指令能够列出所有的信号 (64种死法...) Linux中的信号 大多数作用是把一个过程杀死,于是叫kill了.. 当tail -f xxx文件时,是会始终是阻塞. 如何完结? 个别会按ctrl+c, 其实该命令就是以后的shell($$能够看到以后shell的pid),向tail -f过程发送了一个信号,该信号值是2,即SIGINT kill -9 pid, 9号信号是SIGKILL. 如果不加,则默认15号信号SIGTERM(即Terminal) 9号信号即kill信号是不能被捕获的,必须强制进行. 其余信号能够在程序中捕捉到. ctrl+c : SIGINT kill不带参数: SIGTERM KILL -9: SIGKILL 各个编号的含意,可参见linux kill -l 信号列表 本文由mdnice多平台公布 ...

September 6, 2023 · 1 min · jiezi

关于后端:CPU及并发

2.9G Hz,即每秒进行2.9G次运算(即29亿次) 几个命令 us: 用户应用的cpusy: 零碎(内核)应用的cpuid: idle,即闲暇cpuwa: 期待I/O的cpust: 开虚拟机后会有的一个指标,即虚拟机的cpu使用率 一个过程领有一整套虚拟地址空间,该过程的所有线程都共享该地址空间. 线程是CPU运算的最小单位.CPU不关注是哪个过程,只是轮换着线程来运行,不须要晓得该线程属于哪个过程. 线程的五种状态:只有运行中占用CPU资源,其余包含阻塞状态,都不占用CPU资源. 应用线程池,能够优化线程创立/销毁带来的性能损耗(申请cpu计算资源需进入内核态) 协程是用户自定义的线程,不须要进入内核态进入申请计算资源.(这里的用户就是指应用程序及编程语言了..) CPU性能掂量参数 主频 主频又称时钟频率,指CPU外部晶振的频率,罕用单位为MHz或GHz,它反映了CPU的根本工作节奏; 个别用 f 示意 (frequency) 时钟周期 时钟周期 $ t = \frac{1}{f} $ 即 时钟周期 = 主频的倒数 机器周期 机器周期 = m*t 一个机器周期蕴含若干个时钟周期 指令周期 指令周期 = m*t*n 执行一条指令所须要的工夫,个别蕴含若干个机器周期 CPI CPI = m*n; 每条指令的均匀时钟周期个数 指令周期 = CPI×机器周期 = n(CPI=n)×m×时钟周期=nm/主频f 留神指令周期单位是s或者ns,CPI无穷纲 ...

September 6, 2023 · 1 min · jiezi

关于后端:route命令小结

Destination: 如果不满足该列的任何一个ip,则走默认的default Gataway: *是 不指定gateway.有的零碎是0.0.0.0,与*意义雷同 Genmask: 0.0.0.0是不指定掩码, 255.255.0.0掩码了16位,172.17 结尾的ip,会走这个网关 255.255.255.0掩码了16位,192.168.0 结尾的ip都会走这个网关 当是255.255.255.255时,则阐明指定的是具体的一个ip,掩码全掩了 Flasgs指定不是很重要, 可能有三种标识: U: usedG: gatewayH: host Metric 是下一跳,也不重要 Ref 为被援用次数,不重要 Iface 是指通过哪张网卡进行数据的路由 traceroute命令比ping指令好用 本文由mdnice多平台公布

September 6, 2023 · 1 min · jiezi

关于后端:5个案例和流程图让你从0到1搞懂volatile关键字

volatile随着硬件的晋升,机器的外围数从已经的单核变为多核,为了晋升机器的利用率,当初的并发编程变得越来越重要,成为工作中、面试中的重中之重,而为了可能更好的了解、应用并发编程,就应该构建出本人的Java并发编程常识体系。 本篇文章将围绕Java中的volatile关键字,深入浅出的形容原子性、可见性、有序性,volatile的作用、实现原理、应用场景以及波及到的JMM、伪共享等问题 为了更好的形容volatile,咱们先来聊聊它的前置常识:有序性、可见性、原子性 有序性什么是有序性? 当咱们应用高级语言和简略的语法进行编程时,最终还要将语言翻译为CPU意识的指令 因为干活的是CPU,为了放慢CPU的利用率,会对咱们流程管制的指令进行重排序 在Java内存模型中,指令重排序的规定须要满足后行先产生(happens-before)规定,比如说对一个线程的启动要后行产生于这个线程的其余操作,不能把启动线程的指令重排序到线程执行的工作前面 也就是说在Java内存模型中,指令重排序不会影响咱们规定好的单线程执行流程,但在多线程的状况下不能预估各个线程的执行流程 为了更贴切的形容,看上面这一段代码 static int a, b, x, y; public static void main(String[] args){ long count = 0; while (true) { count++; a = 0;b = 0;x = 0;y = 0; Thread thread1 = new Thread(() -> { a = 1; x = b; }); Thread thread2 = new Thread(() -> { b = 1; y = a; }); thread1.start(); thread2.start(); try { thread1.join(); thread2.join(); } catch (Exception e) {} if (x == 0 && y == 0) { break; } } //count=118960,x=0,y=0 System.out.println("count=" + count + ",x=" + x + ",y=" + y); }初始化 a,b,x,y四个变量都是0 ...

September 6, 2023 · 3 min · jiezi

关于后端:行为型设计模式观察者发布订阅-Observer

简介也叫做公布/订阅模式,多个观察者可订阅一个主题对象,当主题状态发生变化时会告诉所有已订阅的观察者,观察者可自在解决。 角色Subject/Publisher 主题/发布者 保护已订阅的观察者 告诉已订阅的观察者 形象Subscribe 订阅者 定义订阅者接口 具体Subscribe 订阅者 实现订阅者通用接口,并实现各自逻辑 类图 代码class Subject implements \SplSubject{ public $state; private $observers; public function __construct() { $this->observers = new \SplObjectStorage(); } public function attach(\SplObserver $observer): void { echo "Subject: Attached an observer.\n"; $this->observers->attach($observer); } public function detach(\SplObserver $observer): void { $this->observers->detach($observer); echo "Subject: Detached an observer.\n"; } public function notify(): void { echo "Subject: Notifying observers...\n"; foreach ($this->observers as $observer) { $observer->update($this); } } public function someBusinessLogic(): void { echo "\nSubject: I'm doing something important.\n"; $this->state = rand(0, 10); echo "Subject: My state has just changed to: {$this->state}\n"; $this->notify(); }}class ConcreteObserverA implements \SplObserver{ public function update(\SplSubject $subject): void { if ($subject->state < 3) { echo "ConcreteObserverA: Reacted to the event.\n"; } }}class ConcreteObserverB implements \SplObserver{ public function update(\SplSubject $subject): void { if ($subject->state == 0 || $subject->state >= 2) { echo "ConcreteObserverB: Reacted to the event.\n"; } }}$subject = new Subject();$o1 = new ConcreteObserverA();$subject->attach($o1);$o2 = new ConcreteObserverB();$subject->attach($o2);$subject->someBusinessLogic();$subject->someBusinessLogic();$subject->detach($o2);$subject->someBusinessLogic();output: ...

September 6, 2023 · 2 min · jiezi

关于后端:行为型设计模式中介者-Mediator

简介通过引入一个中介者,将对象之间两两交互的情景,改为每个对象都是与中介者交互,行将网状关系改成了星状关系。毛病是中介者逻辑会很臃肿。 当零碎中呈现多对多的状况时,应该先思考设计是否正当,而尽量不要间接应用中介者。 角色形象Mediator中介者具体Mediator中介者形象Component具体Component类图中介者须要理解所有Component,而且notify中要编写解决所有可能产生的状况,Mediator是一个十分臃肿的类。 代码interface Mediator{ public function notify(object $sender, string $event): void;}class ConcreteMediator implements Mediator{ private $component1; private $component2; public function __construct(Component1 $c1, Component2 $c2) { $this->component1 = $c1; $this->component1->setMediator($this); $this->component2 = $c2; $this->component2->setMediator($this); } public function notify(object $sender, string $event): void { if ($event == "A") { echo "Mediator reacts on A and triggers following operations:\n"; $this->component2->doC(); } if ($event == "D") { echo "Mediator reacts on D and triggers following operations:\n"; $this->component1->doB(); $this->component2->doC(); } }}class BaseComponent{ protected $mediator; public function __construct(Mediator $mediator = null) { $this->mediator = $mediator; } public function setMediator(Mediator $mediator): void { $this->mediator = $mediator; }}class Component1 extends BaseComponent{ public function doA(): void { echo "Component 1 does A.\n"; $this->mediator->notify($this, "A"); } public function doB(): void { echo "Component 1 does B.\n"; $this->mediator->notify($this, "B"); }}class Component2 extends BaseComponent{ public function doC(): void { echo "Component 2 does C.\n"; $this->mediator->notify($this, "C"); } public function doD(): void { echo "Component 2 does D.\n"; $this->mediator->notify($this, "D"); }}$c1 = new Component1();$c2 = new Component2();$mediator = new ConcreteMediator($c1, $c2);echo "Client triggers operation A.\n";$c1->doA();echo "\n";echo "Client triggers operation D.\n";$c2->doD();output: ...

September 6, 2023 · 2 min · jiezi

关于后端:行为型设计模式迭代器-Iterator

简介提供一种办法程序拜访一个聚合对象中的各个元素,而又不须要裸露该对象的外部示意。 角色Iterator形象迭代器Collection形象汇合ConcreteIterator具体迭代器ConcreteCollection具体汇合类图如图,Iterator和IterableCollection定义了操作接口,ConcreteIterator实现类持有ConcreteCollection的援用,默默实现迭代的逻辑。 代码use Iterator;class AlphabeticalOrderIterator implements \Iterator{ private $collection; private $position = 0; private $reverse = false; public function __construct($collection, $reverse = false) { $this->collection = $collection; $this->reverse = $reverse; } public function rewind() { $this->position = $this->reverse ? count($this->collection->getItems()) - 1 : 0; } public function current() { return $this->collection->getItems()[$this->position]; } public function key() { return $this->position; } public function next() { $this->position = $this->position + ($this->reverse ? -1 : 1); } public function valid() { return isset($this->collection->getItems()[$this->position]); }}class WordsCollection implements \IteratorAggregate{ private $items = []; public function getItems() { return $this->items; } public function addItem($item) { $this->items[] = $item; } public function getIterator(): Iterator { return new AlphabeticalOrderIterator($this); } public function getReverseIterator(): Iterator { return new AlphabeticalOrderIterator($this, true); }}$collection = new WordsCollection();$collection->addItem("First");$collection->addItem("Second");$collection->addItem("Third");echo "Straight traversal:\n";foreach ($collection->getIterator() as $item) { echo $item . "\n";}echo "\n";echo "Reverse traversal:\n";foreach ($collection->getReverseIterator() as $item) { echo $item . "\n";}output: ...

September 6, 2023 · 1 min · jiezi

关于后端:行为型设计模式命令-Command

简介client 收回的申请,都被封装成 Command 对象,每个 Command 对象代表一种操作,Command 具体操作的是 Receiver 对象内的办法。实现动作与指标隔离和复用的目标。 角色形象 CommandReceiver 真正干活的具体 CommandInvoker 保护 commands 队列类图图中所示,client 调用 Invoker,Invoker 中保护了 commands 队列,每个 command 实际操作的是 TextEditor 这个真正的 Receiver。 代码interface Command{ public function execute(): void;}class SimpleCommand implements Command{ private $payload; public function __construct(string $payload) { $this->payload = $payload; } public function execute(): void { echo "SimpleCommand: See, I can do simple things like printing (" . $this->payload . ")\n"; }}class ComplexCommand implements Command{ private $receiver; private $a; private $b; public function __construct(Receiver $receiver, string $a, string $b) { $this->receiver = $receiver; $this->a = $a; $this->b = $b; } public function execute(): void { echo "ComplexCommand: Complex stuff should be done by a receiver object.\n"; $this->receiver->doSomething($this->a); $this->receiver->doSomethingElse($this->b); }}class Receiver{ public function doSomething(string $a): void { echo "Receiver: Working on (" . $a . ".)\n"; } public function doSomethingElse(string $b): void { echo "Receiver: Also working on (" . $b . ".)\n"; }}class Invoker{ private $onStart; private $onFinish; public function setOnStart(Command $command): void { $this->onStart = $command; } public function setOnFinish(Command $command): void { $this->onFinish = $command; } public function doSomethingImportant(): void { echo "Invoker: Does anybody want something done before I begin?\n"; if ($this->onStart instanceof Command) { $this->onStart->execute(); } echo "Invoker: ...doing something really important...\n"; echo "Invoker: Does anybody want something done after I finish?\n"; if ($this->onFinish instanceof Command) { $this->onFinish->execute(); } }}$invoker = new Invoker();$invoker->setOnStart(new SimpleCommand("Say Hi!"));$receiver = new Receiver();$invoker->setOnFinish(new ComplexCommand($receiver, "Send email", "Save report"));$invoker->doSomethingImportant();output: ...

September 6, 2023 · 2 min · jiezi

关于后端:行为型设计模式责任链-Chain-Of-Responsibility

简介使多个对象都有机会解决申请,从而防止申请的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该申请,直到有一个对象解决它为止。 角色Handler 接口 定义解决办法签名,设置nextHandler办法 Concrete Handler 具体类 实现各自handler逻辑 BaseHandler 封装一层handler,可有可无类图如图,在 client 中,将 handler 一个个串起来,每个 handler 解决完后可决定是否向后传递。 代码interface Handler{ public function setNext(Handler $handler): Handler; public function handle(string $request): string;}abstract class AbstractHandler implements Handler{ private $nextHandler; public function setNext(Handler $handler): Handler { $this->nextHandler = $handler; return $handler; } public function handle(string $request): string { if ($this->nextHandler) { return $this->nextHandler->handle($request); } return ""; }}class MonkeyHandler extends AbstractHandler{ public function handle(string $request): string { if ($request === "Banana") { return "Monkey: I'll eat the " . $request . ".\n"; } else { return parent::handle($request); } }}class SquirrelHandler extends AbstractHandler{ public function handle(string $request): string { if ($request === "Nut") { return "Squirrel: I'll eat the " . $request . ".\n"; } else { return parent::handle($request); } }}class DogHandler extends AbstractHandler{ public function handle(string $request): string { if ($request === "MeatBall") { return "Dog: I'll eat the " . $request . ".\n"; } else { return parent::handle($request); } }}function clientCode(Handler $handler){ foreach (["Nut", "Banana", "Cup of coffee"] as $food) { echo "Client: Who wants a " . $food . "?\n"; $result = $handler->handle($food); if ($result) { echo " " . $result; } else { echo " " . $food . " was left untouched.\n"; } }}$monkey = new MonkeyHandler();$squirrel = new SquirrelHandler();$dog = new DogHandler();$monkey->setNext($squirrel)->setNext($dog);echo "Chain: Monkey > Squirrel > Dog\n\n";clientCode($monkey);echo "\nSubchain: Squirrel > Dog\n\n";clientCode($squirrel);output: ...

September 6, 2023 · 2 min · jiezi

关于后端:开启数据管理新时代玖章算术获评浙江省创新型中小企业

近日,浙江省工业和信息化厅发展了 2023 第二季度创新型中小企业评估工作,经企业自评、地市审核、抽查、市经信局审核评估等程序,玖章算术以优良的自主创新能力通过认定,成为浙江省 2023 年度创新型中小企业。 "创新型中小企业"是指具备较健全的翻新机制,以技术创新为外围,造成以技术、品牌、制度、治理、文化等全面而继续的创新能力,并借此获取超额利润的中小规模企业。其中,评估工作从定性和定量两个方面评估中小企业,尤其关注其创新能力、成长性、专业化三大要害维度。评估过程严格遵循迷信办法和规范,以确保后果的准确性和可靠性。 1、技术创新,引领数据管理新时代玖章算术作为创新型中小企业,从创建开始就失去了杭州将来科技城重点关注,属于科技翻新重点反对我的项目。聚焦于云计算与数据管理根底技术畛域,领有丰盛的研发教训和业余技术团队。凭借着卓越的自主创新能力和技术实力,在数据管理畛域获得了显著成就。 在翻新方面,玖章算术打造的新一代的云原生智能数据管理平台 NineData,始终谋求卓越的产品翻新和技术冲破。2022 年玖章算术的 NineData 数据管理平台怀才不遇,取得了 IT168 &ITPUB"2022 年度翻新产品"奖。2023 年玖章算术的 NineData 智能 SQL 开发荣获“2023 可信 AI 案例生成式人工智能技术和利用优良案例”奖。此次取得认定创新型中小企业,不仅体现了玖章算术在云数据库畛域的技术实力和创新能力,同时也为公司将来的倒退提供了更多的反对和保障。 NineData 采纳了当先的云原生与 AIGC 技术,提供了 SQL 开发、数据复制、数据备份、数据比照等数据管理性能,并与企业数据源买通,构建出更智能的数据管理服务。其中,NineData SQL 开发提供了生成式人工智能的数据库开发能力,晋升 72%的 SQL 开发效率;NineData 数据复制反对数十种同异构数据源,一站式满足企业多样化的数据复制诉求;NineData 数据备份秒级 RPO 及分钟级疾速复原的当先备份能力,能够实现多环境多数据源对立备份;NineData 数据比照是云原生数据比照产品,反对同构、异构数据源之间数据一致性校验,能够达到 100 万笔记录/秒。 2、对于玖章算术玖章算术聚焦在云计算与数据管理根底技术畛域,始终保持“Make a Difference”的翻新理念,以“让每个人用好数据和云“为指标并成为云时代数据管理领导者,服务寰球 1000 万开发者,让大家都用好数据和云。 NineData 是新一代的云原生智能数据管理平台,蕴含了数据复制、SQL 开发、数据备份以及数据比照等多种性能。NineData 采纳当先的云原生与 AIGC 技术,为云与 AI 时代的架构设计提供了智能数据管理平台。作为业界首个反对跨云和本地 IDC 无缝买通的平台,可能帮忙客户轻松实现数据上云、跨云数据实时传输、ETL、数据备份、企业级智能 SQL 开发、数据库研发标准、生产变更以及敏感数据治理等性能,从而让客户的数据应用更加平安高效。

September 6, 2023 · 1 min · jiezi

关于后端:说一说Bean方法

1 前言随着SpringBoot的遍及,Spring的应用也越来越广,在某些场景下,咱们无奈通过注解或配置的模式间接获取到某个Bean。比方,在某一些工具类、设计模式实现中须要应用到Spring容器治理的Bean,此时就须要间接获取到对应的Bean。 本文为大家整顿汇总了常见的获取Bean的形式,并提供一些优劣剖析,不便大家在应用到时有更好的抉择。同时,也会为大家适当的遍及和拓展一些相干常识。 2 Spring的IoC容器在Spring中,Bean的实例化、定位、配置应用程序中的对象及建设对象间的依赖关系,都是在IoC容器中进行的。因而,要在Spring中获取Bean,实质上就是从IoC容器当中获取Bean。 在Spring中,BeanFactory是IoC容器的理论代表者,该接口提供了IoC容器最基本功能。同时,Spring还提供了另外一种类型的容器:ApplicationContext容器。 ApplicationContext容器包含BeanFactory容器的所有性能(BeanFactory的子接口),提供了更多面向利用的性能,它提供了国际化反对和框架事件体系,更易于创立理论利用。 个别状况,咱们称BeanFactory为IoC容器,称ApplicationContext为利用上下文。但有时为了不便,也将ApplicationContext称为Spring容器。 通常不倡议应用BeanFactory,但BeanFactory 依然能够用于轻量级的应用程序,如挪动设施或基于applet的应用程序,其中它的数据量和速度是显著。 2.1 BeanFactory与ApplicationContext的区别BeanFactory是Spring框架的基础设施,面向Spring自身。ApplicationContext则面向应用Spring框架的开发者,简直所有的利用场景都能够间接应用ApplicationContext,而非底层的BeanFactory。 另外,ApplicationContext的初始化和BeanFactory有一个重大的区别: BeanFactory在初始化容器时,并未实例化Bean,直到第一次拜访某个Bean时才实例指标Bean。这样,咱们就不能发现一些存在的Spring的配置问题。如果Bean的某一个属性没有注入,BeanFacotry加载后,直至第一次应用调用getBean办法才会抛出异样。 而ApplicationContext则在初始化利用上下文时就实例化所有单实例的Bean,绝对应的,ApplicationContext的初始化工夫会比BeanFactory长一些。 理解了上述的根本理论知识之后,咱们就能够尝试从IoC容器当中获取Bean对象了。 3 Bean获取形式3.1 形式一:通过BeanFactory获取通过BeanFactory来获取Bean。基于xml配置文件的时代,能够通过如下形式取得BeanFactory,再通过BeanFactory来取得对应的Bean。 BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("applicationContext.xml"));User user = (User) beanFactory.getBean("user");有肯定编程年龄的程序员,应该对此还有一些印象。这种写法预计也只会呈现在古老的我的项目当中。鉴于xml模式配置文件曾经被基于注解模式所代替,同时XmlBeanFactory也被标注为废除。此种形式不举荐应用。 其实,不举荐的理由还有一个,在下面曾经提到,尽量不要应用BeanFactory,而应该应用ApplicationContext。 3.2 形式二 :通过BeanFactoryAware获取在下面的形式中,XmlBeanFactory曾经被废除,但能够通过其余形式来取得BeanFactory,而后再从BeanFactory中取得指定的Bean。获取BeanFactory实例最简略的形式就是实现BeanFactoryAware接口。 BeanFactoryAware接口源码:public interface BeanFactoryAware extends Aware { /** * 初始化回调办法,Spring会主动将BeanFactory注入进去,接管之后即可应用BeanFactory */ void setBeanFactory(BeanFactory beanFactory) throws BeansException;}BeanFactoryAware属于org.springframework.beans.factory.Aware根标记接口,应用setter注入来在应用程序上下文启动期间获取对象。Aware接口是回调,监听器和观察者设计模式的混合,它示意Bean有资格通过回调形式被Spring容器告诉。示例如下:@Componentpublic class BeanFactoryHelper implements BeanFactoryAware { private static BeanFactory beanFactory; /** * 重写 BeanFactoryAware 接口的办法 * @param beanFactory :参数赋值给本地属性之后即可应用 BeanFactory * @throws BeansException BeansException */ @Override public void setBeanFactory(BeanFactory beanFactory) throws BeansException { BeanFactoryHelper.beanFactory = beanFactory; } /** * 依据名称获取容器中的对象实例 * @param beanName :注入的实例必须曾经存在容器中,否则抛异样:NoSuchBeanDefinitionException * @return Object */ public static Object getBean(String beanName) { return beanFactory.getBean(beanName); } /** * 依据 class 获取容器中的对象实例 * @param requiredType :被注入的必须曾经存在容器中,否则抛异样:NoSuchBeanDefinitionException * @param <T> Class * @return 对象 */ public static <T> T getBean(Class<T> requiredType) { return beanFactory.getBean(requiredType); } /** * 判断 spring 容器中是否蕴含指定名称的对象 * @param beanName bean名称 * @return 是否存在 */ public static boolean containsBean(String beanName) { return beanFactory.containsBean(beanName); } //其它需要皆可参考 BeanFactory 接口和它的实现类}

September 6, 2023 · 1 min · jiezi

关于后端:结构型设计模式代理-Proxy

简介代理与装璜器很像,都是在原有类根底上,增量做改变。 不同在于,代理模式下,client 间接操作的就是 proxy 对象,new 的就是 proxy 对象,不能够让client 间接操作被代理对象,相当于原始类被齐全暗藏掉了。 类比现实生活,租房代理是不会让客户间接跟房东分割的,客户签合同也是跟代理签,全程没有跟房东交互。 角色根底性能接口 Subject 定义根本动作 被代理类 实现 Subject 接口,实现业务逻辑 Proxy 代理类 实现 Subject接口 类图图中ServiceInterface是根底接口,定义一个operation办法。Service是被代理类,实现了ServiceInterface接口,Proxy是代理类,也实现了ServiceInterface接口。 Proxy类的operation办法做了CheckAccess操作,容许的话再调用被代理类的operation办法。 代码interface Subject{ public function request(): void;}class RealSubject implements Subject{ public function request(): void { echo "RealSubject: Handling request.\n"; }}class Proxy implements Subject{ private $realSubject; public function __construct(RealSubject $realSubject) { $this->realSubject = $realSubject; } public function request(): void { if ($this->checkAccess()) { $this->realSubject->request(); $this->logAccess(); } } private function checkAccess(): bool { echo "Proxy: Checking access prior to firing a real request.\n"; return true; } private function logAccess(): void { echo "Proxy: Logging the time of request.\n"; }}function clientCode(Subject $subject){ $subject->request();}echo "Client: Executing the client code with a real subject:\n";$realSubject = new RealSubject();clientCode($realSubject);echo "\n";echo "Client: Executing the same client code with a proxy:\n";$proxy = new Proxy($realSubject);clientCode($proxy);output: ...

September 6, 2023 · 1 min · jiezi

关于后端:结构型设计模式享元缓存Flyweight

简介享元模式更常见的叫法是缓存或 cache,一个对象只创立一次,之后始终复用这一对象。 跟单例不同在于,单例是全局只有惟一一个对象,所有人一起用同一个对象,且该对象是提前预设好的,不能定制。 而享元则能够依据参数不同创立出不同的实例,不过实例一旦创立就只保留一份,之后再次创立雷同参数的实例则返回该对象,供所有援用的中央应用,援用方之间共享同一份享元实例的数据。 过程有点像定制化的单例模式。 角色Flyweight 享元类 定制化的业务实体,依据不同须要可能定制不同的享元类,但一旦创立出一个享元类,当前都复用这一个类 FlyweightFactory 享元工厂类 用来创立和缓存享元实体的中央 类图 代码class Flyweight{ private $sharedState; public function __construct($sharedState) { $this->sharedState = $sharedState; } public function operation($uniqueState): void { $s = json_encode($this->sharedState); $u = json_encode($uniqueState); echo "Flyweight: Displaying shared ($s) and unique ($u) state.\n"; }}class FlyweightFactory{ private $flyweights = []; public function __construct(array $initialFlyweights) { foreach ($initialFlyweights as $state) { $this->flyweights[$this->getKey($state)] = new Flyweight($state); } } private function getKey(array $state): string { ksort($state); return implode("_", $state); } public function getFlyweight(array $sharedState): Flyweight { $key = $this->getKey($sharedState); if (!isset($this->flyweights[$key])) { echo "FlyweightFactory: Can't find a flyweight, creating new one.\n"; $this->flyweights[$key] = new Flyweight($sharedState); } else { echo "FlyweightFactory: Reusing existing flyweight.\n"; } return $this->flyweights[$key]; } public function listFlyweights(): void { $count = count($this->flyweights); echo "\nFlyweightFactory: I have $count flyweights:\n"; foreach ($this->flyweights as $key => $flyweight) { echo $key . "\n"; } }}$factory = new FlyweightFactory([ ["Chevrolet", "Camaro2018", "pink"], ["Mercedes Benz", "C300", "black"], ["Mercedes Benz", "C500", "red"], ["BMW", "M5", "red"], ["BMW", "X6", "white"],]);$factory->listFlyweights();function addCarToPoliceDatabase( FlyweightFactory $ff, $plates, $owner, $brand, $model, $color) { echo "\nClient: Adding a car to database.\n"; $flyweight = $ff->getFlyweight([$brand, $model, $color]); $flyweight->operation([$plates, $owner]);}addCarToPoliceDatabase($factory, "CL234IR", "James Doe", "BMW", "M5", "red");addCarToPoliceDatabase($factory, "CL234IR", "James Doe", "BMW", "X1", "red");$factory->listFlyweights();output: ...

September 6, 2023 · 2 min · jiezi

关于后端:结构型设计模式外观-Facade

简介外观模式特点是屏蔽后端简单的实现逻辑,将其整合成简略的一个或几个接口提供进来,client 只需与 Facade 层提供的简略接口交互即可。 例如银行办业务,前面波及到很多财务细节,但用户面对的就是一个窗口业务员。 角色Facade 外观层Subsystem 负责具体事务的子系统们类图 代码class Facade{ protected $subsystem1; protected $subsystem2; public function __construct( Subsystem1 $subsystem1 = null, Subsystem2 $subsystem2 = null ) { $this->subsystem1 = $subsystem1 ?: new Subsystem1(); $this->subsystem2 = $subsystem2 ?: new Subsystem2(); } public function operation(): string { $result = "Facade initializes subsystems:\n"; $result .= $this->subsystem1->operation1(); $result .= $this->subsystem2->operation1(); $result .= "Facade orders subsystems to perform the action:\n"; $result .= $this->subsystem1->operationN(); $result .= $this->subsystem2->operationZ(); return $result; }}class Subsystem1{ public function operation1(): string { return "Subsystem1: Ready!\n"; } public function operationN(): string { return "Subsystem1: Go!\n"; }}class Subsystem2{ public function operation1(): string { return "Subsystem2: Get ready!\n"; } public function operationZ(): string { return "Subsystem2: Fire!\n"; }}function clientCode(Facade $facade){ echo $facade->operation();}$subsystem1 = new Subsystem1();$subsystem2 = new Subsystem2();$facade = new Facade($subsystem1, $subsystem2);clientCode($facade);output: ...

September 6, 2023 · 1 min · jiezi

关于后端:结构型设计模式装饰器-Decorator

简介装璜器模式能够在指标对象原有的根底上,增加其余性能,实现动静加强。 须要明确的是代理模式也有相似的作用,而装璜器模式与代理模式最大的不同在于,装璜器模式下,对指标对象设置加强的权力交给了 client,即 client 先要失去指标对象,之后决定要用哪些装璜器给指标对象加强,一层层嵌套。 具体来说比方 Java 的 IO 操作,个别须要先 new 一个指标对象 FileInputStream,之后将其作为参数传给 BufferedInputStream 即可实现有 buffer 加强性能 InputStream。 装璜器类和被装璜类应该实现同一接口,这样能够保障被装璜器加强后的类的调用形式与之前始终,且反对有限次装璜调用。 装璜器是典型的组合优于继承的例子,试想如果用继承来实现加强的话,每有一个加强项,都须要重写一个类,而反对多种加强项的类则须要继承屡次。 角色Component 接口 定义根本的操作 Decorator 装璜器 实现 Component 接口,加强代码所在 Wrappee/Concrete Component 被装璜的原始类 实现 Component 接口,是被装璜加强的原始类 类图图中所示,Component 是共有的接口,Concrete Component 是被装璜的类,Concrete Decorators 装璜器类。装璜器类接管 Component 为参数,execute 办法即加强办法。 代码interface Component{ public function operation(): string;}class ConcreteComponent implements Component{ public function operation(): string { return "ConcreteComponent"; }}class Decorator implements Component{ protected $component; public function __construct(Component $component) { $this->component = $component; } public function operation(): string { return $this->component->operation(); }}class ConcreteDecoratorA extends Decorator{ public function operation(): string { return "ConcreteDecoratorA(" . parent::operation() . ")"; }}class ConcreteDecoratorB extends Decorator{ public function operation(): string { return "ConcreteDecoratorB(" . parent::operation() . ")"; }}function clientCode(Component $component){ echo "RESULT: " . $component->operation() . "\n";}$simple = new ConcreteComponent();echo "Client: I've got a simple component:\n";clientCode($simple);echo "\n";$decorator1 = new ConcreteDecoratorA($simple);$decorator2 = new ConcreteDecoratorB($decorator1);echo "Client: Now I've got a decorated component:\n";clientCode($decorator2);output: ...

September 6, 2023 · 1 min · jiezi

关于后端:结构型设计模式组合对象树-Composite

简介组合模式又叫对象树,将对象依照树形构造串起来,呈现出部分和整体雷同的个性。 树中每个节点都由两局部组成,首先节点有本人的业务数据,其次节点内能够含有子节点汇合。 比方盒子中能够放物品,也能够放其余小盒子,小盒子里又能够放物品和其余更小的盒子。 当计算盒子的物品价格时,只须要将盒子里自身的物品价格,加上小盒子里所有物品价格即可,递归解决。 角色形象节点 Component 定义一个节点的根底办法,如外部增加子节点等 具体节点之叶子节点 Leaf 叶子节点没有子节点 具体节点之非叶子节点 Composite/Container 非叶子节点,可增加子节点 或者也能够不辨别是否是叶子节点,都视为节点即可 类图图中显示,Leaf 和 Composite 都实现 Component 接口。 Composite 可增加或删除子节点,execute 则指派调用子节点的 execute 办法。 Leaf 的 execute 是真正执行逻辑的中央 代码<?phpabstract class Component{ protected $parent; public function setParent(Component $parent) { $this->parent = $parent; } public function getParent(): Component { return $this->parent; } public function add(Component $component): void { } public function remove(Component $component): void { } public function isComposite(): bool { return false; } abstract public function operation(): string;}class Leaf extends Component{ public function operation(): string { return "Leaf"; }}class Composite extends Component{ protected $children; public function __construct() { $this->children = new \SplObjectStorage(); } public function add(Component $component): void { $this->children->attach($component); $component->setParent($this); } public function remove(Component $component): void { $this->children->detach($component); $component->setParent(null); } public function isComposite(): bool { return true; } public function operation(): string { $results = []; foreach ($this->children as $child) { $results[] = $child->operation(); } return "Branch(" . implode("+", $results) . ")"; }}function clientCode(Component $component){ echo "RESULT: " . $component->operation();}// 只有一个叶子节点$simple = new Leaf();echo "Client: I've got a simple component:\n";clientCode($simple);echo "\n";// 构建一个tree$tree = new Composite();$branch1 = new Composite();$branch1->add(new Leaf());$branch1->add(new Leaf());$branch2 = new Composite();$branch2->add(new Leaf());$tree->add($branch1);$tree->add($branch2);echo "Client: Now I've got a composite tree:\n";clientCode($tree);// 合并两个treefunction clientCode2(Component $component1, Component $component2){ if ($component1->isComposite()) { $component1->add($component2); } echo "RESULT: " . $component1->operation();}echo "\n";echo "Client: I don't need to check the components classes even when managing the tree:\n";clientCode2($tree, $simple);output: ...

September 6, 2023 · 2 min · jiezi

关于后端:结构型设计模式桥接模块化-Bridge

简介桥接模式可将一系列严密相干的、程度等级的类,转变为组合关系,造成垂直等级关系。 如抽象类 Color、Shape,别离有 RedColor、BlueColor、CircleShape、SquareShape 的实现类,那么想创立红色方形,则能够将 Shape 类中持有 Color 援用,动静向 Shape 中注入 Color 实现即可。 否则别离实现 RedCircleShape、RedSquareShape、BlueCircleShape、BlueCircleShape 的话,如果再新增一个维度,实现类则须要批改,并新增很多实例。 桥接更间接的说就是组件化,模块化,让 A 中持有 B 的援用,B 能够随便调换,造成不同组合。 角色形象实体 A A 中蕴含实体 B 的援用 A 的具体实现形象实体 BB 的具体实现类图图中的 Remote 和 Device 两头,就是桥接。Remote 外部持有一个 Device 的援用:device。通过 set 不同的 device,实现 Remote 与 Device 的不同组合。 代码class Abstraction{ protected $implementation; public function __construct(Implementation $implementation) { $this->implementation = $implementation; } public function operation(): string { return "Abstraction: Base operation with:\n" . $this->implementation->operationImplementation(); }}class ExtendedAbstraction extends Abstraction{ public function operation(): string { return "ExtendedAbstraction: Extended operation with:\n" . $this->implementation->operationImplementation(); }}interface Implementation{ public function operationImplementation(): string;}class ConcreteImplementationA implements Implementation{ public function operationImplementation(): string { return "ConcreteImplementationA: Here's the result on the platform A.\n"; }}class ConcreteImplementationB implements Implementation{ public function operationImplementation(): string { return "ConcreteImplementationB: Here's the result on the platform B.\n"; }}function clientCode(Abstraction $abstraction){ echo $abstraction->operation();}$implementation = new ConcreteImplementationA();$abstraction = new Abstraction($implementation);clientCode($abstraction);$implementation = new ConcreteImplementationB();$abstraction = new ExtendedAbstraction($implementation);clientCode($abstraction);output: ...

September 6, 2023 · 1 min · jiezi

关于后端:结构型设计模式适配器-Adapter

结构型设计模式-适配器 Adapterdate: April 13, 2021slug: design-pattern-adapterstatus: Publishedtags: 设计模式type: Page 简介适配器模式是一种结构型设计模式, 它能使接口不兼容的对象可能相互合作 角色Client 接口 / Target 指标接口 用户应用的接口 Adaptee 被适配的对象,原有办法不能间接给 client 应用 Adapter 适配器,实现 Target 接口,将 Adaptee 的办法革新成兼容 client 的模式,供 client应用 类图图示,Adapter 持有 Service 对象实例,method 办法实现自 Client Interface,使 client 能够调用,method 外部逻辑则将 client 的入参转换后交给 service 解决 代码class Target{ public function request(): string { return "Target: The default target's behavior."; }}class Adaptee{ public function specificRequest(): string { return ".eetpadA eht fo roivaheb laicepS"; }}class Adapter extends Target{ private $adaptee; public function __construct(Adaptee $adaptee) { $this->adaptee = $adaptee; } public function request(): string { return "Adapter: (TRANSLATED) " . strrev($this->adaptee->specificRequest()); }}function clientCode(Target $target){ echo $target->request();}echo "Client: I can work just fine with the Target objects:\n";$target = new Target();clientCode($target);$adaptee = new Adaptee();echo "Client: The Adaptee class has a weird interface. See, I don't understand it:\n";echo "Adaptee: " . $adaptee->specificRequest();echo "Client: But I can work with it via the Adapter:\n";$adapter = new Adapter($adaptee);clientCode($adapter);output: ...

September 6, 2023 · 1 min · jiezi

关于后端:互联网公司裁员的预兆和手段

大家好,我是煎鱼。 明天是来自匿名同学小E 的受权投稿。 前段时间分享了互联网大厂裁员的起因和预兆,外面蕴含了许多互联网公司的裁员起因剖析和预兆。 有许多同学反馈,规模不同的公司,有一些更经典的预兆和步骤,对于大家来说更普适。心愿能对大家有所帮忙。 背地目标对于一家企业而言,裁员的目标,大部分都比拟单纯,就是:升高经营老本。 单针对某条业务线,背地的起因不外乎: 公司(也可能是业务线)曾经进入长期亏损情况,高管们认为通过市场无奈短时间扭亏。最快的方法就是升高收入。大佬们认为投入的老本无奈产生更多的收益(前文提到的市梦率),看不到将来,空想开始幻灭。再投入只会持续扩充亏损。基于上述目标(不限于,但大多是钱的问题),从员工角度来看,公司就会开始呈现一些奇奇怪怪的骚操作了。 裁员预兆小试牛刀:省钱加班在最早的初期来讲,个别是不会马上开始裁员的,会想想其余路子。 大佬们会想着进步大家的工作效率和缩减福利开销,看看能不能挤挤,有没有新心愿。 转到打工人侧,初中期常看到的步骤是: 抓考勤:如果早上上班时间比拟灵便,主打一个宽松感。那么大佬们为了提效,会要求 9 点或 9 点 30 要到。不再像以前那样,会进行收紧,不会再有过于活自在的工夫点。多加班:会有领导层认为只有员工多加班,公司就能失去更多的好处。例如:进步交付效率。因而会扭转工作时长,暗地里要求 9105,9106 等时长的执行。砍开销:加班餐、下午茶等经费缩减或间接勾销。食堂管制每个人能够拿的重量等。这对于大佬们都是实打实的银子。(也会抓一些不合规的行为)卡福利:严格意义来讲,这属于砍开销的一部分。但这对于咱们打工人而言,感触也比拟深。因而独自拎进去。常见的操作,像是推延加班餐达到工夫、推延加班容许打车工夫、节假日的礼品调整等。加制度:为了上述动作合规,时常会有加制度的行为。例如抓考勤,有的公司就会要求上下班要打卡,加到规章制度中,确保不会被人抓到破绽。当然。到中后期后。大部分措施曾经落地,米已成炊了,发现这些措施对公司盈利其实没有特地大的作用。 并不会说什么你做了这次,公司业务的业绩就蹭蹭蹭涨了。前面大家也就间接略过这种提效降本的步骤。 大刀阔斧:减人合并在发现无论如何降本、提效(加班)都无奈进步公司业绩的利润后,真正的裁员步骤开始了。 罕用的步骤如下: 部门人员盘点:在正式入手前,中层及以上治理岗还有人力部门,会有密集的盘点行为。这是一个哨声。间接缩减 HC:在公司通过盘点测算后,在裁员的晚期,会下发给每个部门 HC,要求间接增员。这是最根底的裁员。合并业务后裁员:在通过多轮的切香肠式裁员后,会发现一个问题:切不动了。这种时候,就会用 “高阶” 方法,将原有的业务再进行切割和划分,用看起来多给了几个人的 HC,让既有部门负责更多的业务。再进行增员。整条业务线裁员:这个比拟常呈现在大厂,这个业务的梦想破灭了。从总监、基层治理、研发都会被增员。能够认为是第二点的加强版。个别企业中会分为老本核心和利润核心,对于程序员们最相熟的就是 “老本核心” 了。纯正的技术部门,例如:工具、架构、数据、中台等部门,如果没有产生理论的客户业绩增收,都被归属为老本核心。 许多公司裁员会先动老本核心的相干部门,如果你曾经发现了蹊跷,就能够找这些部门的同学理解一下当前情况,就能晓得是不是真的了。 集体应答措施一言半语,多说无益。次要以下几点: 多存些钱,留好备用金。应答被裁员后的相当一段时间的经济收入。多卷八股文和算法等,以备突发面试,保障本人常在面试状态。多居安思危,要考量在公司本人的技术能失去什么。多理解公司现状和将来倒退预期,看好危险,做好心里预期。多看看多渠道支出倒退,看看能不能有 ABZ 打算。有就是最好的。少背些负债,像房贷、月供等,要不自量力。不要一崩就全崩了。总结目前的行业状况和场面,须要大家放弃好本人的外围竞争力。身边有许多的敌人都有过被裁员或被动到职。大多数最初还是能找到工作,又或是降薪才找到的。 心愿以上内容可能给大家带来一些察看细节和日常警醒,公司裁员个别还是有迹可循的。提前做好肯定的筹备,对本人和家庭都是十分重要的。 文章继续更新,能够微信搜【脑子进煎鱼了】浏览,本文 GitHub github.com/eddycjy/blog 已收录,学习 Go 语言能够看 Go 学习地图和路线,欢送 Star 催更。Go 图书系列Go 语言入门系列:初探 Go 我的项目实战Go 语言编程之旅:深刻用 Go 做我的项目Go 语言设计哲学:理解 Go 的为什么和设计思考Go 语言进阶之旅:进一步深刻 Go 源码举荐浏览又有新性能!Go 将有生成新模板的 gonew 工具链Go1.21 那些事:泛型库、for 语义变更、对立 log/slog、WASI 等新个性,你晓得多少?互联网大厂裁员的起因和预兆

September 6, 2023 · 1 min · jiezi

关于后端:服务优化发现问题解决报警提高稳定性

作为一名程序员,咱们不能只关注代码的实现和上线,而漠视了线上环境的运行和优化。 近期遇到了两个线上服务的问题,一个后端利用和一个前端我的项目,它们存在一些 bug 和历史遗留问题。为了不影响用户的应用体验,决定对它们进行一次优化。 后端服务这个后端服务是年初的时候有共事到职了,交到了我这里,没接手的时候不晓得,没想到接手后,到处都是问题,天天各种报警,基本上隔三差五就要重启。 尽管一开始的时候晓得这个服务不是很稳固,日常会有一些队列音讯沉积,然而不在本人手上,不晓得问题会这么多,动不动就沉积上亿条音讯,天天慢 SQL 和高负载报警。 平时工作日的时候收到报警不是很在意,棘手重启一下就算了,然而当每次周末或者出门在外的时候,收到报警心里还是蛮荒的。 抱着做一个问题的终结者的想法,最初还是筹备花工夫把这个服务做一下手术,从根本上解决问题。 成果先说一下成果,这个服务从优化过后,基本上除了迭代就再也没有须要重新启动过,更不存在隔三差五的重启,当初每天的报警量从之前的一天几百条变为 0,队列无任何沉积。 优化过程优化的过程中最难的是发现问题,只有能精准的找到问题所在,解决起来还是很容易的。 优化次要分两步:1. 解决慢 SQL;2. 解决沉积报警; 慢 SQL解决慢 SQL 的思路很简略,依据慢 SQL 日志,找到对应的慢 SQL 进行优化即可。优化能够从两个方向来进行,一种是基于 SQL 自身来进行优化,另一种是能够通过缓存来解决。这里须要依据具体的业务来抉择,如果不是常常变动的数据,则能够通过减少缓存来解决,刚好我这里就能够满足。 通过剖析能够通过减少 Redis 缓存来解决这个问题,所以通过引入的 Redis 解决了慢 SQL 问题。 音讯沉积队列音讯沉积的解决形式无非也就是两种,缩小数据量,放慢处理速度。 音讯队列外面的音讯因为是上游发过来的,没方法从发送方进行缩小,不过剖析了一下音讯类型,发现有很多音讯的类型是齐全不须要关怀的,所以第一步减少音讯过滤,将无用的音讯间接提交掉。 另外之前遇到音讯沉积的时候,察看到生产音讯的 TPS 特地低,有时候只有个位数,齐全不失常,而且每次重启过后 TPS 能够达到几千的级别,并且每次沉积的时候在日志层面都有一些“断开连接” 的谬误。 所以从日志层面剖析,必定是生产线程出了问题,导致生产能力降落从而沉积,从而问题就转变为为什么线程会出现异常。 认真查了下利用层面的监控,发现利用有频繁的 FullGC 产生,奇怪的是为什么频繁 FullGc 却没有触发报警呢?看了一眼几乎要吐血,因为 FullGc 的报警开关被关了。。。 至此基本上能晓得问题的起因了,因为产生了 FullGc 导致 STW,而后生产线程挂了,导致音讯沉积,重启后内存开释从新进行生产。接下来的问题就转变为排查 FullGc 的起因了。 排查 FullGc 的根本流程首先必定是 dump 一下内存的 heap ,而后剖析一下内存泄露的代码块。通过 dump 下来的日志,发现在代码中应用 ThreadLocal,然而没有开释,从而导致频次的 FullGc。问题到这基本上也解决了,批改了相干的中央,从新上线,稳固运行。 至此没有沉积,没有报警,没有重启,爽歪歪! 总结敬畏线上,不要放过任何一个线上的异样和报警! ...

September 6, 2023 · 3 min · jiezi

关于后端:创建型设计模式单例-Singleton

简介全局共用一个对象,益处是对象只实例化一次,缩小资源占用 角色单例类 返回本类的惟一一个实例 代码class Singleton{ private static $instances = []; protected function __construct() { } protected function __clone() { } public function __wakeup() { throw new \Exception("Cannot unserialize a singleton."); } public static function getInstance(): Singleton { $cls = static::class; if (!isset(self::$instances[$cls])) { self::$instances[$cls] = new static(); } return self::$instances[$cls]; } public function someBusinessLogic() { // ... }}function clientCode(){ $s1 = Singleton::getInstance(); $s2 = Singleton::getInstance(); if ($s1 === $s2) { echo "Singleton works, both variables contain the same instance."; } else { echo "Singleton failed, variables contain different instances."; }}clientCode();output: ...

September 6, 2023 · 1 min · jiezi

关于后端:创建型设计模式原型-Prototype

简介原型模式反对依照一个对象为模板,创立出另一个截然不同的对象。 简略说就是把 A 对象的属性,都赋值到 B 上,留神必须是深拷贝,即 clone 后的 AB 关联的对象是不同的对象。 角色形象原型类 定义 clone 办法 具体实现类 实现 clone 办法 类图 代码class Prototype{ public $primitive; public $component; public $circularReference; public function __clone() { $this->component = clone $this->component; $this->circularReference = clone $this->circularReference; $this->circularReference->prototype = $this; }}class ComponentWithBackReference{ public $prototype; public function __construct(Prototype $prototype) { $this->prototype = $prototype; }}function clientCode(){ $p1 = new Prototype(); $p1->primitive = 245; $p1->component = new \DateTime(); $p1->circularReference = new ComponentWithBackReference($p1); $p2 = clone $p1; if ($p1->primitive === $p2->primitive) { echo "Primitive field values have been carried over to a clone. Yay!\n"; } else { echo "Primitive field values have not been copied. Booo!\n"; } if ($p1->component === $p2->component) { echo "Simple component has not been cloned. Booo!\n"; } else { echo "Simple component has been cloned. Yay!\n"; } if ($p1->circularReference === $p2->circularReference) { echo "Component with back reference has not been cloned. Booo!\n"; } else { echo "Component with back reference has been cloned. Yay!\n"; } if ($p1->circularReference->prototype === $p2->circularReference->prototype) { echo "Component with back reference is linked to original object. Booo!\n"; } else { echo "Component with back reference is linked to the clone. Yay!\n"; }}clientCode();output: ...

September 6, 2023 · 2 min · jiezi

关于后端:quarkus依赖注入之三用注解选择注入bean

欢送拜访我的GitHub这里分类和汇总了欣宸的全副原创(含配套源码):https://github.com/zq2599/blog_demos本篇概览本文是《quarkus依赖注入》系列的第三篇,前文咱们把握了创立bean的几种形式,本篇趁热打铁,学习一个与创立bean无关的重要知识点:一个接口如果有多个实现类时,bean实例应该如何抉择其中的一个呢?能够用注解来设定bean的抉择逻辑如果您相熟spring,此刻应该会想到ConditionalXXX注解,上面的代码来自spring官网,注解ConditionalOnProperty的作用是依据配置信息来管制bean是否实例化,本篇咱们要把握的是quarkus框架下的相似管制逻辑 @Service@ConditionalOnProperty(value="logging.enabled", havingValue = "true", matchIfMissing = true)class LoggingService { // ...}本篇次要是通过实例学习以下五个注解的用法LookupIfProperty,配置项的值符合要求能力应用beanLookupUnlessProperty,配置项的值不符合要求能力应用beanIfBuildProfile,如果是指定的profile能力应用beanUnlessBuildProfile,如果不是指定的profile能力应用beanIfBuildProperty,如果构建属性匹配能力应用bean源码下载本篇实战的残缺源码可在GitHub下载到,地址和链接信息如下表所示(https://github.com/zq2599/blog_demos)名称链接备注我的项目主页https://github.com/zq2599/blog_demos该我的项目在GitHub上的主页git仓库地址(https)https://github.com/zq2599/blog_demos.git该我的项目源码的仓库地址,https协定git仓库地址(ssh)git@github.com:zq2599/blog_demos.git该我的项目源码的仓库地址,ssh协定这个git我的项目中有多个文件夹,本次实战的源码在<font color="blue">quarkus-tutorials</font>文件夹下,如下图红框<img src="https://typora-pictures-1253575040.cos.ap-guangzhou.myqcloud.com/image-20220312091203116.png" alt="image-20220312091203116" style="zoom: 80%;" /><font color="blue">quarkus-tutorials</font>是个父工程,外面有多个module,本篇实战的module是<font color="red">basic-di</font>,如下图红框<img src="https://typora-pictures-1253575040.cos.ap-guangzhou.myqcloud.com/image-20220312091404031.png" alt="image-20220312091404031" style="zoom:80%;" />LookupIfProperty,配置项的值符合要求能力应用bean注解<font color="blue">LookupIfProperty</font>的作用是查看指定配置项,如果存在且符合要求,能力通过代码获取到此bean,有个关键点请留神:下图是官网定义,可见LookupIfProperty并没有决定是否实例化beam,它决定的是是否通过代码取到bean,这个代码就是Instance\<T>来注入,并且用Instance.get办法来获取 定义一个接口TryLookupIfProperty.javapublic interface TryLookupIfProperty { String hello();}以及两个实现类,第一个是TryLookupIfPropertyAlpha.javapublic class TryLookupIfPropertyAlpha implements TryLookupIfProperty { @Override public String hello() { return "from " + this.getClass().getSimpleName(); }}第二个TryLookupIfPropertyBeta.javapublic class TryLookupIfPropertyBeta implements TryLookupIfProperty { @Override public String hello() { return "from " + this.getClass().getSimpleName(); }}而后就是注解<font color="blue">LookupIfProperty</font>的用法了,如下所示,SelectBeanConfiguration是个配置类,外面有两个办法用来生产bean,都用注解LookupIfProperty润饰,如果配置项<font color="blue">service.alpha.enabled</font>的值等于<font color="red">true</font>,就会执行<font color="blue">tryLookupIfPropertyAlpah</font>办法,如果配置项<font color="blue">service.beta.enabled</font>的值等于<font color="red">true</font>,就会执行<font color="blue">tryLookupIfPropertyBeta</font>办法package com.bolingcavalry.config;import com.bolingcavalry.service.TryLookupIfProperty;import com.bolingcavalry.service.impl.TryLookupIfPropertyAlpha;import com.bolingcavalry.service.impl.TryLookupIfPropertyBeta;import io.quarkus.arc.lookup.LookupIfProperty;import javax.enterprise.context.ApplicationScoped;public class SelectBeanConfiguration { @LookupIfProperty(name = "service.alpha.enabled", stringValue = "true") @ApplicationScoped public TryLookupIfProperty tryLookupIfPropertyAlpha() { return new TryLookupIfPropertyAlpha(); } @LookupIfProperty(name = "service.beta.enabled", stringValue = "true") @ApplicationScoped public TryLookupIfProperty tryLookupIfPropertyBeta() { return new TryLookupIfPropertyBeta(); }}而后来验证注解<font color="blue">LookupIfProperty</font>是否失效,上面是单元测试代码,有两处须要留神的中央,稍后会提到package com.bolingcavalry;import com.bolingcavalry.service.TryLookupIfProperty;import com.bolingcavalry.service.impl.TryLookupIfPropertyAlpha;import io.quarkus.test.junit.QuarkusTest;import org.junit.jupiter.api.Assertions;import org.junit.jupiter.api.BeforeAll;import org.junit.jupiter.api.Test;import javax.enterprise.inject.Instance;import javax.inject.Inject;@QuarkusTestpublic class BeanInstanceSwitchTest { @BeforeAll public static void setUp() { System.setProperty("service.alpha.enabled", "true"); } // 留神,后面的LookupIfProperty不能决定注入bean是否实力话,只能决定Instance.get是否能取到, //所以此处要注入的是Instance,而不是TryLookupIfProperty自身 @Inject Instance<TryLookupIfProperty> service; @Test public void testTryLookupIfProperty() { Assertions.assertEquals("from " + tryLookupIfPropertyAlpha.class.getSimpleName(), service.get().hello()); }}上述代码有以下两点要留神<font color="red">留神TryLookupIfProperty的注入形式</font>,对这种运行时能力确定具体实现类的bean,要用Instance的形式注入,应用时要用Instance.get办法获得bean单元测试的BeforeAll注解用于指定测试前要做的事件,这里用System.setProperty设置配置项<font color="blue">service.alpha.enabled</font>,所以,实践上SelectBeanConfiguration.tryLookupIfPropertyAlpha办法应该会执行,也就是说注入的TryLookupIfProperty应该是<font color="blue">TryLookupIfPropertyAlpha</font>实例,所以testTryLookupIfProperty中用assertEquals断言预测:TryLookupIfProperty.hello的值来自TryLookupIfPropertyAlpha执行单元测试,如下图,合乎预期 ...

September 6, 2023 · 2 min · jiezi

关于后端:Spring的IoC容器

1 前言随着SpringBoot的遍及,Spring的应用也越来越广,在某些场景下,咱们无奈通过注解或配置的模式间接获取到某个Bean。比方,在某一些工具类、设计模式实现中须要应用到Spring容器治理的Bean,此时就须要间接获取到对应的Bean。 本文为大家整顿汇总了常见的获取Bean的形式,并提供一些优劣剖析,不便大家在应用到时有更好的抉择。同时,也会为大家适当的遍及和拓展一些相干常识。 2 Spring的IoC容器在Spring中,Bean的实例化、定位、配置应用程序中的对象及建设对象间的依赖关系,都是在IoC容器中进行的。因而,要在Spring中获取Bean,实质上就是从IoC容器当中获取Bean。 在Spring中,BeanFactory是IoC容器的理论代表者,该接口提供了IoC容器最基本功能。同时,Spring还提供了另外一种类型的容器:ApplicationContext容器。 ApplicationContext容器包含BeanFactory容器的所有性能(BeanFactory的子接口),提供了更多面向利用的性能,它提供了国际化反对和框架事件体系,更易于创立理论利用。 个别状况,咱们称BeanFactory为IoC容器,称ApplicationContext为利用上下文。但有时为了不便,也将ApplicationContext称为Spring容器。 通常不倡议应用BeanFactory,但BeanFactory 依然能够用于轻量级的应用程序,如挪动设施或基于applet的应用程序,其中它的数据量和速度是显著。 2.1 BeanFactory与ApplicationContext的区别BeanFactory是Spring框架的基础设施,面向Spring自身。ApplicationContext则面向应用Spring框架的开发者,简直所有的利用场景都能够间接应用ApplicationContext,而非底层的BeanFactory。 另外,ApplicationContext的初始化和BeanFactory有一个重大的区别: BeanFactory在初始化容器时,并未实例化Bean,直到第一次拜访某个Bean时才实例指标Bean。这样,咱们就不能发现一些存在的Spring的配置问题。如果Bean的某一个属性没有注入,BeanFacotry加载后,直至第一次应用调用getBean办法才会抛出异样。 而ApplicationContext则在初始化利用上下文时就实例化所有单实例的Bean,绝对应的,ApplicationContext的初始化工夫会比BeanFactory长一些。 理解了上述的根本理论知识之后,咱们就能够尝试从IoC容器当中获取Bean对象了。 3 Bean获取形式3.1 形式一:通过BeanFactory获取通过BeanFactory来获取Bean。基于xml配置文件的时代,能够通过如下形式取得BeanFactory,再通过BeanFactory来取得对应的Bean。 BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("applicationContext.xml"));User user = (User) beanFactory.getBean("user");有肯定编程年龄的程序员,应该对此还有一些印象。这种写法预计也只会呈现在古老的我的项目当中。鉴于xml模式配置文件曾经被基于注解模式所代替,同时XmlBeanFactory也被标注为废除。此种形式不举荐应用。 其实,不举荐的理由还有一个,在下面曾经提到,尽量不要应用BeanFactory,而应该应用ApplicationContext。 3.2 形式二 :通过BeanFactoryAware获取在下面的形式中,XmlBeanFactory曾经被废除,但能够通过其余形式来取得BeanFactory,而后再从BeanFactory中取得指定的Bean。获取BeanFactory实例最简略的形式就是实现BeanFactoryAware接口。 BeanFactoryAware接口源码:public interface BeanFactoryAware extends Aware { /** * 初始化回调办法,Spring会主动将BeanFactory注入进去,接管之后即可应用BeanFactory */ void setBeanFactory(BeanFactory beanFactory) throws BeansException;}BeanFactoryAware属于org.springframework.beans.factory.Aware根标记接口,应用setter注入来在应用程序上下文启动期间获取对象。Aware接口是回调,监听器和观察者设计模式的混合,它示意Bean有资格通过回调形式被Spring容器告诉。示例如下:@Componentpublic class BeanFactoryHelper implements BeanFactoryAware { private static BeanFactory beanFactory; /** * 重写 BeanFactoryAware 接口的办法 * @param beanFactory :参数赋值给本地属性之后即可应用 BeanFactory * @throws BeansException BeansException */ @Override public void setBeanFactory(BeanFactory beanFactory) throws BeansException { BeanFactoryHelper.beanFactory = beanFactory; } /** * 依据名称获取容器中的对象实例 * @param beanName :注入的实例必须曾经存在容器中,否则抛异样:NoSuchBeanDefinitionException * @return Object */ public static Object getBean(String beanName) { return beanFactory.getBean(beanName); } /** * 依据 class 获取容器中的对象实例 * @param requiredType :被注入的必须曾经存在容器中,否则抛异样:NoSuchBeanDefinitionException * @param <T> Class * @return 对象 */ public static <T> T getBean(Class<T> requiredType) { return beanFactory.getBean(requiredType); } /** * 判断 spring 容器中是否蕴含指定名称的对象 * @param beanName bean名称 * @return 是否存在 */ public static boolean containsBean(String beanName) { return beanFactory.containsBean(beanName); } //其它需要皆可参考 BeanFactory 接口和它的实现类}

September 6, 2023 · 1 min · jiezi

关于后端:Semaphore带权重的信号量

<font color="#CD853F">初入门径</font> Java中有Semaphore类,用来限度拜访特定资源的并发线程的数量.绝对于内置锁synchronized和重入锁ReentrantLock的互斥性来说,Semaphore能够容许多个线程同时访问共享资源 参考自 Go 并发编程-信号量的应用办法和其实现原理 信号量的概念由 Dijkstra 提出,广泛应用在不同的操作系统中。零碎会给每一个过程一个信号量,代表每个过程以后的状态,未失去控制权的过程,会在特定的中央被迫停下来,期待能够持续进行的信号到来。PV操作 个别用信号量来爱护一组资源, 如数据库连接池、一组客户端的连贯等等。每次获取资源时,都会将信号量中的计数器减去对应的数值,在开释资源时从新加回来。当遇到信号量资源不够时,尝试获取的线程就会进入休眠,期待其余线程开释偿还信号量。如果信号量是只有0和1的二进位信号量,那么其 P/V 就和互斥锁的 Lock/Unlock 一样了。 Go 外部应用信号量来管制goroutine的阻塞和唤醒,如互斥锁sync.Mutex构造体的第二个字段,就是一个信号量: type Mutex struct { state int32 sema uint32} 信号量的PV操作在Go外部是通过上面这几个底层函数实现的. 这几个函数都仅供Go语言外部调用,不能在编程时间接应用。 func runtime_Semacquire(s *uint32)func runtime_SemacquireMutex(s *uint32, lifo bool, skipframes int)func runtime_Semrelease(s *uint32, handoff bool, skipframes int)更多可参考 sync包-Mutex 不过Go的 扩大并发原语包 中提供了带权重的信号量 semaphore.Weighted <font color="#CD853F">应用场景</font> 在理论开发中,当须要管制拜访资源的线程数量时,就会须要信号量. 假如有一组要抓取的网站, 资源无限,最多容许同时执行三个抓取工作. 当同时有三个抓取工作在执行时,在执行完一个抓取工作后能力执行下一个排队期待的工作. 这个问题用Channel也能解决,在此应用Go提供的信号量原语来解决该问题: package mainimport ( "context" "fmt" "sync" "time" "golang.org/x/sync/semaphore")func doSomething(u string) { // 模仿抓取工作的执行 fmt.Printf("开始抓取%s网站\n", u) time.Sleep(5 * time.Second)}const ( Limit = 3 // 同時并行运行的goroutine下限 Weight = 1 // 每个goroutine获取信号量资源的权重)func main() { urls := []string{ "http://www.apple.com", "http://www.baidu.net", "http://www.c.com", "http://www.d.com", "http://www.ebay.com", } s := semaphore.NewWeighted(Limit) var w sync.WaitGroup for _, u := range urls { //for的速度远远快过起协程,所以到这里并往下执行时,可能是5个字符串元素工夫差不多 w.Add(1) go func(u string) { s.Acquire(context.Background(), Weight) doSomething(u) s.Release(Weight) w.Done() }(u) } w.Wait() fmt.Println("All Done")}输入为: ...

September 5, 2023 · 4 min · jiezi

关于后端:排序相关问题

本篇博客在B站做了外部分享,题目为「排序相干问题」 MySQL的ORDER BY有两种排序实现形式: 利用有序索引获取有序数据(不得不进行)文件排序在explain中剖析时,利用有序索引获取有序数据显示Using index,文件排序显示Using filesort。 <font color="orange">1. 可能 利用有序索引获取有序数据 的条件比拟刻薄</font> 以下几种优化形式,可能使order by利用到索引,而无需进行filesort: 1、ORDER BY的索引优化。如果一个SQL语句形如:SELECT [column1],[column2],…. FROM [TABLE] ORDER BY [sort];在[sort]这个栏位上建设索引就能够实现利用索引进行order by 优化。 2、WHERE + ORDER BY的索引优化,形如:SELECT [column1],[column2],…. FROM [TABLE] WHERE [columnX] = [value] ORDER BY [sort];建设一个联结索引(columnX,sort)来实现order by 优化。 留神:如果columnX对应多个值,如上面语句就无奈利用索引来实现order by的优化SELECT [column1],[column2],…. FROM [TABLE] WHERE [columnX] IN ([value1],[value2],…) ORDER BY[sort]; 3、WHERE+ 多个字段ORDER BYSELECT * FROM [table] WHERE uid=1 ORDER x,y LIMIT 0,10;建设索引(uid,x,y)实现order by的优化,比建设(x,y,uid)索引成果要好得多。 <font size=3>Order By不能应用索引来优化排序的状况:</font> 对不同的索引键做 ORDER BY :(key1,key2别离建设索引)      SELECT * FROM t1 ORDER BY key1, key2; ...

September 5, 2023 · 2 min · jiezi

关于后端:JIT逆优化导致ES集群CPU异常的问题分析

背景 在一次全链路压测过程中,逆风车匹配ES集群呈现了个别节点CPU简直被打满的状况。第二轮压测,咱们敞开了最近上线的H3召回匹配降级AB试验,在同样压力下集群cpu运行安稳,放弃在35%左右,开启AB试验后之前异样节点cpu又急速减少,初步定位到节点异样应该和H3召回降级试验相干。 问题复现因为压测是在凌晨进行,过后并没有对异样节点的堆栈信息进行具体的拉取和剖析。所以要找到问题的起因咱们首先须要复现问题,刚好上半年咱们实现线上es双集群的我的项目,在业务低峰期能够把线上流量切换到其中一个es集群中,另外一个集群和预发环境的利用进行连贯,通过在预发环境发动申请进行模仿压测,很快便复现了问题,es集群cpu从10%急速增长到100%,详见下图。 在整个过程中网络、磁盘、内存相干指标均未呈现大的稳定,次要耗费是在system load(90%)。 而后,应用Arthas工具生成异样节点的火焰图和热点线程占用,进行剖析。 通过以上火焰图数据分析,咱们发现在程序的次要CPU节约在Deoptimization::uncommon_trap里。 而后开始从Deoptimization::uncommon_trap 动手查阅一些相干的材料,发现这个原来是jit的一种逆优化策略,咱们先来看下什么是jit和逆优化。 背景常识:JIT优化和逆优化为了进步热点代码(Hot Spot Code)的执行效率,在运行时,虚拟机将会把这些代码编译成与本地平台相干的机器码,并进行各种档次的优化,实现这个工作的编译器称为即时编译器(JIT)。 “热点代码”两类:被屡次调用的办法。被屡次执行的循环体 – 只管编译动作是由循环体所触发的,但编译器仍然会以整个办法(而不是独自的循环体)作为编译对象。 Deoptimization::uncommon_trap是一个在JIT编译器中用于解决不常见陷阱的机制。当JIT编译器对一个办法进行编译时,会依据以后的执行环境和代码的个性进行优化,生成相应的本地机器代码。然而,因为一些非凡状况或者代码变动,之前优化的代码可能不再实用。 当产生这种状况时,JIT编译器会触发Deoptimization::uncommon_trap机制。这个机制会将以后的执行状态标记为不常见,而后将控制流返回到解释器或者其余备用代码门路,以便从新执行相应的代码。在从新执行的过程中,JIT编译器会从新生成实用于新状况的本地机器代码。 Deoptimization::uncommon_trap机制的目标是为了保障编译后的代码的正确性和可靠性。当代码执行环境或者代码自身发生变化时,通过触发不常见陷阱,能够及时修复和从新优化代码,以保障程序的正确性和性能。 如: static void test(Object input) { if (input == null) { return; } // do something }如果input始终不为空,执行1W次时,那么上述代码将优化为: static void test(Object input) { // do something }然而如果之后呈现input为空,那么将会触发Uncommon Trap,通过逆优化(Deoptimization)退回到解释状态继续执行。 如果程序始终在执行Deoptimization::uncommon_trap,可能有以下几个可能的起因: 频繁的代码变动:如果程序中频繁地批改代码,特地是对于通过优化的热点代码,会导致JIT编译器重复触发不常见陷阱来从新优化代码。这可能是因为代码变动导致了之前的优化假如不再成立,须要从新优化代码。动静类型变动:如果程序中存在频繁的动静类型变动,例如办法的参数类型常常变动,JIT编译器可能会触发不常见陷阱来解决类型不匹配的状况。这种状况下,能够思考应用类型稳固的代码模式或进行类型查看来缩小不常见陷阱的产生。程序自身的个性:某些程序的个性可能会导致频繁的不常见陷阱,例如大量的动静代码生成、简单的多态调用等。在这种状况下,可能须要从新设计程序结构或应用其余优化技术来缩小不常见陷阱的产生。定位问题&解决方案理解了相干jit和逆优化的常识后,开始联合节点异样期间的热点线程进行具体代码的跟进剖析。 通过进一步剖析,咱们发现在对三个实验组进行了解决逻辑辨别的时候应用switch的形式进行判断,java虚拟机对这块代码设别为热点代码,当办法被执行的次数+办法体内总循环的执行次数 > 阈值,会触发JIT编译成本地代码进行了优化。如果过后依照其中一个实验组进行编译的优化,当其余实验组开流量时这种优化策略便不成立,这时候就呈现了逆优化(Deoptimization)。 解决方案:把原来应用switch形式进行实验组逻辑判断的代码革新成应用map函数式编程的形式。通过优化能够缩小程序中的条件分支,防止逆优化问题的呈现。 HashMap<String, Function<Map<String, ScriptDocValues<?>>, Boolean>> methodMap = new HashMap<>(); methodMap.put("exp1", this::executeForExp1); methodMap.put("exp2", this::executeForExp2); methodMap.put("exp3", this::executeForExp3); executeFunction = methodMap.get(h3Version); ...

September 5, 2023 · 1 min · jiezi

关于后端:Jrebel与Xrebel教学

简介JRebel和XRebel是两个十分有用的工具,能够显著晋升Java开发人员的生产力和应用程序性能。 JRebel是一个弱小的Java开发工具,它容许开发人员在不重新启动应用程序的状况下进行代码批改和调试。传统上,每次批改Java代码都须要从新编译和重新启动应用程序,这会节约大量的工夫。然而,应用JRebel,你能够即时看到你的代码批改的成果,无需重新启动应用程序。这种即时反馈的能力极大地提高了开发效率,缩短了开发周期。 JRebel通过在运行时从新加载批改的类文件,使得代码批改可能立刻失效。它反对各种Java框架和服务器,包含Spring、Hibernate、Tomcat等。此外,JRebel还提供了与常见IDE(如Eclipse、IntelliJIDEA)的集成,使得应用JRebel变得更加不便。 XRebel是另一个弱小的工具,专一于Java应用程序的性能监控和优化。它能够实时监测和剖析应用程序的性能瓶颈,帮忙开发人员疾速定位和解决性能问题。XRebel提供了一个直观的用户界面,显示了应用程序的申请和响应工夫、数据库查问、HTTP会话等要害指标。它还可能检测潜在的性能问题,如慢查问、内存透露等,并提供相应的倡议和解决方案。 XRebel反对各种Java应用程序,包含Web应用程序、企业应用程序等。它能够与常见的Java开发工具和服务器集成,如Eclipse、IntelliJIDEA、Tomcat等。 综上所述,JRebel和XRebel是两个十分有用的工具,能够极大地晋升Java开发人员的生产力和应用程序性能。JRebel容许即时查看代码批改的成果,而XRebel帮忙开发人员实时监测和优化应用程序的性能。这两个工具的联合将为你的Java开发带来更高效和优化的体验。 激活能够参考这篇文章: Jrebel与Xrebel激活 一、XRebel有哪些性能间接在调用接口时查看报错信息,不须要去服务器上看日志文件,防止繁琐定位日志问题,还在一次次的切窗口去翻日志??? 查看接口外部解决工夫,能够通过这个剖析并优化程序性能 查看所有的IO操作,具体SQL,SQL耗时都有哦,神奇啊!!!! 查看日志。。 二、下载JRebel官网地址:https://jrebel.com/software/xrebel/download/thank-you/?file=xrebel/releases/xrebel-4.0.1.zip私人提供:https://weiyun-1253652709.cos.ap-guangzhou.myqcloud.com/xrebel.jar三、启动启动我的项目时,指定javaagent即可 :-javaagent:xrebel.jar,前面jar包地址依据理论环境批改TIP:idea中springboot我的项目启动 四、查看我的项目启动后,在我的项目根url前面输出/xrebel,并点击start即可 点击之后是这样子滴 这时候进swagger就能间接看到了哦! 请关注某绿色软件【程序员朱永胜】回复1011获取 双击关上获取UUID关上https://www.guidgen.com/ 生成一个UUID JH拷贝UUID到这里即可JH com/202308062052295.png) 设置成开机自启办法一启动后不久会主动挂掉,倡议应用办法二 办法一关上cmd执行以下命令 这里要留神,必须为管理员启动 注册为服务 sc create jrebelJH binPath= "C:\Users\17602\Documents\install\ReverseProxy_windows_386.exe"设置开机自启 sc config jrebelJH start= auto启动 sc start jrebelJH办法二关注【程序员朱永胜】回复【1022】获取安装包 关上cmd执行以下命令 这里要留神,必须为管理员启动 将压缩包解压 执行命令 cd C:\Users\17602\Downloads\nssm-2.24-101-g897c7ad\win64\注册 nssm install jrebelJH2 "C:\Users\17602\Documents\install\ReverseProxy_windows_386.exe"启动 sc start jrebelJH 本文由mdnice多平台公布

September 5, 2023 · 1 min · jiezi

关于后端:基于SSM的实验室设备仪器样品管理系统Android

 博主介绍:✌退职Java研发工程师、专一于程序设计、源码分享、技术交换、专一于Java技术畛域和毕业设计✌舒适提醒:文末有 CSDN 平台官网提供的老师 Wechat / QQ 名片 :) 项目名称 基于SSM的实验室设施仪器样品管理系统+Android 演示视频 https://ym.maptoface.com/archives/60496 零碎介绍 数字网络技术在晚期的20世纪80年代-90年代开始倒退,逐步成为21世纪的支流。 网络倒退也扭转了咱们生存形式,当初曾经有了智能手机的呈现,咱们能够通过手机和电脑上通过网络传输进行数据同步,现目前应用最多的就是Android零碎的智能手机,因为从Android开发以来始终是开源零碎,让晚期很多不足开发能力和业余技术不齐全的手机厂家找到了“救星”,很快Android零碎迅速遍及到全国各个中央。在高校的网络建设中也起到很要害的作用,实验室设施仪器样品管理系统可能高效、便捷的治理实验室的日常工作,并且实验室管理系统的数据共享性能可能是实验室管理人员和学生之间进行无效的沟通,晋升治理设施技术性、专业性,也让实验室的信息程度建设有了质的变动。实验室治理建设和治理的改革工作的无效发展,就须要对实验室设施仪器样品管理系统的无效钻研。 本零碎是基于SSM框架加上MySQL数据库技术的实验室设施仪器样品管理系统,本文剖析了设计时遵循的软件工程思维,并以此为根据进行零碎的开发。依据查阅的材料和结合实际需要加上参考大量的我的项目来进行剖析和设计,采纳B/S框架联合JSP技术来开发。为了保证数据长久化须要应用数据库保留数据,应用MySQL数据库来保留。依据高校理论需要,零碎实现了管理员的后盾WEB零碎端以及基于Android的用户手机端,实现了人员治理、设施治理、设施借用、设施偿还、设施分类等实验室常见性能,并且通过一段时间的测试,零碎运行稳固、界面敌对、操作灵便不便、数据查问高效。 关键词:实验室设施治理;Android;SSM;设施借还 1.4.2 性能需要剖析 基于Android的实验室样品与器材治理App的性能需要剖析旨在解决以下问题: 用户治理:提供对管理员和普通用户的治理性能,确保不同角色的用户能够正确应用零碎。组织设置:解决不同组织架构之间的关系,使得不同学校和学院能够独立治理各自的实验室设施和样品。物品信息管理:实现对实验室设施、仪器和样品的对立治理,不便实验室管理人员对物品进行保护和监控。借用/偿还治理:优化设施借用和偿还流程,确保学生能够顺利借用和偿还设施,同时不便管理员对借用和偿还记录进行治理。设施分类管理:对设施、仪器和样品进行分类管理,进步管理效率和便利性。设施搜寻:容许学生在手机端疾速搜寻并获取实验室设施和样品的相干信息。设施借用:简化学生借用设施的流程,同时提供设施借用状态的查问性能。设施偿还:不便学生在手机端进行设施偿还操作,同时提供待偿还和已偿还设施信息的查问性能。通过这些性能需要剖析,App的设计和实现将解决实验室设施和样品治理中的痛点问题,进步实验室管理效率,优化学生借用和偿还设施的体验,并简化管理员对实验室资源的监控和保护工作。 1.4.3 用例剖析 1.学生用例剖析 学生用户次要是应用手机端进行零碎操作的,在手机端进行登录后能够进行设施搜寻、设施借用、查看设施借用状态、设施偿还、查看设施偿还状态、明码批改和退出零碎的操作。学生用例如图2-1所示。 图2-1 用户用例图 2.管理员用例剖析 在登录胜利后能够操作管理员性能,管理员是整个零碎中权限最大的用户,基本上所有数据的治理和保护管理人员都能够操作。所以管理人员的账号密码须要应用高验证的明码最好。首次启动程序,须要管理员登录后初始化一部分的数据后,我的项目能力失常运行,所以后期最好做肯定的管理员操作培训。 管理员用例如图2-2所示。 图2-2 管理员用例图 2.2 功能模块设计 在零碎的的功能分析当中,须要明确的是零碎用户的所有功能模块并且明确它们的分割,并且还须要对系统的角色进行划分从而明确零碎的性能权限用以设计前端页面。 次要蕴含性能如以下所示: (1)用户治理:包含了对管理员以及用户的治理性能,能够对用户进行减少、删除、批改、受权、登记、批改明码等数据的批改。 (2)组织设置:零碎用户属于不同的组织架构中,不同的组织架构对应不同的学校学院。 (3)物品信息管理:系统管理员能够对系统的所有设施、仪器以及样品进行对立的增删改查治理。 (4)借用/偿还治理:用户在手机端进行设施借用后,管理员进行审核是否批准借用,用户借用设施后进行偿还操作,这一系列操作流程都会留下记录进行治理。 (5)设施分类管理:不同的设施、仪器、样品都属于不同的分类,通过分类来对设施进行分类,治理将会更加粗疏化。 (6)设施搜寻:用户在手机端能够对系统的设施样品进行搜寻,包含分类、所属学校、编号、创立工夫等信息。 (7)设施借用:用户在手机端抉择须要借用的设施填写单据、借用工夫、偿还工夫、借用人员、备注信息后进行借用操作,并且能够查问到审核中以及借用中的设施。 (8)设施偿还:用户在手机端进行设施的偿还,并且能够查问到待偿还以及已偿还的设施信息。 2.2.1 学生功能模块设计 学生功能模块包含登录、设施搜寻、借用操作、偿还操作、批改明码、个人信息、增加借用、借用查问、偿还设施、偿还查问。学生功能模块图如3-2所示: 图3-3 管理员功能模块图 编辑 编辑 编辑 编辑 零碎截图 编辑 编辑 编辑 编辑 编辑 编辑 编辑 编辑 编辑 编辑 编辑 编辑 编辑 编辑 ...

September 5, 2023 · 5 min · jiezi

关于后端:ToplingDB-如何减小写放大功大欺理

背景ToplingDB,尽管 fork 自 RocksDB 并且兼容其 API,但实现了本性难移的改良,最重要的就是实现了性能更高的 CSPP MemTable(Rep) 和 SST。ToplingDB CSPP MemTable 设计精要 对 CSPP MemTable 进行了初步介绍。对于共享内存shm和内存映射mmap的区别是什么? 介绍了 CSPP 间接将 MemTable 转化为 SST。2. 减小写放大实际上,间接把 MemTable 转化为 SST,除了间接地缩小 CPU/内存/IO 耗费,还能够带来进一步的收益:减小写放大。LSM 的数据分为多层,通常状况下,每层数据规模是上一层的 10 倍(可配置),Level Compaction 对相邻两层 key 重叠的文件进行合并,由此带来写放大。对于齐全随机的输出,在零碎进入稳固状态时,每层引入的写放大是 10,事实中的理论数据有肯定法则,写放大远小于齐全随机的数据,例如在 TPCC 测试中,通过 ToplingDB 的 WebView 能够看到:这里写放大远小于随机数据在每层中引入的写放大(10),写放大的计算公式继承原版 RocksDB。咱们将 MemTable 尺寸设为 1G,max_bytes_for_level_base 也设为 1G,开启 convert_to_sst 时,L0 的写放大实际上是 0(图中显示的是 1.0) 。与此同时,因为 max_bytes_for_level_base 比拟大(默认是 256M),所以咱们的 L1 尺寸实际上近似于 RocksDB 的 L2,由此,咱们相当于打消了原版 L1->L2 的所有 Compact,假设原版 L1->L2 compact 写放大也是 3.7,咱们这里相当于将总的写放大减小了 3.7。再算上 L0 的理论写放大从 1.0 减到了 0,咱们将总的写放大减小了 4.7!3. 为什么 ToplingDB 能够这样做MemTable 转化成 SST 能够霎时实现,max_write_buffer_number=2 就足以撑持最大的写压力。CSPP MemTable 的内存是 File Mmap,从而,这些内存能够 swap 进来,特地是当存在不沉闷的 SuperVersion 导致老旧 MemTable 无奈开释时(没有拜访,但也无奈开释),malloc 的内存个别很少被 swap,就要始终占用物理内存。所以,同样是 5 个(或者10个,20个)MemTable 无奈开释,ToplingDB 只有沉闷的 MemTable 占用物理内存,而 rocksdb 的所有 MemTable 都要占用物理内存。其次,从 MemTable 转化来的 SST,和 MemTable 共享同一份 PageCache,相当于并未耗费额定内存。再次,从 MemTable 转化来的 SST 不须要 BlockCache,又一次减小了内存用量。所有这些劣势叠加,ToplingDB 能够熟能生巧,不附带任何条件地,全方位地优于 RocksDB 。【完】【附】write_buffer_size 和 max_bytes_for_level_base = 256M 时(rocksdb 默认值)【附】write_buffer_size 和 max_bytes_for_level_base = 2560M 时(rocksdb 默认值的 10 倍)这两个比照充沛地展现了不同配置下写放大的差别:9.0 vs 6.6,因为实际上 L0 的写放大是 0,所以实在的写放大是 8.0 vs 5.6。其中,L4 开始启用压缩,写放大是按压缩后的尺寸计算的,按未压缩的尺寸算,须要乘以 3.3(L4 压缩到30.6%),按 256M 配置,153.8*3.3 = 505.9,综合写放大是 9.0 + (505.9/221.4) - 1 = 10.3。所以实在的比照是 9.3 vs 5.6!

September 5, 2023 · 1 min · jiezi

关于后端:JPAquerydsl增强工具querydslplus现在已开源并推送到mvnrepository

前言约定俗成......一种接口通用的查询方法,简化开发,加强性能,让更多的精力放在更简单的业务上。即--依照约定,将查问条件封装成string,前端随时随便更改,然而后盾不必任何调整,一个查问接口就能实现绝大多数条件查问。 因为喜爱应用JPA,所以后续就接触了query-dsl,然而呢,随着需要的变更,数据查问条件也会越来越简单(这个和jpa没关系,就算应用mybatis也一样) 我的项目开源地址(以github为主,国内应用jpa挺少,然而gitee也会实时更新): gitee: https://gitee.com/mose-x/query-dsl-plus.gitgithub:https://github.com/mose-x/query-dsl-plus.git 先上应用成果__ ---------------------------------------------------------------------------------------------- 留神,这里的参数必须 encode URI 转换,否则会报错,此处为了展现分明__ ---------------------------------------------------------------------------------------------- __ ---------------------------------------------------------------------------------------------- 留神,这里的参数必须 encode URI 转换,否则会报错,此处为了展现分明__ ---------------------------------------------------------------------------------------------- 疾速应用引入 <dependency> <groupId>cn.ljserver.tool</groupId> <artifactId>query-dsl-plus</artifactId> <version>1.0.0-RELEASE</version></dependency>DAO 继承 QuerydslBinderCustomizerService 继承 SearchServiceapi测试

September 5, 2023 · 1 min · jiezi

关于后端:ToplingDB-的-SidePlugin-配置系统

ToplingDB 配置零碎对于 ToplingDB 配置零碎 的设计动机,请参考 Motivation To Solution 概要ToplingDB 配置零碎采纳 json/yaml 格局定义配置项,将 ToplingDB/RocksDB 的所有元对象均纳入此配置零碎。总体而言,ToplingDB 配置零碎实现了以下指标:ToplingDB/RocksDB 的所有配置需要无缝插件化:用户代码无需批改,即可插入第三方模块(例如 ToplingZipTable)可视化:通过 Web Service 展现引擎外部状态(相干文档)监控:通过 Web Service 将引擎指标导出到 Prometheus,进而应用 grafana 可视化简化多语言 Binding (只须要 bind conf 对象即可) 具体介绍ToplingDB/RocksDB 的根配置对象是 DBOptions 和 ColumnFamilyOptions,额定的 Options 对象是 DBOptions 和 ColumnFamilyOptions(简称 CFOptions) 的结合体(从后两者继承而来)。DBOptions 和 CFOptions 中蕴含二级配置对象,有些二级对象还进一步蕴含三级配置对象。所有这些对象,都定义为 json 中以其基类名命名的一级 json 对象的子对象,另外,json 中还有另外几个非凡的一级 json 对象(http,setenv,databases,open)。能够在 json 对象中援用其它 json 对象,这些援用将转化成 C++ 对象间的援用关系。 2.1. json 配置示例 { "http": { "document_root": "/path/to/dbname", "listening_ports": "8081"},"setenv": { "DictZipBlobStore_zipThreads": 8, "StrSimpleEnvNameNotOverwrite": "StringValue", "IntSimpleEnvNameNotOverwrite": 16384, "OverwriteThisEnv": { "overwrite": true, "value": "overwrite is default to false, can be manually set to true" }},"permissions": { "web_compact": true },"Cache": { "lru_cache": { "class": "LRUCache", "params": { "capacity": "4G", "num_shard_bits": -1, "high_pri_pool_ratio": 0.5, "strict_capacity_limit": false, "use_adaptive_mutex": false, "metadata_charge_policy": "kFullChargeCacheMetadata" } }},"WriteBufferManager" : { "wbm": { "class": "Default", "params": { "//comment": "share mem budget with cache object ${lru_cache}", "buffer_size": "512M", "cache": "${lru_cache}" } }},"Statistics": { "stat": "default" },"TableFactory": { "bb": { "class": "BlockBasedTable", "params": { "block_cache": "${lru_cache}" } }, "fast": { "class": "ToplingFastTable", "params": { "indexType": "MainPatricia" } }, "zip": { "class": "ToplingZipTable", "params": { "localTempDir": "/dev/shm/tmp", "sampleRatio": 0.01, "entropyAlgo": "kNoEntropy" } }, "dispatch" : { "class": "DispatcherTable", "params": { "default": "bb", "readers": { "ToplingFastTable": "fast", "ToplingZipTable": "zip" }, "level_writers": ["fast", "fast", "bb", "zip", "zip", "zip", "zip"] } }},"CFOptions": { "default": { "max_write_buffer_number": 4, "write_buffer_size": "128M", "target_file_size_base": "16M", "target_file_size_multiplier": 2, "table_factory": "dispatch", "ttl": 0 }},"databases": { "db1": { "method": "DB::Open", "params": { "options": { "write_buffer_manager": "${wbm}", "create_if_missing": true, "table_factory": "dispatch" } } }, "db_mcf": { "method": "DB::Open", "params": { "db_options": { "create_if_missing": true, "create_missing_column_families": true, "write_buffer_manager": "${wbm}", "allow_mmap_reads": true }, "column_families": { "default": "$default", "custom_cf" : { "max_write_buffer_number": 4, "target_file_size_base": "16M", "target_file_size_multiplier": 2, "table_factory": "dispatch", "ttl": 0 } }, "path": "'dbname' passed to Open. If not defined, use 'db_mcf' here" } }},"open": "db_mcf"}2.2. 非凡对象2.2.1. http在这个示例中,第一个 json 子对象是: ...

September 5, 2023 · 3 min · jiezi

关于后端:UML基础

对立建模语言(UML是 Unified Modeling Language的缩写, 是用来对软件系统进行可视化建模的一种语言。UML为面向对象开发零碎的产品 进行阐明、可视化、和编制文档的一种规范语言。 共有9种图 UML中的图其实不止九种 (雷同的图还可能会有不同的名称), 这里的九种图是被广泛认可的根底图, 别离为:用例图、类图、对象图、状态图、构件图、部署图、合作图、交互序列图、流动图。 之前在惠普时,用过时序图(即程序图,交互序列图) UML图也可分为用例视图、设计视图、过程视图、实现视图和拓扑视图 又能够依据静动分为动态视图和动静视图 动态图分为:用例图,类图,对象图,包图,构件图,部署图动态图分为:状态图,流动图,合作图,序列图 个别状况下,又以类图,状态图,用例图最为重要 <font color="#FF8C00">类图(Class Diagram)</font> 类图是应用频率最高的UML图之一 If someone were to come up to you in a dark alley and say, 'Psst, wanna see a UML diagram?' that diagram would probably be a class diagram. The majority of UML diagrams I see are class diagrams.” --- Martin Fowler 《UML Distilled: A Brief Guide to the Standard Object Modeling Language, Third Edition》 ...

September 5, 2023 · 1 min · jiezi

关于后端:统计命令汇总

实用于Unix体系 对于wc命令 Word Count 用于统计指定文件中的字节数、字数、行数,并将统计结果显示输入。 wc [-lcw] c 统计字节数l 统计行数m 统计字符数,此标记不能与-c标记一起应用w 统计字数。一个字定义为由空白、跳格或换行字符分隔的字符串 统计某文件夹下的文件数量 ls -l | grep "^-" | wc -l <font color="#668B8B" size=1> grep "^-": 将ls -l长列表输入信息过滤一部分,只保留个别文件; 如果只保留目录就是 ^d wc -l: 统计输入信息的行数, 因为曾经过滤得只剩个别文件了,又因为一行信息对应一个文件, 所以后果也就是文件的个数 </font> 统计某文件夹下的目录的数量(即文件夹的数量) ls -l | grep "^d" | wc -l 统计文件夹下文件的个数,包含子文件 ls -lR | grep "^-" | wc -l <font color="#668B8B" size=1> -R为 递归子文件夹 wc -l: 统计输入信息的行数, 因为曾经过滤得只剩个别文件了,又因为一行信息对应一个文件, 所以后果也就是文件的个数 </font> ...

September 5, 2023 · 1 min · jiezi

关于后端:谷歌身份验证器如何工作的

谷歌身份验证器如何工作的?谷歌身份验证器 (Google Authenticator)是一种基于软件的身份验证器,可实现两步验证服务 (2FA, Two-Factor Authentication)。 如何了解两步验证服务?鉴权 (Authentication) 从大方向来说蕴含3种因素: 常识因素:你所晓得的 (something you know)。比方事后设置的明码。所有权因素:你所领有的 (something you own)。比方一次性明码能够证实咱们领有一部手机或其余设施。固有因素:你自身具备的 (something you are)。比方指纹、人脸和虹膜等生物特色。 比方,为了进步账户安全性,网站在用明码登录后会提醒输出谷歌身份验证器生成的一次性明码。这样就联合了前两类因素。谷歌身份验证器的应用分两个阶段。 第一个阶段 - 用户启用谷歌身份验证器。 步骤 1 和 2:韩梅梅关上网页以启用两步验证。前端申请一个秘钥 (Secret Key)。验证服务会为韩梅梅生成秘钥,并将其存储在数据库中。步骤 3:验证服务向前端返回一个 URI。URI 由密钥发放者、用户名和秘钥组成。URI 以二维码的模式显示在网页上。步骤 4:而后,韩梅梅应用谷歌身份验证器扫描生成的 QR 码。秘钥存储在验证器客户端中。第二个阶段 - 用户应用验证器登录 步骤 1 和 2:韩梅梅想通过谷歌两步验证登录一个网站。每隔 30 秒,谷歌身份验证器会应用 TOTP (Time-based One Time Password)算法生成一个 6 位数的明码。韩梅梅在网站上输出这个明码。步骤 3 和 4:韩梅梅输出的明码被发送到后盾进行身份验证。验证服务从数据库中读取秘钥,并应用与客户端雷同的 TOTP 算法生成一个 6 位数明码。步骤 5:身份验证服务比拟客户端和服务器生成的两个明码,并将比拟后果返回前端。只有当两个明码匹配时,韩梅梅能力持续登录。这种身份验证机制平安吗?他人是否获取秘钥?谷歌身份验证器应用HTTPS来传输密钥,并且客户端和数据库是以加密的模式来存储密钥。多层加密确保了密钥的安全性。 生成的 6 位明码会被黑客猜到吗?不会。明码有 6 位数字,因而生成的明码有 100 万种可能的组合。此外,明码每 30 秒更改一次。如果黑客想在 30 秒内猜出明码,他们每秒须要输出 30,000 个明码组合。 ...

September 5, 2023 · 1 min · jiezi

关于后端:SSD存储中的规格接口和协议

SSD Form Factor-形状规格决定了硬盘的尺寸规格形态。 SATA长宽:宽30mm,长51mm。厚度:单面颗粒厚度为4.85mm。线缆:SATA硬盘须要两根线缆,一条用于和主板之间传输数据,另一条须要电源供电。 M.2长宽:宽度在12、16、22、30mm,长度在16、26、30、38、42、60、80、110mm,比方最常见的"M.2 2280"就示意宽22mm长80mm规格的盘。厚度:单面颗粒厚度在2.75mm,双面颗粒厚度在3.85mm。 Interface-接口SATA (Serial Advanced Technology Attachment)SATA interface只能用SATA SSD。 PCIe (Peripheral Component Interconnect Express)PCIe通道PCIe能够有多条通道(lane)并行传输数据,每个PCIe通道蕴含两条铜线,一条用于向CPU发送数据,另一条用于承受数据,PCIe lane是全双工的所以要留神辨别单向和双向带宽。比方GPU往往须要16通道能力达到最佳性能,最近几代PCIe的显卡能够在至多8个PCIe通道的状况下对渲染程序提供最佳性能。PCIe有两类通道,CPU PCIe通道间接与CPU相连,而一般的PCH PCIe通道还是须要通过DMI (Direct Media Interface)连贯到CPU(须要CPU有专门反对的CPU PCIe通道),因为这个总带宽无限,还会连USB、网卡之类的,所以链路可能会饱和使得性能降落。https://zhuanlan.zhihu.com/p/584802526 PCIe插槽主板的PCIe插槽上有x1、x4、x8、x16配置,决定的是PCIe连接器的物理尺寸,插槽的配置数不肯定等于通道数,有可能有x16的插槽然而只有8个通道。 PCIe带宽从PICe 1.0到5.0,每一代带宽都会翻倍。PCIe的接口带宽须要应用每通道带宽乘以通道数,留神每通道带宽是要算无效数据传输效率,而不是数据传输速率。具体地,PCIe1.0-2.0每传8个bit无效数据须要用10bit(编码方案8b/10b),而PCIe 3.0-5.0是128b/130b,PCIe 6.0-7.0是1b/1b。所以,理论吞吐量=传输速率*编码效率。https://zhuanlan.zhihu.com/p/646920500 下层软件协定AHCI、SCSI以前的协定,对于协定分类能够看:https://www.zhihu.com/question/592159651/answer/3010648376 NVMe (Non-Volatile Memory Express)NVMe就是专门为高速PCIe接口上的NAND、闪存等非易失性存储设计的(尽管实践上也能够不必在PCIe接口上),从而冲破SATA接口的速度限制。 命令集NVMe简化了命令集,相比于IDE和SCSI,所须要的CPU指令数缩小了一半。 Queue和Queue Depth最大反对64K-1(65535)个queue,最大反对64000QD。 本文由博客一文多发平台 OpenWrite 公布!

September 5, 2023 · 1 min · jiezi

关于后端:orchestrator系列二故障检测与恢复

Orchestrator实现了主动Failover,当初来看看主动Failover的大抵流程是怎么样的。 1、故障检测(Failure detection)orchestrator应用整体性办法来检测主节点和两头主节点的故障。 在原始的检测办法中,监控工具会探测主节点,并在无奈分割或查问主服务器时收回警报。这种办法容易受到网络故障引起的误报的影响。为了缩小误报的几率,简略办法通过以t长时间距离运行n个测试来缓解这个问题。这在某些状况下缩小了误报的几率,但也减少了在真正故障事件产生时的响应工夫。 orchestrator利用了复制拓扑。它不仅察看master server自身,还察看其正本。例如,为了诊断一个主节点生效的状况,orchestrator必须同时满足以下两个条件: *无奈连贯主节点 可能连贯到主节点的正本,并确认它们也无奈看到主节点* orchestrator不是按工夫来排查谬误,而是通过多个观察者,即复制拓扑中的服务器。实际上,当一个主节点的所有正本都统一认为它们无奈分割到主节点时,复制拓扑实际上曾经呈现故障,此时进行故障转移是正当的。 orchestrator的整体性故障检测办法在生产环境中被认为十分牢靠。 2、检测和复原(Detection and recovery)检测并不总是导致复原。有一些状况下不心愿进行复原: 集群没有被列为主动故障转移的候选项; 管理员批示不应在特定服务器上进行复原; 管理员全局禁用了复原操作; 在之前的故障转移实现后不久,进行了重复操作; 故障类型被认为不值得进行复原; 在冀望的状况下,复原会立刻追随检测。在其余状况下,例如被阻止的复原,复原可能在检测后的几分钟内进行。 检测是独立于复原的,并且始终处于启用状态。依据检测执行OnFailureDetectionProcesses钩子函数,具体配置看下文故障检相干测配置。 3、故障检测相干配置故障检测的配置: { "FailureDetectionPeriodBlockMinutes": 60,}组织发送工夫,orchestrator每秒检测一次。 hooks: { "OnFailureDetectionProcesses": [ "echo 'Detected {failureType} on {failureCluster}. Affected replicas: {countReplicas}' >> /tmp/recovery.log" ],}MySQL 侧设置: set global slave_net_timeout = 4在从库和主库之间设置一个较短(2秒)的心跳距离,使从库可能疾速辨认故障。如果没有进行此设置,某些状况可能须要长达一分钟能力检测到故障。 CHANGE MASTER TO MASTER_CONNECT_RETRY=1, MASTER_RETRY_COUNT=86400在复制失败的状况下,使从库每秒尝试从新连贯(默认为60秒)。对于短暂的网络问题,此设置尝试疾速复原复制,如果胜利,将防止由协调器执行的个别故障/复原操作。 故障检测场景 以下是潜在故障列表: - DeadMaster 主节点故障- DeadMasterAndReplicas 主节点和正本节点故障- DeadMasterAndSomeReplicas 主节点和局部正本节点故障- DeadMasterWithoutReplicas 主节点没有正本节点- UnreachableMasterWithLaggingReplicas 无法访问的主节点且存在滞后的正本节点- UnreachableMaster 无法访问的主节点- LockedSemiSyncMaster 被锁定的半同步主节点- MasterWithTooManySemiSyncReplicas 主节点具备过多的半同步正本- AllMasterReplicasNotReplicating 所有主节点正本均未进行复制- AllMasterReplicasNotReplicatingOrDead 所有主节点正本未进行复制或进行工作- DeadCoMaster 协同主节点故障- DeadCoMasterAndSomeReplicas 协同主节点和局部正本节点故障- DeadIntermediateMaster 两头主节点故障- DeadIntermediateMasterWithSingleReplicaFailingToConnect 两头主节点故障且单个正本无奈连贯- DeadIntermediateMasterWithSingleReplica 两头主节点故障且只有一个正本节点- DeadIntermediateMasterAndSomeReplicas 两头主节点和局部正本节点故障- DeadIntermediateMasterAndReplicas 两头主节点和正本节点故障- AllIntermediateMasterReplicasFailingToConnectOrDead 所有两头主节点正本无奈连贯或进行工作- AllIntermediateMasterReplicasNotReplicating 所有两头主节点正本未进行复制- UnreachableIntermediateMasterWithLaggingReplicas 无法访问的两头主节点且存在滞后的正本节点- UnreachableIntermediateMaster 无法访问的两头主节点- BinlogServerFailingToConnectToMaster Binlog服务器无奈连贯到主节点4 拓扑复原拓扑复原 ...

September 4, 2023 · 1 min · jiezi

关于后端:面试题精讲MySQL中覆盖索引是什么

有的时候博客内容会有变动,首发博客是最新的,其余博客地址可能会未同步,认准https://blog.zysicyj.top首发博客地址 系列文章地址 在MySQL中,笼罩索引是一种非凡类型的索引,它蕴含了查问所需的所有列,而不仅仅是索引列自身。当一个查问能够齐全应用笼罩索引来满足时,MySQL能够间接从索引中读取数据,而无需拜访理论的数据行,从而进步查问性能。 应用笼罩索引的益处是缩小了磁盘I/O和内存的应用,因为MySQL不须要加载和解决理论的数据行。这对于查问大型表或者须要频繁执行的查问特地有用。 要创立笼罩索引,你须要确保索引蕴含了查问所需的所有列。例如,如果你有一个蕴含列A、B和C的表,并且你的查问只须要列A和B,那么你能够创立一个蕴含列A、B和C的索引,以便笼罩查问。 上面是一个示例,展现了如何创立一个笼罩索引: CREATE INDEX idx_covering ON your_table (column_a, column_b, column_c);在这个示例中,your_table是你的表名,column_a、column_b和column_c是你想要蕴含在索引中的列。 请留神,笼罩索引并不适用于所有类型的查问。它对于抉择少量列的查问十分无效,但对于须要返回大量列或进行简单计算的查问可能不太实用。此外,过多的笼罩索引可能会减少写操作的开销,因为每次更新表时都须要更新索引。 因而,在设计索引时,须要衡量查问性能和写操作的开销,并依据具体的查问需要来决定是否应用笼罩索引。 本文由mdnice多平台公布

September 4, 2023 · 1 min · jiezi

关于后端:Kafka系列一Kafka入门

有的时候博客内容会有变动,首发博客是最新的,其余博客地址可能会未同步,认准https://blog.zysicyj.top首发博客地址 系列文章地址 Kafka是什么?一句话概括:Apache Kafka 是一款开源的音讯引擎零碎 什么是音讯引擎零碎?音讯引擎零碎(Message Broker System)是一种中间件软件或服务,用于在分布式系统中进行异步消息传递。它提供了牢靠的音讯传输、音讯路由和音讯解决的性能,使不同的应用程序和组件可能通过发送和接管音讯进行通信。 音讯引擎零碎通常由以下几个外围组件组成: 发布者(Publisher):负责将音讯公布到音讯引擎零碎中。发布者将音讯发送到指定的主题(Topic)或队列(Queue)中。订阅者(Subscriber):订阅者能够通过订阅特定的主题或队列来接管音讯。订阅者能够依照本人的需要抉择订阅的音讯类型和主题。主题/队列(Topic/Queue):主题或队列是音讯的目的地,音讯发布者将音讯发送到特定的主题或队列,而订阅者能够从中接管相应的音讯。音讯路由(Message Routing):音讯引擎零碎负责将音讯路由到正确的订阅者。它依据订阅者的订阅关系和音讯的标识(如主题、标签等)来确定音讯的路由形式。音讯长久化(Message Persistence):音讯引擎零碎通常会将音讯长久化到存储介质中,以确保音讯的可靠性和持久性。这样即便在系统故障或重启后,音讯依然能够被正确地传递和解决。消息传递模式(Message DeliveryPatterns):音讯引擎零碎反对多种消息传递模式,如点对点模式(Point-to-Point)、公布/订阅模式(Publish/Subscribe)、申请/响应模式(Request/Response)等,以满足不同的通信需要。音讯引擎零碎具备解耦性、可靠性和扩展性等长处,使得分布式系统中的不同组件可能进行异步通信,进步零碎的可靠性、可伸缩性和性能。常见的音讯引擎零碎包含ApacheKafka、RabbitMQ、ActiveMQ等。 为什么要引入音讯引擎呢?间接A发送给B不好吗?引入音讯引擎零碎的次要目标是解耦和进步零碎的可伸缩性、可靠性和性能。上面是一些应用音讯引擎零碎的长处: 解耦性:通过引入音讯引擎零碎,发送者和接收者之间能够解耦。发送者只须要将音讯发送到音讯引擎中的特定主题或队列,而不须要间接晓得接收者的详细信息。接收者能够依据本人的需要抉择订阅相应的主题或队列来接管音讯。这种解耦能够使零碎的组件能够独立演变和扩大,防止了紧耦合的依赖关系。异步通信:音讯引擎零碎反对异步通信模式,发送者能够将音讯发送到音讯引擎中后立刻返回,而不须要期待接收者的响应。这种异步通信模式能够进步零碎的响应速度和并发解决能力,使得发送者和接收者能够独立地进行工作解决,进步零碎的整体性能和吞吐量。可靠性:音讯引擎零碎通常会将音讯长久化到存储介质中,以确保音讯的可靠性和持久性。即便在系统故障或重启后,音讯依然能够被复原和传递,防止了音讯的失落。此外,音讯引擎零碎还提供了音讯的确认机制和重试机制,确保音讯的牢靠传递。扩展性:应用音讯引擎零碎能够轻松地扩大零碎的规模和容量。通过减少音讯引擎的实例或减少音讯队列的分区,能够实现程度扩大,以解决更大的音讯流量和更高的并发申请。消息传递模式:音讯引擎零碎反对多种消息传递模式,如点对点模式、公布/订阅模式、申请/响应模式等。不同的模式实用于不同的业务场景,能够依据需要抉择适合的模式。引入音讯引擎零碎能够提供更灵便、牢靠和高效的消息传递形式,使得零碎能够更好地适应简单的业务需要和分布式环境。它提供理解耦、异步通信、可靠性、可伸缩性和性能等劣势,使零碎设计更具弹性和可维护性。 常见的音讯传输模型有哪些呢在计算机系统中,常见的音讯传输模型有以下几种: 点对点模型(Point-to-Point Model):在点对点模型中,音讯的发送者将音讯发送到特定的接收者。每个音讯只被一个接收者接管,相似于一对一的通信。这种模型通常应用队列或消息中间件来实现,例如JMS(JavaMessage Service)中的点对点模型。公布/订阅模型(Publish/SubscribeModel):在公布/订阅模型中,音讯的发送者(发布者)将音讯公布到一个主题(Topic),多个接收者(订阅者)能够订阅该主题,接管公布的音讯。这种模型通常用于播送音讯给多个接收者,相似于一对多的通信。常见的实现包含音讯队列、消息中间件、事件总线等。申请/响应模型(Request/ResponseModel):在申请/响应模型中,客户端发送申请音讯给服务端,服务端解决申请并发送响应音讯给客户端。这种模型通常用于客户端向服务端申请数据或执行操作,并期待服务端返回响应。常见的实现包含HTTP协定、RPC(RemoteProcedure Call)等。公布/订阅加申请/响应模型:这种模型联合了公布/订阅模型和申请/响应模型的个性。音讯的发送者能够公布音讯到一个主题,多个接收者能够订阅该主题并接管音讯。同时,某些接收者还能够向发送者发送申请音讯,并期待发送者的响应音讯。这种模型通常用于实现简单的分布式系统和消息传递模式。这些音讯传输模型能够依据具体的需要和场景进行抉择和组合,以实现灵便、牢靠的音讯传输和通信。不同的模型实用于不同的利用场景,需依据具体的业务需要来抉择适合的模型。 那么,kafka反对哪些音讯传输模型?Kafka是一个分布式流解决平台,它反对以下几种常见的音讯传输模型: 公布/订阅模型(Publish/SubscribeModel):Kafka的外围个性就是基于公布/订阅模型的音讯传输。生产者(发布者)将音讯公布到一个主题(Topic),多个消费者(订阅者)能够订阅该主题,以并行形式生产音讯。Kafka应用消息日志来长久化音讯,保障音讯的持久性和可靠性。队列模型(Queue Model):只管Kafka次要是基于公布/订阅模型,但也能够通过应用单个消费者组来实现相似队列模型的行为。在这种状况下,每个主题的每个分区只能由一个消费者生产,确保音讯按程序进行解决。申请/响应模型(Request/ResponseModel):只管Kafka次要是用于流式解决,但也能够应用申请/响应模式。客户端能够向Kafka发送申请音讯,并期待Kafka返回响应音讯。这种模型通常用于须要以申请/响应形式与Kafka进行交互的利用场景。批量解决模型(Batch Processing Model):Kafka反对从生产者端进行音讯批量发送,以及从消费者端进行音讯批量生产。这种模型能够更无效地利用网络和IO资源,进步音讯的吞吐量和性能。Kafka的灵活性和可扩展性使其实用于许多不同的利用场景,包含实时数据流解决、音讯队列、日志收集和剖析等。依据具体的需要,能够抉择适合的模型来构建基于Kafka的音讯传输零碎。 不同模型对应的应用场景是什么呢点对点模型(Point-to-Point Model): 实用场景:单个音讯只能被一个接收者解决的场景。例如,工作散发零碎、异步申请-响应零碎等。公布/订阅模型(Publish/Subscribe Model): 实用场景:须要将音讯播送给多个订阅者的场景。例如,实时数据推送、事件告诉、日志订阅等。申请/响应模型(Request/Response Model): 实用场景:须要进行申请和响应的场景。例如,客户端与服务器之间的申请-响应交互、RPC(近程过程调用)等。队列模型(Queue Model): 实用场景:须要确保音讯按程序解决的场景,每个音讯只能被一个接收者解决。例如,工作队列、工作流零碎等。扇出/扇入模型(Fan-Out/Fan-In Model): 实用场景:须要将音讯复制给多个不同的接收者的场景。例如,日志记录和剖析零碎、音讯播送等。申请/异步响应模型(Request/Async Response Model): 实用场景:须要异步解决申请并返回响应的场景。例如,长时间运行的工作、异步告诉等。分布式事务模型(Distributed Transaction Model): 实用场景:须要保障多个分布式系统之间的事务一致性的场景。例如,分布式订单解决、分布式领取零碎等。Kafka术语阐明 音讯:Record。Kafka 是音讯引擎嘛,这里的音讯就是指 Kafka 解决的次要对象。主题:Topic。主题是承载音讯的逻辑容器,在理论应用中多用来辨别具体的业务。分区:Partition。一个有序不变的音讯序列。每个主题下能够有多个分区。音讯位移:Offset。示意分区中每条音讯的地位信息,是一个枯燥递增且不变的值。正本:Replica。Kafka 中同一条音讯可能被拷贝到多个中央以提供数据冗余,这些中央就是所谓的正本。正本还分为领导者正本和追随者正本,各自有不同的角色划分。正本是在分区层级下的,即每个分区可配置多个正本实现高可用。生产者:Producer。向主题公布新音讯的应用程序。消费者:Consumer。从主题订阅新音讯的应用程序。消费者位移:Consumer Offset。表征消费者生产进度,每个消费者都有本人的消费者位移。消费者组:Consumer Group。多个消费者实例独特组成的一个组,同时生产多个分区以实现高吞吐。重均衡:Rebalance。消费者组内某个消费者实例挂掉后,其余消费者实例主动重新分配订阅主题分区的过程。Rebalance 是 Kafka消费者端实现高可用的重要伎俩。咱们要留神的几个点 Kafka的正本并不像MySQL那样对外提供服务Kafka的正本(Replicas)和MySQL的正本(Replicas)在性能和设计上有一些不同,因而它们在对外提供服务方面有所不同。 数据复制目标不同:Kafka的正本是为了提供数据冗余和高可用性而设计的,它们用于备份主题的分区数据,以避免数据失落。正本之间的数据同步和复制是Kafka集群的外围机制。而MySQL的正本则是为了提供数据的冗余备份和读取负载平衡而设计的,正本之间通过复制和同步来保证数据的一致性和可用性。数据读写形式不同:Kafka的正本只用于读取数据,不间接对外提供写入服务。生产者将音讯写入主题的分区,而后Kafka集群负责将音讯复制到正本中,以提供冗余和容错能力。消费者能够从任意正本中读取数据,实现高可用性和负载平衡。而MySQL的正本是通过主从复制实现数据的读写拆散,主节点负责写入操作,从节点负责读取操作。数据一致性要求不同:Kafka的正本之间的数据同步是异步进行的,即主题的分区数据在写入主节点后,可能会有一些提早才被复制到正本。这种异步复制形式能够进步Kafka的吞吐量和性能,但可能导致正本之间存在肯定的数据提早。而MySQL的正本之间的数据同步是同步进行的,确保数据在主节点写入后立刻被复制到所有正本,以保证数据的一致性和可用性。Kafka只是一个音讯引擎吗?Kafka通常被形容为一个分布式流解决平台,而不仅仅是一个音讯引擎。只管Kafka的外围性能是音讯引擎,它提供了高性能、牢靠的分布式消息传递,但Kafka还具备其余重要的个性和性能,使其成为一个全面的分布式流解决平台。 如果你通读全篇文字但只能记住一句话,我心愿你记住的就是这句。再强调一遍,Kafka 是音讯引擎零碎,也是分布式流解决平台。 Kafka发展史Kafka的设计历史能够追溯到2010年,过后由LinkedIn的工程师Jay Kreps、Neha Narkhede和Jun Rao共同开发和推出。 起初的需要:在LinkedIn,存在一个须要解决大规模数据流的问题。传统的音讯队列零碎无奈满足其高吞吐量和低提早的需要。因而,JayKreps、Neha Narkhede和Jun Rao决定自行开发一种新的解决方案。我的项目开始:2010年,Kafka我的项目正式启动。最后的指标是构建一个高性能的分布式提交日志零碎,用于LinkedIn外部的数据管道和实时流式解决。公布开源:2011年,LinkedIn将Kafka作为开源我的项目公布,成为Apache软件基金会的孵化我的项目。这使得更多的公司和开发者开始参加和奉献Kafka的倒退。Kafka 0.8版本:2012年,公布了Kafka的第一个重要版本0.8。该版本引入了新的存储层设计,应用分段日志(SegmentedLog)来进步吞吐量和可靠性。此外,0.8版本还引入了新的音讯生产模型(Consumer Model),反对多个消费者组和音讯的长久化存储。Kafka 0.9版本:2015年,公布了Kafka的0.9版本。这是一个重要的里程碑,引入了Kafka的新的消费者API,加强了安全性和可靠性。此外,0.9版本还引入了KafkaConnect和Kafka Streams,使Kafka成为一个全面的流解决平台。Kafka 1.0版本:2017年,公布了Kafka的1.0版本。这是一个重要的稳固版本,引入了许多改良和性能优化。1.0版本还引入了幂等写入和事务反对等重要性能,使Kafka成为更牢靠和全面的分布式流解决平台。自那时以来,Kafka继续倒退和改良,一直减少新的性能和个性。它曾经成为一个宽泛应用的分布式流解决平台,被许多公司和组织用于构建实时数据管道、事件驱动应用程序和大规模数据处理。 言归正传,Kafka 在设计之初就旨在提供三个方面的个性: ...

September 4, 2023 · 2 min · jiezi

关于后端:测试大姐提了个bug为什么你多了个options请求

1 上班前的沉寂刚筹备上班呢,测试大姐又给我提个bug,你看我这就操作了一次,network里咋有两个申请? 我心一惊,”不可能啊!我代码明明就调用一次后端接口,咋可能两个申请!“。关上她的截图一看:多个options申请。 我镇定自若解释道:”这不必管,是浏览器默认发送的一个预检申请“。 可测试大姐如同仍旧很执着:“那这可必定不行啊,明明一次申请,干嘛要两次呢,这不是增大服务端压力吗?” “md,真执著啊,那就不上班了,加个钟给你讲懂!” HTTP申请分为两种: 简略申请非简略申请2 简略申请2.1 条件申请形式:HEAD、GET、POSTheader中只能蕴含以下申请头字段: AcceptAccept-LanguageContent-LanguageContent-Type所指的媒体类型值仅仅限于下列三者之一 text/plainmultipart/form-dataapplication/x-www-form-urlencoded2.2 浏览器的不同解决形式简略申请,若申请跨域,浏览器会放行让申请收回。浏览器会发cors申请,并携带origin。此时不论服务端返回啥,浏览器都会把返回拦挡,并查看返回的response的header中有无Access-Control-Allow-Origin: 这头部信息的值通常为申请的Origin值,示意容许该起源的申请阐明资源是共享的,能够拿到如果Origin头部信息的值为"*"(示意容许来自任何起源的申请)但这种状况下须要审慎应用,因为它存在安全隐患如没有这个头信息,阐明服务端没有开启资源共享,浏览器会认为这次申请失败终止这次申请,并且报错。3 非简略申请只有不满足简略申请的条件,都是非简略申请。 收回非简略cors申请,浏览器会做一个http的查问申请(预检申请)即options。options申请会依照简略申请来解决。 为啥要做一次options申请?查看服务器是否反对跨域申请,并确认理论申请的安全性。预检申请是为爱护客户端的平安,避免不受信赖网站利用用户浏览器向其余网站发歹意申请。 预检申请头中除了携带了origin字段还蕴含两个非凡字段: Access-Control-Request-Method: 告知服务器理论申请应用的HTTP办法Access-Control-Request-Headers:告知服务器理论申请所携带的自定义首部字段如: OPTIONS /resources/post-here/ HTTP/1.1Host: bar.otherAccept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8Accept-Language: en-us,en;q=0.5Accept-Encoding: gzip,deflateAccept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7Connection: keep-aliveOrigin: http://foo.exampleAccess-Control-Request-Method: POSTAccess-Control-Request-Headers: X-PINGOTHER, Content-Type以上报文中就能够看到,应用OPTIONS申请,浏览器依据下面的应用的申请参数来决定是否须要发送,这样服务器就能够回应是否能够承受用理论的申请参数来发送申请。 -Access-Control-Request-Method告知服务器,理论申请将应用 POST 办法 Access-Control-Request-Headers告知服务器,理论申请将携带两个自定义申请标头字段:X-PINGOTHER 与 Content-Type。服务器据此决定,该理论申请是否被容许。 啥时触发预检申请?发送跨域申请时,申请头中蕴含了一些非简略申请的头信息,如自定义头(custom header)发送跨域申请时,应用了 PUT、DELETE、CONNECT、OPTIONS、TRACE、PATCH等申请办法“大姐你听懂了吗?所以这不是 bug,连忙把它关掉吧!” 大姐漏出了澄澈的眼光,好吧 4 上案例 这下测试大姐终于将信将疑地敞开了Bug。 5 如果世上没有测试大姐我说如果啊!你的测试老大姐就是说:我不懂你说的这些,我不论,反正我当初想看到的是在浏览器外面只有一次网络申请,你本人看着办吧,bug 我留在这了,你本人解决! 爱!浏览器厂商为了保障安全性,禁止了跨域,可最终还是程序员接受了所有优化的代价! 本文由博客一文多发平台 OpenWrite 公布!

September 4, 2023 · 1 min · jiezi

关于后端:电商类面试问题02针对商品排行榜你是怎么实现的

02-针对商品排行榜,你是怎么实现的背景形容过后产品提出了每日热销排行榜在零点进行变更的需要。在我接到这个需要后,我立刻想到了应用Redis的有序汇合(ZSET)来实现这个性能,并与咱们的技术负责人进行了沟通。 通过与技术负责人的探讨和确认,咱们统一认为应用有序汇合是一个可行的解决方案。因而,我进行了技术评审,并失去了批准开始施行该计划。 在实现过程中,我应用了Redis的有序汇合数据结构来存储和排序商品销量信息。具体而言,我将日期作为有序汇合的key,商品ID作为成员(member),销售数量作为分值(score)。每当有订单数据更新时,我通过调用ZINCRBY命令来减少对应商品的销售数量。这样,在每天零点之前,所有的订单数据会被累积到有序汇合中。 至于定时更新排行榜数据的性能,我采纳了Spring Boot提供的定时工作注解(@Scheduled)来指定每天零点执行更新操作。在定时工作中,我首先删除前一天的排行榜数据,而后依据最新的订单数据从新生成排行榜。 代码实现// 记录订单数据public void recordOrderData(String date, String productId, int quantity) { // 更新有序汇合中对应商品的销售数量 redisTemplate.opsForZSet().incrementScore("daily_ranking_" + date, productId, quantity);}// 查问每日商品销量排行榜public List<String> getDailyRanking(String date, int topN) { // 获取分值最高的成员,即销量最高的商品ID Set<String> members = redisTemplate.opsForZSet().reverseRange("daily_ranking_" + date, 0, topN - 1); return new ArrayList<>(members);}// 定时工作更新排行榜数据(程序员fly)@Scheduled(cron = "0 0 0 * * ?") // 每天零点执行public void updateDailyRanking() { String date = LocalDate.now().minusDays(1).format(DateTimeFormatter.ofPattern("yyyyMMdd")); // 昨天的日期 String today = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd")); // 明天的日期 // 革除前一天的排行榜数据 redisTemplate.delete("daily_ranking_" + date); // 依据最新的订单数据从新生成排行榜(程序员fly) // 假如从数据库或缓存中获取当日的订单数据,并依据订单数据更新有序汇合的分值 List<Order> orders = orderService.getOrdersByDate(today); for (Order order : orders) { String productId = order.getProductId(); int quantity = order.getQuantity(); recordOrderData(today, productId, quantity); }}上述代码示例中,在实现每日热销排行榜的性能时,应用了Redis有序汇合来存储和排序商品销量信息。对应的办法包含: ...

September 4, 2023 · 1 min · jiezi

关于后端:TuGraph-Analytics图计算快速上手之Kcore算法

作者:郑光杰 引言K-Core算法是一种用来在图中找出合乎指定外围度的严密关联的子图构造,在K-Core的后果子图中,每个顶点至多具备k的度数,且所有顶点都至多与该子图中的 k 个其余节点相连。K-Core通常用来对一个图进行子图划分,通过去除不重要的顶点,将合乎逾期的子图裸露进去进行进一步剖析。K-Core图算法罕用来辨认和提取图中的严密连通群组,因具备较低的工夫复杂度(线性)及较好的直观可解释性,广泛应用于金融风控、社交网络和生物学等钻研畛域。 K-Core算法介绍一张图的 K-Core子图是指从图中重复去掉度(不思考自环边)小于 k 的节点之后失去的子图。该计算过程是一个重复迭代剪枝的过程,在某一轮剪枝之前度大于等于 k 的节点,可能会在该轮剪枝后变为度小于 k。比方3-core子图的切分过程如图1所示: 3-core子图切分过程 TuGraph-Analytics实现K-Core算法要运行K-Core算法,咱们能够指定应用的图,间接在图查问里调用K-Core算法,语法模式如下: INSERT INTO tbl_resultCALL kcore(3) YIELD (id, value)RETURN id, value;运行该语法之后,就能够从图中查问到k=3的子图的id以及该id的街坊数。TuGraph-Analytics 曾经内置了许多算法,如果想要自定义算法,能够基于AlgorithmUserFunction接口实现,比方自定义k-core 算法实现如下: package com.tugraph.demo;import com.antgroup.geaflow.common.type.primitive.IntegerType;import com.antgroup.geaflow.dsl.common.algo.AlgorithmRuntimeContext;import com.antgroup.geaflow.dsl.common.algo.AlgorithmUserFunction;import com.antgroup.geaflow.dsl.common.data.RowEdge;import com.antgroup.geaflow.dsl.common.data.RowVertex;import com.antgroup.geaflow.dsl.common.data.impl.ObjectRow;import com.antgroup.geaflow.dsl.common.function.Description;import com.antgroup.geaflow.dsl.common.types.StructType;import com.antgroup.geaflow.dsl.common.types.TableField;import com.antgroup.geaflow.model.graph.edge.EdgeDirection;import java.util.Iterator;import java.util.List;@Description(name = "kcore", description = "built-in udga for KCore")public class KCore implements AlgorithmUserFunction<Object, Integer> { private AlgorithmRuntimeContext<Object, Integer> context; private int k = 1; @Override public void init(AlgorithmRuntimeContext<Object, Integer> context, Object[] params) { this.context = context; if (params.length > 1) { throw new IllegalArgumentException( "Only support zero or more arguments, false arguments " + "usage: func([alpha, [convergence, [max_iteration]]])"); } // 设置k值,默认k=1 if (params.length > 0) { k = Integer.parseInt(String.valueOf(params[0])); } } @Override public void process(RowVertex vertex, Iterator<Integer> messages) { boolean isFinish = false; //第一轮迭代将所有顶点初始化,指标点的value值初始化为-1,并向邻点发送音讯 if (this.context.getCurrentIterationId() == 1) { this.context.updateVertexValue(ObjectRow.create(-1)); } else { // v = 0,则示意须要删除 int currentV = (int) vertex.getValue().getField(0, IntegerType.INSTANCE); if (currentV == 0) { return; } // 计算点的输出音讯数 int sum = 0; while (messages.hasNext()) { sum += messages.next(); } // 如果点接管的音讯数小于k的则须要删除 if (sum < k) { isFinish = true; sum = 0; } // 更新以后点的值为接管音讯数 context.updateVertexValue(ObjectRow.create(sum)); } if (isFinish) { return; } // 向点的街坊发送音讯 List<RowEdge> outEdges = this.context.loadEdges(EdgeDirection.OUT); for (RowEdge rowEdge : outEdges) { context.sendMessage(rowEdge.getTargetId(), 1); } List<RowEdge> inEdges = this.context.loadEdges(EdgeDirection.IN); for (RowEdge rowEdge : inEdges) { context.sendMessage(rowEdge.getTargetId(), 1); } // 向本点送音讯,避免该点因没有音讯不会触发下次迭代 context.sendMessage(vertex.getId(), 0); } @Override public StructType getOutputType() { return new StructType( new TableField("id", IntegerType.INSTANCE, false), new TableField("v", IntegerType.INSTANCE, false) ); }}TuGraph-Analytics运行K-Core算法图定义如果想要在dsl中运行k-core算法,咱们能够第一步先进行图定义,比方: ...

September 4, 2023 · 2 min · jiezi

关于后端:MySQL的Json类型个人用法详解

前言尽管MySQL很早就增加了Json类型,然而在业务开发过程中还是很少设计带这种类型的表。少不代表没有,当真正要对Json类型进行特定查问,批改,插入和优化等操作时,却感觉一下子想不起那些函数怎么应用。比方把json里的某个键和值作为SQL条件,批改某个键下的子键的值,其中可能会遇到数组模式的Json或者键名是字符串的数字批改异样等问题。那么,以下是小北在业务中常遇到的Json类型操作汇总了。  查问1. 查问一般键以下示例是从goods表的price字段里取出price键的值,能够顺次往下取值,就是price.嵌套键名即可。 select json_extract(price, "$.price") as de from goods where id = 1595402. 2. 查问字符串类型的数字键尽管以上能解决大部分取值,但有时候的json嵌套里有字符串类型的数字键名,如下图的json,要取出字段下sku键名的 "45453"键algorithm的值。 select json_extract(price, "$.sku.\"45453\".algorithm") as de from price where id = 1595403. 3. 查问数组类的Json指定值以上的两种是咱们常见的对象类,但当呈现数组类时,就没有键名了,取值只须要指定索引即可,如下别离是查问某值和依据json的某值作为查问条件。 select JSON_EXTRACT(`crumbs`, $[1]) as one_crumbs from comment where id = 4565select * from comment where JSON_EXTRACT(`crumbs` ,'$[1]') = 2564. 4. 查问Json里是否蕴含某个值select * from goods_item where goods_id=10263 and JSON_CONTAINS(item_value->'$', concat(43318,''));select * from goods_item where goods_id=10263 and JSON_CONTAINS(item_value, concat(43318,''));select * from goods_item where goods_id=10263 and JSON_CONTAINS(item_value, concat(43318,''),'$');5. 查问Json长度以下的goods_img是一个数组类的Json字段,通过长度作为SQL的查问条件。 ...

September 4, 2023 · 1 min · jiezi

关于后端:git一些撤销操作

参考自 如何撤销 Git 操作? 一、撤销提交 git revert HEAD 撤销上次提交. (会在以后提交前面,新增一次提交,对消掉上一次提交导致的所有变动,所有记录都会保留) 二、撤销某次merge git merge --abort 三、替换上一次提交 git commit --amend -m "新的提交信息" 能够批改上一次的提交信息 四、从暂存区撤销文件 如果不小心应用了git add命令, 把一个文件本不想增加到暂存区的文件加到了暂存区,可用上面的命令撤销 git rm --cached [filename] 更多: Git的撤销和回滚命令总结 复原GIT不同区域的批改 本文由mdnice多平台公布

September 4, 2023 · 1 min · jiezi

关于后端:海明校验码

二进制数据在 传送、存取等环节,可能会产生 误码(1变成0或0变成1). 如何发现并纠正 误码? 解决此类问题的思路是在原始数据(数码位)根底上减少几位校验位。常应用的检验码有三种. 别离是 奇偶校验码、海明校验码和循环冗余校验码(CRC)") 其中 奇偶校验码 只能查是否有谬误而无奈纠错,且要求只能有一位呈现谬误。 为了能找到产生谬误的地位,而有了 海明校验码 <font size=1 color="#3CB371"> 实际上实质来说, 海明码是降级款的奇偶校验码,其采纳了一种十分奇妙的形式,把这串数字(即要传输的内容)分了组,通过分组校验来确定哪一位呈现了谬误 相似KMP算法,形容起来很麻烦,实际上应用起来却很简略 "海明"也被译为"汉明" </font> 实例 数据位为8的数据 $D_7D_6D_5D_4D_3D_2D_1D_0=01101001$,求海明码 1.计算校验位的个数 设数据位为n位,校验位P为k位,则n和k必须满足以下关系: $$2^k - 1 ≥ n + k$$ 此例中有 $2^k - 1 ≥ 8 + k$,可得k最小应为4,即 16 - 1 ≥ 8 + 4。 (奇偶校验称为 Parity Check,Parity Bit即奇偶校验位,故用P示意校验位) 2.计算校验位的地位 2.1 海明码的总位数 设校验位为P,数据位为D,海明码为H,则海明码H的位数为数据的位数和校验码的位数相加, 在此即为 8+4 = 12 位 2.2 校验码的地位 ...

September 4, 2023 · 1 min · jiezi

关于后端:买卖股票的数据结构-订单簿

交易股票的数据结构 - 订单簿最近股票市场很冷落啊,你晓得买单和卖单是如何匹配的吗? 证券交易所应用的数据结构称为订单簿 (Order Book)。订单簿是按价格排列的订单队列。它有一个买入簿和一个卖出簿,匹配时依照先进先出 (First In First Out)的准则。 下图是一个简略的订单簿数据结构示意图。 咱们联合图来看一个例子。如果买入 2700 股的市价单,会产生什么状况呢? 该买入订单与价格为 100.10 的所有卖出订单以及价格为 100.11 的第一笔订单(以浅红色显示)相匹配。当初,因为大买单 “吃掉 ”了卖出簿上的第一个价位,最佳卖出价从 100.10 升至 100.11。因而,当市场看涨时,人们偏向于买入股票,价格就会一涨再涨。订单簿的高效数据结构必须满足以下条件: 恒定的查问工夫。操作包含:获取某一价位或两个价位之间的成交量查问最佳买入价/卖出价。疾速增加/勾销/执行/更新操作,工夫复杂度最好为 O(1)。操作包含:下新订单勾销订单匹配订单欢送点赞留言提出你的宝贵意见! 【图解架构设计,关注公众号:ByteByteGo】

September 4, 2023 · 1 min · jiezi

关于后端:springboot-vue户外论坛系统含springboot版本spring-jpa版本vue前端版

 博主介绍:✌退职Java研发工程师、专一于程序设计、源码分享、技术交换、专一于Java技术畛域和毕业设计✌舒适提醒:文末有 CSDN 平台官网提供的老师 Wechat / QQ 名片 :) 项目名称 springboot vue户外论坛零碎(含springboot版本、spring jpa版本、vue前端版本、vue手机端版本) 演示视频 springboot vue户外论坛零碎(含springboot版本、spring jpa版本、vue前端版本、vue手机端版本)_哔哩哔哩_bilibili 零碎介绍 零碎架构:Spring Boot + JPA+mysql前端Vue3 + element-plus 管理员后盾地址为 http://localhost:8080/admin/login管理员初始账号admin 明码123456 用户zhansanzhansan 批改明码createEncryptionDatabaseParameter 零碎截图 编辑 编辑 编辑 编辑 编辑 编辑 编辑 编辑 编辑 编辑 编辑 编辑 编辑 编辑 编辑 编辑 编辑 编辑 编辑 编辑 编辑 编辑 编辑 编辑 编辑 编辑 编辑 编辑 编辑 编辑 编辑 编辑 编辑 编辑 编辑 编辑 编辑 编辑 编辑 编辑 ...

September 4, 2023 · 5 min · jiezi

关于后端:面试题精讲什么是websocket如何与前端通信

有的时候博客内容会有变动,首发博客是最新的,其余博客地址可能会未同步,认准https://blog.zysicyj.top首发博客地址 系列文章地址 什么是WebSocket?WebSocket是一种在Web应用程序中实现双向通信的协定。它容许在客户端和服务器之间建设长久的、全双工的连贯,以便实时地发送数据。 传统的HTTP协定是一种无状态的申请-响应协定,客户端发送申请,服务器返回响应,而后连贯立刻敞开。这种模型实用于大多数Web应用程序,但对于须要实时数据更新或双向通信的应用程序来说,它并不现实。 WebSocket通过在客户端和服务器之间建设短暂的TCP连贯,提供了一种持久性的通信通道。它通过在HTTP握手过程中降级连贯,从而容许在同一个连贯上进行双向通信。 WebSocket的特点包含: 双向通信:WebSocket容许客户端和服务器之间双向发送数据,而不仅仅是客户端向服务器发送申请。实时性:WebSocket提供了高效的实时数据传输,能够在数据可用时立刻将其推送给客户端。较低的开销:WebSocket应用较少的网络开销,因为它应用长久连贯而不须要频繁的握手和头部信息。兼容性:WebSocket协定曾经失去了宽泛的反对,古代的Web浏览器和服务器都能够很好地反对WebSocket。WebSocket在许多实时应用程序中失去广泛应用,例如聊天应用程序、实时合作工具、股票市场报价、多人游戏等。它提供了一种弱小的机制,使得开发者能够轻松实现实时和双向的Web应用程序。 Spring Boot如何实现WebSocket在Spring Boot中,能够应用Spring WebSocket模块来实现WebSocket性能。以下是应用Spring Boot实现WebSocket的根本步骤: 增加依赖:在pom.xml文件中增加以下依赖,以引入Spring WebSocket和Tomcat WebSocket的反对:<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId></dependency><dependency><groupId>org.apache.tomcat.embed</groupId><artifactId>tomcat-embed-websocket</artifactId></dependency>创立一个WebSocket处理器类:创立一个类,实现org.springframework.web.socket.handler.TextWebSocketHandler,并重写handleTextMessage和afterConnectionEstablished等办法来解决WebSocket事件。import org.springframework.web.socket.TextMessage;import org.springframework.web.socket.WebSocketSession;import org.springframework.web.socket.handler.TextWebSocketHandler;public class MyWebSocketHandler extends TextWebSocketHandler { @Override protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception { // 解决收到的文本音讯 } @Override public void afterConnectionEstablished(WebSocketSession session) throws Exception { // 解决连贯建设事件 }}配置WebSocket端点:创立一个配置类,继承自org.springframework.web.socket.config.annotation.WebSocketConfigurer,并重写registerWebSocketHandlers办法来注册WebSocket处理器和端点。import org.springframework.context.annotation.Configuration;import org.springframework.web.socket.config.annotation.EnableWebSocket;import org.springframework.web.socket.config.annotation.WebSocketConfigurer;import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;@Configuration@EnableWebSocketpublic class WebSocketConfig implements WebSocketConfigurer { @Override public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { registry.addHandler(new MyWebSocketHandler(), "/websocket").setAllowedOrigins("*"); }}启动应用程序:编写一个Spring Boot启动类,并增加@SpringBootApplication注解来启动应用程序。import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplicationpublic class MyApplication { public static void main(String[] args) { SpringApplication.run(MyApplication.class, args); }}通过这些步骤,您能够在Spring Boot中实现WebSocket性能。客户端能够应用JavaScript的WebSocket对象或其余WebSocket客户端库来连贯到您的WebSocket端点。 ...

September 4, 2023 · 1 min · jiezi

关于后端:SQL-查询的执行顺序

by emanjusaka from https://www.emanjusaka.top/archives/6 彼岸花开可奈何 本文欢送分享与聚合,全文转载请留下原文地址。前言理解 SQL 查问的执行程序对咱们解决一些问题很有帮忙,有时咱们可能会纳闷为什么不能对分组的后果进行筛选这样相似的问题?之前始终不是了解这个问题,在理解了SQL 查问的执行程序之后这个问题也就迎刃而解。在咱们对 SQL 查问语句进行剖析优化时,把握执行程序也是有肯定帮忙的。 一、实践程序 下面是图示 SQL 的执行程序,上面用列表列出: FROMONJOINWHEREGROUP BYCUBE | ROLLUPHAVINGSELECTDISTINCTORDER BYLIMIT下面所列出的执行程序能帮忙咱们解答一些问题: 为啥不能对窗口函数的执行后果进行过滤? 因为窗口函数在 SELECT 步骤执行,而这步是在 WHERE 和 GROUP BY 之后 能够对分组的后果进行筛选吗? 不能够,因为 GROUP BY 在 WHERE 之后执行 能够对分组后的后果进行排序吗? 能够,因为 ORDER BY 在 GROUP BY 之后。 二、代码示例学生表 <!----> 成绩表 <!----> 查问语句 查问来自天津且总成绩高于70分,并且查问他们的总成绩,查问后果按问题降序排列 SELECT ss.student_id,sum(se.grade) as total,ss.cityFROM students ss LEFT JOIN score se ON ss.student_id = se.student_id WHERE ss.city = "天津"GROUP BY ss.student_idHAVING sum(se.grade) > 70ORDER BY total DESCLIMIT 10<!----> ...

September 4, 2023 · 2 min · jiezi

关于后端:Nacos-注册中心的设计原理让你的应用轻松实现高效注册与发现

当利用开始脱离单机运行和拜访时,服务发现就诞生了。目前的网络架构是每个主机都有⼀个独立的 IP 地址,服务发现根本都是通过某种形式获取到服务所部署的 IP 地址。 DNS 协定是最早将⼀个网络名称翻译为网络 IP 的协定,在最后的架构选型中,DNS+LVS+Nginx 根本满足所有 RESTful 服务的发现,此时服务的 IP 列表通常配置在 nginx 或 LVS。起初呈现 RPC 服务,服务的高低线更加频繁,人们开始寻求⼀种可能反对动静高低线并且推送 IP 列表变动的注册核心产品。 互联网软件行业广泛热捧开源产品,因为开源产品代码通明、能够参加共建、有社区进行交换和学习,当然更重要是收费。集体开发者或者中小型公司往往会将开源产品作为选型首选。 1 开源产品1.1 Zookeeper经典服务注册核心产品(尽管它最后的定位并不在于此),在很长⼀段时间里,是国人在提起 RPC 服务注册核心时心里想到的唯⼀抉择,这很大水平上与 Dubbo 在中国的遍及水平无关。 1.2 Consul 和 Eureka都呈现于 2014 年: Consul 在设计上把很多分布式服务治理上要用到的性能都蕴含在内,能够反对服务注册、健康检查、配置管理、Service Mesh 等Eureka借微服务概念风行,与 SpringCloud 生态的深度联合,也获取了大量的用户1.3 Nacos则携带着阿里巴巴大规模服务生产教训,试图在服务注册和配置管理这个市场上,提供给用户⼀个新的抉择。 图 1 服务发现: 1.4 开源产品的劣势开发人员能够去浏览源代码,了解产品的功能设计和架构设计,同时也能够通过本地部署来测试性能,随之而来的是各种产品的比照文章。 不过以后对于注册核心的比照,往往停留在外表的性能比照上,对架构或者性能并没深入探讨。 1.5 痛点是服务注册核心往往暗藏在服务框架背地,作为默默反对的产品。优良的服务框架往往反对多种配置核心,然而注册核心的抉择仍然强关联与服务框架,⼀种广泛的状况是⼀种服务框架会带⼀个默认的服务注册核心。这样尽管免去了用户在选型上的懊恼,然而单个注册核心的局限性,导致用户应用多个服务框架时,必须部署多套齐全不同的注册核心,这些注册核心之间的数据协同也是⼀个问题。 本文从各个角度深度介绍 Nacos 注册核心的设计原理,并试图从咱们的教训和调研中总结和论述服务注册核心产品设计上应该去遵循和思考的要点。 2 数据模型注册核心的外围数据: 服务的名字它对应的网络地址当服务注册了多个实例时,咱们须要对不衰弱的实例过滤或针对实例的⼀些特色进行流量调配,就须要在实例存储⼀些如衰弱状态、权重等属性。随服务规模扩充,慢慢的又须要在整个服务级别设定⼀些权限规定、以及对所有实例都失效的⼀些开关,于是在服务级别又会设立⼀些属性。再往后,咱们又发现单个服务的实例又会有划分为多个子集的需要,例如⼀个服务是多机房部署的,那么可能须要对每个机房的实例做不同的配置,这样又须要在服务和实例之间再设定⼀个数据级别。 比照Zookeeper 没有针对服务发现设计数据模型,它的数据是以⼀种更加形象的树形 K-V 组织的,因而实践上能够存储任何语义的数据Eureka 或者 Consul 都做到实例级的数据扩大,可满足大部分的场景,不过无奈满足大规模和多环境的服务数据存储Nacos 在通过外部多年生产教训后提炼出的数据模型,则是⼀种服务-集群-实例的三层模型。根本满足服务在所有场景下的数据存储和治理。 Nacos 的数据模型尽管绝对简单,但它不强制你应用它外面的所有数据,在大多数场景下,你能够抉择疏忽这些数据属性,此时可降维成和 Eureka 和 Consul ⼀样的数据模型。 ...

September 3, 2023 · 1 min · jiezi

关于后端:详解配置文件系列es7配置文件详解

首发博客地址 系列文章地址 配置文件# ---------------------------------- Cluster -----------------------------------cluster.name: my-cluster# 集群的名称node.name: node-1# 节点的名称node.master: true# 是否容许节点成为主节点(默认为 true)node.data: true# 是否容许节点存储数据(默认为 true)# ----------------------------------- Paths ------------------------------------path.data: /path/to/data# 数据文件的存储门路path.logs: /path/to/logs# 日志文件的存储门路# ---------------------------------- Network -----------------------------------network.host: 0.0.0.0# 监听的网络接口地址(默认为 0.0.0.0,即监听所有接口)http.port: 9200# HTTP 通信应用的端口号(默认为 9200)transport.tcp.port: 9300# 节点间通信应用的 TCP 端口号(默认为 9300)# --------------------------------- Discovery ----------------------------------discovery.seed_hosts: [ "host1", "host2" ]# 发现初始主机节点的地址列表,用于集群主动发现cluster.initial_master_nodes: [ "node-1", "node-2" ]# 初始主节点列表,用于集群主动发现# ---------------------------------- Gateway -----------------------------------gateway.recover_after_nodes: 3# 节点数达到指定数量后,才开始复原数据(默认为 3)gateway.expected_nodes: 5# 预期的节点数量,用于复原数据(默认为 5)# ---------------------------------- Memory ------------------------------------bootstrap.memory_lock: true# 是否锁定 Elasticsearch 过程的内存(须要设置文件系统权限)# ---------------------------------- Various -----------------------------------action.destructive_requires_name: true# 在执行危险操作(如删除索引)时,须要显式指定操作名称(默认为 true)# ---------------------------------- Security ----------------------------------xpack.security.enabled: true# 是否启用 X-Pack 平安性能(默认为 false)xpack.security.authc.api_key.enabled: true# 是否启用 API 密钥认证(默认为 false)# ---------------------------------- Logging ----------------------------------logger.org.elasticsearch.transport: debug# 日志级别设置(可选:trace, debug, info, warn, error, fatal)cluster.namecluster.name是 Elasticsearch 配置文件中的一个重要选项,用于指定集群的名称。每个运行的 Elasticsearch 实例都必须具备雷同的集群名称能力退出同一个集群。 ...

September 3, 2023 · 2 min · jiezi

关于后端:面试题精讲Java-Stream排序的实现方式

首发博客地址 系列文章地址 如何应用Java Stream进行排序在Java中,应用Stream进行排序能够通过sorted()办法来实现。sorted()办法用于对Stream中的元素进行排序操作。具体实现如下: 对根本类型元素的排序: 应用sorted()办法对Stream进行排序,默认是依照天然程序进行排序。例如,对一个Stream<Integer>进行排序能够如下操作: Stream<Integer> stream = Arrays.stream(new Integer[] {3, 1, 2});Stream<Integer> sortedStream = stream.sorted();sortedStream.forEach(System.out::println);输入后果是:1, 2, 3。 如果想要依照特定的程序进行排序,能够应用sorted(Comparator)办法,并传入一个自定义的比拟器。例如,对一个Stream<String>依照长度进行排序能够如下操作: Stream<String> stream = Stream.of("apple", "banana", "cherry");Stream<String> sortedStream = stream.sorted(Comparator.comparingInt(String::length));sortedStream.forEach(System.out::println);输入后果是:apple, cherry, banana。 对自定义对象的排序: 对于自定义对象,能够通过实现Comparable接口来定义对象的天然排序形式。而后,在sorted()办法中间接调用,就会依照天然排序进行排序。如果想要依照其余形式进行排序,能够应用sorted(Comparator)办法,并传入一个自定义的比拟器。 public class Person implements Comparable<Person> { private String name; private int age; // 省略构造方法和其余代码 @Override public int compareTo(Person other) { return Integer.compare(this.age, other.age); }}// 应用天然排序形式Stream<Person> stream = persons.stream();Stream<Person> sortedStream = stream.sorted();sortedStream.forEach(System.out::println);// 应用自定义比拟器进行排序Stream<Person> stream = persons.stream();Stream<Person> sortedStream = stream.sorted(Comparator.comparingInt(Person::getAge));sortedStream.forEach(System.out::println);以上就是应用Java Stream进行排序的根本实现形式。能够依据具体的排序需要,抉择适合的排序办法和比拟器。 ...

September 3, 2023 · 1 min · jiezi

关于后端:电商类面试问题01Elasticsearch与Mysql数据同步问题

在实现基于关键字的搜寻时,首先须要确保MySQL数据库和ES库中的数据是同步的。为了解决这个问题,能够思考两层计划。 全量同步:全量同步是在服务初始化阶段将MySQL中的数据与ES库中的数据进行全量同步。能够在服务启动时,对ES库进行全量数据同步操作,以确保数据的一致性。而在进行服务时,能够清空ES的缓存库,以便下次启动服务时进行全量同步。增量同步:为了实现热同步,即在不重启服务的状况下保持数据的同步,能够应用增量同步来解决新的或批改过的数据。有几种增量同步的实现形式可供选择。同步双写:最后的计划是通过同步双写的形式,在MySQL中有数据插入或批改时,同时对ES中的数据进行同步更新或插入。然而,因为这种形式会导致代码的耦合性较高,这是个劣势,面试能够点一下。异步双写:为了解决代码耦合性的问题,引入了RabbitMQ作为中间件。在数据写入ES之前,数据先被发送到RabbitMQ中,而后RabbitMQ生产数据并将其写入ES。如果写入失败,能够采取熔断降级策略,将数据发送到死信队列,并进行重试,直到胜利写入ES为止。尽管这种形式可能会存在一些延时,但绝对于保证数据一致性而言,是能够容忍的。优化计划: 为了进一步优化数据同步的性能和可靠性,还能够思考了以下计划: 批量同步:将多条记录批量写入ES,而不是每条记录都发送一次申请,能够缩小网络开销并进步写入性能。并发同步:应用多线程或异步工作来并行处理同步操作,从而进步同步速度和吞吐量。数据过滤:依据需要过滤须要同步的数据,防止同步无关的数据,缩小同步工作量和资源耗费。监控和重试机制:实现监控和报警机制,及时发现同步异样或失败,并进行相应的重试或错误处理。另外,还思考到每次敞开和重启服务时全量同步工夫逐步增长的问题。 解决方案是设置两个ES服务器正本。一个服务器(A节点)始终进行同量写入,并将数据同时写入主节点(A节点)和备份节点(B节点)。当须要降级A节点时,能够切换申请到B节点,暂停A节点的服务进行降级,而B节点持续提供服务。这样就实现了数据的无缝连接,在不须要大量同步工夫的状况下实现搜寻服务的执行。待A节点实现降级后,再将其与B节点进行数据同步,而后切回A节点。 通过上述优化措施,能够进一步提高数据同步的性能、效率和可靠性。

September 3, 2023 · 1 min · jiezi

关于后端:单调栈

枯燥栈是一种非凡的数据结构,它由栈内元素形成枯燥递增或枯燥递加的个性。具体来说,对于枯燥递增栈,栈内元素从栈底到栈顶枯燥递增;对于枯燥递加栈,栈内元素从栈底到栈顶枯燥递加。 枯燥栈的利用十分宽泛,包含字符串匹配、门路寻找、序列比对等场景。 例如,在字符串匹配中,咱们能够应用枯燥栈来优化暴力匹配算法。具体来说,咱们应用枯燥递加栈存储文本串中尚未匹配的字符,保障栈底是文本串中最早呈现的尚未匹配的字符。而后,对于模式串中的每个字符,咱们顺次与栈顶元素进行匹配。如果匹配胜利,则将该字符压入栈中;如果匹配失败,则将栈顶元素弹出,相当于将该字符“疏忽”。通过这种形式,咱们能够疾速找到模式串在文本串中的所有呈现地位。 除了字符串匹配,枯燥栈还能够利用于其余场景。例如,在门路寻找问题中,咱们能够应用枯燥递增栈来存储每个节点的后继节点。具体来说,咱们将以后节点的后继节点顺次压入栈中,并保障栈内元素依照达到以后节点的间隔进行排序。而后,对于每个新达到的节点,咱们能够从栈顶找到间隔该节点最近的先人节点,并以此为终点持续搜寻。通过这种形式,咱们能够疾速找到从终点到起点的最短门路。 总之,枯燥栈是一种十分实用的数据结构,它能够广泛应用于各种场景。枯燥栈是一种非凡的数据结构,用于解决一些特定的问题。以下是应用Java实现枯燥栈的示例代码: java复制代码 import java.util.ArrayList; import java.util.Stack; public class MonotonicStack { private Stack<Integer> stack; private Stack<Integer> maxStack; public MonotonicStack() { stack = new Stack<>(); maxStack = new Stack<>(); } public void push(int val) { if (val >= stack.peek()) { stack.push(val); } else { while (!maxStack.isEmpty() && val > maxStack.peek()) { maxStack.pop(); } stack.push(val); maxStack.push(val); } } public int pop() { if (!stack.isEmpty()) { return stack.pop(); } else { return -1; } } public int top() { if (!stack.isEmpty()) { return stack.peek(); } else { return -1; } } public boolean isEmpty() { return stack.isEmpty(); } }在下面的代码中,咱们应用了两个栈,stack 用于存储一般元素,maxStack 用于存储最大元素。在 push() 办法中,咱们首先判断要插入的元素是否大于等于栈顶元素,如果是,则间接将其压入 stack 中;否则,咱们将从 maxStack 中弹出比以后元素小的元素,直到找到一个比以后元素大的元素或 maxStack 为空。而后将以后元素压入 stack 中,并压入 maxStack 中。在 pop() 和 top() 办法中,咱们间接从 stack 中弹出或返回栈顶元素。在 isEmpty() 办法中,咱们判断 stack 是否为空。 ...

September 3, 2023 · 1 min · jiezi

关于后端:10分钟搞懂缓存设计策略

在设计缓存零碎时须要思考不同缓存策略的优缺点和实用场景,通过理解和利用这些策略,能够优化缓存零碎的性能和效率。原文: 6-Caching Strategies to Remember while designing Cache System前言缓存的指标是缩小从原始数据源获取数据的次数,从而放慢处理速度并缩小提早。 缓存能够在不同体系架构级别上实现,包含内存缓存、磁盘缓存、数据库缓存和CDN缓存。 能够用不同的技术缓存数据,每种技术都有其优缺点。比方内存缓存将数据存储在计算机主内存中,与磁盘缓存相比,能够实现更快的访问速度。 另一方面,磁盘缓存将数据存储在硬盘上,速度比内存慢,但绝对拜访近程数据源的速度还是要快得多。 应用数据库缓存,将频繁拜访的数据存储在数据库中,从而缩小从内部存储检索数据的须要。 最初,CDN缓存将数据存储在分布式服务网络中,从而缩小拜访近程数据的时延。 目录缓存零碎要害性能指标读密集型利用缓存写密集型利用缓存缓存生效办法论断缓存零碎要害性能指标为了进步缓存零碎的效率和性能,十分重要的一点是须要监控各种指标,从而依据指标做出无关缓存零碎的重要业务决策。 须要思考的参数有: 缓存命中率: 该指标掂量申请项在缓存中被找到次数的百分比。较高的缓存命中率意味着缓存能够提供更多数据,从而缩小拜访内部存储并进步性能。时延: 时延是指拜访数据所需工夫。在缓存零碎中,较低的时延意味着数据服务速度更快,从而进步整体性能。吞吐量: 吞吐量度量在给定工夫范畴内能够解决的数据量。高吞吐量的缓存零碎能够解决更多申请,提供更多数据,从而进步整体性能。缓存大小: 缓存大小是为缓存调配的内存或存储的容量。缓存大小会影响缓存命中率,较大的缓存能够进步命中率,但也会减少缓存解决方案的老本和复杂性。缓存未命中率: 此指标度量申请项在缓存中找不到并且须要从内部存储中获取的次数百分比。高缓存未命中率意味着须要从内部存储获取更多数据,从而对性能造成影响。如果始终监控这些性能指标,就能够据此优化缓存零碎,以取得更高的吞吐量和更低的时延。 读密集型利用缓存读密集型利用(如Wordpress/动态图像网站)须要设计缓存零碎,以反对更多的读缓存。 上面是一些有用的办法: Cache-asideCache-throughRefresh-ahead1. Cache-Aside Cache-aside办法是最罕用的缓存策略之一。 办法 每当利用发送申请,首先查看缓存中是否有申请的数据。如果有,返回缓存的数据。否则,应用程序从数据库查问数据,并在返回途中更新缓存,而后返回数据。优缺点 每次缓存未命中都会导致三次拜访,可能会造成显著的时延。如果有人更新数据库而不写入缓存,可能会读到过期数据。(因而,Cache-aside通常与其余策略一起应用)。2. Read-through 在read-through办法中,缓存对数据库进行读取/查问操作,而后更新本人并将申请数据返回给最终用户。 办法 应用程序每次都从缓存中查问数据。如果数据不在缓存中,则缓存查询数据库并更新本人。缓存将数据返回给最终用户。优缺点 简化利用程序代码,read-through策略确保将数据获取逻辑转移到缓存中,从而简化了利用程序代码。更好的读取可伸缩性。当某个key在Cache-aside中过期时,并发申请可能会触发屡次数据库查问雷同的数据。在Read-through中,缓存确保只向数据库发送一个查问。3. Refresh-ahead Refresh-ahead策略是在过期之前刷新缓存数据,该办法实用于热数据,即预计在不久的未来会被申请的数据。 办法 假如缓存数据的过期工夫为60秒,刷新提前系数为0.5。如果缓存数据在60秒后被拜访,将从缓存存储执行同步读取以刷新其值。如果缓存数据在30秒后被拜访,比方第35秒,缓存将间接返回数据,并异步刷新数据。优缺点 因而,refresh-ahead缓存实质上是在下一次可能的缓存拜访之前以配置的距离刷新缓存。在这种读流量十分高的零碎中,几毫秒内可能会产生几千个读操作。 写密集型利用缓存任何写密集型应用程序都须要缓存策略,例如: 1. Write-Through Write-Through策略将缓存作为其主数据存储,即首先在缓存中更新数据,而后才在数据库中更新数据。 上面是利用想要写入数据或更新值时产生的状况: 应用程序将数据间接写入缓存。缓存更新主数据库中的数据。当写操作实现时,缓存和数据库都具备雷同的值,并且始终保持统一。优缺点 当与read-through配合应用时,在网络调用中十分无效,数据首先被读/写到缓存中,使得简直不会产生缓存有效的状况。因为所有数据都是新的和常常拜访的数据,而且所有对数据库的写入都是通过缓存实现,使得数据库和缓存简直始终保持统一。 2. Write-back Write-back办法与write-through十分类似,只是数据库写调用是异步的。 优缺点 Write-back缓存能够进步写性能,非常适合波及大量写操作的工作负载。当与read-through联合应用时,也非常适合混合工作负载,能够确保最近更新拜访的数据始终在缓存中可用。升高网络老本: 如果应用批处理调用,还能够缩小对数据库的总体写操作,从而缩小负载并降低成本,特地是当数据库按申请数量免费时(例如DynamoDB)。缓存应用效率低下: 不常常被申请的数据也会被写入缓存。这点能够通过TTL进行优化。3. Write-around 在Write-around办法中,首先将数据更新到数据库,而后数据库对缓存进行异步调用以更新key。 办法 当收到写申请时,应用程序更新数据库中的记录。数据库异步更新/删除缓存中的键。优缺点 Write-around能够与read-through联合应用,在数据只写入一次,读取频率较低或从不读取的状况下提供良好的性能(例如实时日志或聊天室)。同样,这种模式也能够与cache-aside联合应用。 缓存生效办法缓存生效是从缓存中删除古老或过期数据的过程,以确保只保留最新的可用数据。缓存生效策略有: 基于工夫生效(TTL): 在此策略中,缓存数据在通过一段时间后生效。这是一个简略而无效的策略,易于施行,但可能并不适用于所有用例,因为有些数据可能比其余数据更容易过期。基于事件生效: 在此策略中,缓存数据将依据产生的特定事件(如底层数据源更改或其余相干事件)生效。这是一种更有针对性的生效办法,可确保数据仅在必要时生效,但须要与利用和底层数据源进行更档次的集成。基于版本生效: 在此策略中,为缓存中的每个数据块调配一个版本号,该版本号在每次数据更改时递增。当数据生效时,将在缓存中更新版本号,以确保仅应用数据的最新版本。这种策略对于频繁更改的数据成果很好,但须要额定的开销来治理版本号。最近起码应用(Least recently used, LRU)生效: 在此策略中,当缓存达到容量限度时,缓存中最近起码应用的数据将生效,从而确保在缓存中保留最罕用的数据,升高存储古老数据的危险。然而,该机制可能并不适宜所有用例,因为有些数据可能不被常常拜访,但依然须要缓存。手动生效: 在此策略中,生效由应用程序或管理员手动触发。该机制提供了最大的灵活性和对缓存的管制,但须要更多开销来治理生效过程。具体生效办法包含革除、禁止、刷新等。 ...

September 3, 2023 · 1 min · jiezi

关于后端:瑞吉外卖简历也许可以这样写

我的项目形容: 瑞吉外卖是一款专门为餐饮企业(餐厅、饭店)定制的软件产品,包含系统管理后盾和挪动端利用两局部。系统管理后盾次要提供给餐饮企业外部员工应用,用于对餐厅的分类、菜品、套餐、订单、员工等进行治理保护。挪动端利用次要提供给消费者应用,能够在线浏览菜品、增加购物车、下单等。 开发环境: 环境(软件): JDK +MySQL +IDEA+Git+Tomcat技术: Spring Boot、SSM、Mybatis Plus、Spring Security、Redis、Spring Cache、Swagger、Linux、ShardingJDBC、Nginx责任形容: 负责系统管理后盾的员工、分类、菜品、套餐模块的编写。负责挪动端利用的开发,实现短信验证码登录性能。开发挪动端利用的菜品浏览性能,使用户能够不便地浏览菜品信息。实现挪动端利用中用户地址簿信息的治理性能,不便用户治理收货地址。开发挪动端利用的购物车性能,使用户能够不便地增加菜品到购物车并治理订单。实现挪动端利用中提交订单的性能,确保用户可能胜利下单。进行挪动端利用的数据展现缓存优化,进步零碎的响应速度和用户体验。负责数据库主从配置以及读写拆散的实现,进步数据库的性能和可靠性。实现我的项目接口API文档生成性能,应用Swagger生成清晰明了的接口文档。技术形容: 应用Redis缓存高频数据,并应用Spring Cache优化代码,进步零碎的性能和响应速度。在整个开发过程中应用Linux零碎进行部署,充分利用Linux零碎的稳定性和安全性。应用Nginx部署前端我的项目,实现前后端拆散的部署形式,进步零碎的灵活性和可维护性。应用Nginx实现反向代理和负载平衡,进步零碎的并发解决能力和可用性。应用ShardingJDBC实现数据库读写拆散,进步数据库的读取性能和写入性能。应用Spring Security框架进行权限模块的开发,采纳经典的RBAC模型进行精密的权限治理。应用YApi实现前后端拆散开发,并应用Swagger生成接口API文档,进步团队的合作效率。应用Git进行我的项目的版本控制和代码治理,充分利用分支性能进行我的项目优化和问题修复。喜爱关注一下呀,查看更多内容

September 3, 2023 · 1 min · jiezi

关于后端:面试题精讲Redis如何实现分布式锁

首发博客地址 系列文章地址 Redis 能够应用分布式锁来实现多个过程或多个线程之间的并发管制,以确保在给定工夫内只有一个过程或线程能够拜访临界资源。以下是一种应用 Redis 实现分布式锁的常见办法: 获取锁: 客户端尝试应用SETNX命令在 Redis 中设置一个特定的键(作为锁)和一个惟一的标识符(例如,客户端 ID)。如果SETNX胜利,即键之前不存在,客户端取得锁并能够执行相应的操作。如果SETNX失败,即键曾经存在,示意锁曾经被其余客户端持有,客户端能够抉择期待一段时间后从新尝试获取锁,或者放弃获取锁。开释锁: 客户端应用DEL命令从 Redis 中删除之前设置的键,开释锁。开释锁的时候须要确保只有持有锁的客户端能够开释锁,能够应用 Lua 脚本来保障原子性。须要留神的是,分布式锁须要解决一些非凡状况和边界条件,如锁的超时工夫、锁的可重入性、锁的主动续期等。以下是一些常见的技巧和注意事项: 设置锁的超时工夫:能够为锁设置一个过期工夫,避免锁在某些状况下无奈被开释。能够应用EXPIRE命令为锁设置一个正当的过期工夫。锁的可重入性:能够在锁的值中保留客户端的惟一标识符,并在开释锁时查看标识符是否匹配,以确保只有持有锁的客户端能够开释锁。锁的主动续期:能够应用 Redis 的EXPIRE命令和定时器机制来定期续期锁的过期工夫,避免持有锁的客户端在执行较长操作时锁过期。应用 Lua 脚本:为了保障获取锁和开释锁的操作的原子性,能够应用 Redis 的 Lua 脚本来执行这些操作。须要留神的是,应用 Redis 的分布式锁依然须要留神正确处理并发和竞争条件,并且在非凡状况下可能会呈现死锁或活锁的状况。因而,在应用分布式锁时,须要认真思考并测试各种场景和边界条件,以确保零碎的正确性和可靠性。 本文由mdnice多平台公布

September 3, 2023 · 1 min · jiezi

关于后端:卡特兰数

title: 卡特兰数date: 2021-02-28 16:27:10 tags: 算法 概念 卡特兰数 的通项公式为 $$f \left( n \right) = \frac{1}{n+1} C_{2n}^{n}$$ 又依据 组合数的计算公式: 可得: $$f \left(n \right) = \frac{1}{n+1} \frac{(2n)!}{n!\cdot n!} = \frac{(2n)!}{(n+1)!\cdot n!} $$ 同时满足递推关系式: $$f \left(0 \right) = 1, f \left(n+1 \right) = \frac{2(2n+1)}{n+2} \cdot f \left(n \right) $$ 利用 <font color="#008B8B">1.括号化问题(或者01的个数问题)</font> 矩阵链乘: P=a1×a2×a3×……×an,根据乘法结合律,不扭转其程序,只用括号示意成对的乘积,试问有几种括号化的计划?(h(n)种) <font color="#008B8B">2.出栈秩序问题</font> 一个栈(无穷大)的进栈序列为1,2,3,…n,有多少个不同的出栈序列?与 问题1解法雷同, 进栈相当于左括号,出栈相当于右括号 ...

September 3, 2023 · 1 min · jiezi

关于后端:不同写法的性能差异

达到雷同目标,能够有多种写法,每种写法有性能、可读性方面的区别,本文旨在探讨不同写法之间的性能差别 <font color="#1E90FF"> len(str) vs str == "" </font> 本局部参考自: 问个 Go 问题,字符串 len == 0 和 字符串== "" ,有啥区别? gotest.go: package gotestfunc Test1() bool { var v string if v == "" { return true } return false}func Test2() bool { var v string if len(v) == 0 { return true } return false} webbench_test.go: package gotestimport ( "testing")func BenchmarkTest1(b *testing.B) { for i := 0; i < b.N; i++ { Test1() }}func BenchmarkTest2(b *testing.B) { for i := 0; i < b.N; i++ { Test2() }} ...

September 3, 2023 · 55 min · jiezi

关于后端:Mysql系列一MySQL语句执行流程

首发博客地址首发博客地址 系列文章地址 参考文章 MySQL 逻辑架构 连接器连贯命令个别是这么写的 mysql -h$ip -P$port -u$user -p那么 什么是连接器?MySQL 连接器(MySQL Connector)是用于连贯和与 MySQL 数据库进行交互的驱动程序。它提供了与 MySQL 数据库服务器通信的性能,包含建设连贯、执行查问、更新数据等。 MySQL 提供了多种连接器,罕用的有以下几种: JDBC 连接器:JDBC(Java DatabaseConnectivity)是 Java 语言的一种规范 API,用于连贯和操作各种数据库。MySQL 提供了一个 JDBC 驱动程序,能够通过 JDBC 连接器在 Java 应用程序中连贯和操作 MySQL 数据库。ODBC 连接器:ODBC(Open DatabaseConnectivity)是一种通用的数据库拜访接口,能够在不同的编程语言和操作系统中连贯和操作多种数据库。MySQL 提供了一个 ODBC 驱动程序,能够通过 ODBC 连接器在反对 ODBC 的应用程序中连贯和操作 MySQL 数据库。.NET 连接器:MySQL 提供了一个专门用于.NET 平台的连接器,能够在.NET 应用程序中连贯和操作 MySQL 数据库。它提供了与 ADO.NET 兼容的接口,能够不便地在.NET 开发环境中应用 MySQL 数据库。Python 连接器:MySQL 提供了一个 Python 连接器,能够在 Python 应用程序中连贯和操作 MySQL 数据库。该连接器是通过 Python 的规范数据库 API(PythonDB API)实现的。应用 MySQL 连接器,能够通过配置连贯参数(如主机名、端口号、用户名、明码等)来建设与 MySQL 数据库的连贯。连接器还提供了执行 SQL 语句、获取查问后果、处理事务等性能,能够不便地进行数据库的操作。 ...

September 3, 2023 · 3 min · jiezi

关于后端:给Hexo添加说说功能

首发博客地址 官网地址 成果 前言GitHub 仓库:Artitalk.js 个性增删查改全方面反对反对针对每条说说的评论反对 Markdown/html 语法反对图片上传 疾速应用下列主题已将本我的项目整合进去,能够间接应用。 感激以下主题对本我的项目的反对~ hexo-theme-volantishexo-theme-cardshexo-theme-butterflyhexo-theme-materygridea-theme-darkhexo-theme-MengD 开始应用 LeanCloud 的相干筹备TIP 与 Valine 在同一个页面应用 如果迫切需要将 Artitalk 与 Valine 在同一个页面应用,能够通过 Artitalk 与 Valine 应用同一个 LeanCloud 的利用来解决。 倡议应用国际版的 LeanCloud 因为国际版的 LeanCloud 不须要配置 serverurl,所以举荐应用国际版,速度没有区别,如果应用国内版的 LeanCloud 别忘了填写 serverurl 即可 与valine在同一页面应用 如果有这个须要,能够将 artitalk 与 valine 寄存在同一个利用中。能够无效防止同一个页面应用两个leancloud利用所产生的抵触。 返回 LeanCloud 国际版,注册账号。注册实现之后依据 LeanCloud 的提醒绑定手机号和邮箱。绑定实现之后点击创立利用,利用名称随便,接着在结构化数据中创立 class,命名为 shuoshuo。在你新建的利用中找到结构化数据下的用户。点击增加用户,输出想用的用户名及明码。回到结构化数据中,点击 class 下的 shuoshuo。找到权限,在 Class 拜访权限中将 add_fields 以及 create 权限设置为指定用户,输出你方才输出的用户名会主动匹配。为了平安起见,将 delete 和 update 也设置为跟它们一样的权限。而后新建一个名为atComment的class,权限什么的应用默认的即可。点击 class 下的 _User 增加列,列名称为 img,默认值填上你这个账号想要用的公布说说的头像url,这一项不进行配置,说说头像会显示为默认头像 —— Artitalk 的 logo。在最菜单栏中找到设置-\> 利用 keys,记下来 AppID 和 AppKey ,一会会用。最初将 _User 中的权限全副调为指定用户,或者数据创建者,为了保障不被篡改用户数据以达到强制公布说说。❗ 对于设置权限的这几步 ...

September 2, 2023 · 1 min · jiezi

关于后端:技术人员该读什么书-并发编程篇

前言并发编程是IT人面试必备的八股文之一,我的项目开发中也常遇到高并发的场景,程序员须要思考多线程编程、资源竞争、锁机制、分布式计算等多个方面的常识和技术。 小编举荐一期高并发相干书籍,能够通过这些书籍系统地理解高并发相干常识,并学习不同的解决方案和优化策略,从而可能更好地应答理论问题。 本期举荐1、《Java 并发编程实战》 举荐理由: 这本书被誉为被誉为 Java 并发编程的圣经,本书深入浅出地介绍了Java线程和并发,是一本完满的Java并发参考手册。书中从并发性和线程安全性的基本概念登程,介绍了如何应用类库提供的根本并发构建块,用于防止并发危险、结构线程平安的类及验证线程平安的规定,如何利用线程来进步并发应用程序的吞吐量等。还介绍了一些高级主题,如显式锁、原子变量、非阻塞算法以及如何开发自定义的同步工具类。 2、《Java并发编程的艺术》 举荐理由: 并发编程畛域的扛鼎之作,作者是阿里和1号店的资深Java技术专家,本书内容涵盖Java并发编程机制的底层实现原理、Java内存模型、Java并发编程根底、Java中的锁、并发容器和框架、原子类、并发工具类、线程池、Executor框架等主题,每个主题都做了深刻的解说,同时通过实例介绍了如何利用这些技术。 3、《Java多线程编程实战指南(外围篇)》 举荐理由: 本书适宜有肯定Java语言根底的读者作为入门多线程编程之用,也适宜有肯定多线程编程教训的读者作为从新梳理知识结构以晋升认知档次和参考之用。 4《Java多线程编程实战指南(设计模式篇)》 举荐理由: 本书采纳Java(JDK1.6)语言和UML 为描述语言,并联合作者多年工作经验的相干实战案例,介绍了多线程环境下罕用设计模式的前因后果:各个设计模式是什么样的及其典型的理论利用场景、理论利用时须要留神的事项以及各个模式的可复用代码实现。 5、《精通Java并发编程(第2版)》 举荐理由: 本书讲述Java 并发API 最重要的元素,包含执行器框架、Phaser 类、Fork/Join 框架、流API、并发数据结构、同步机制,并展现如何在理论开发中应用它们。此外,本书还介绍了设计并发应用程序的方法论、设计模式、实现良好并发应用程序的提醒和技巧、测试并发应用程序的工具和办法,以及如何应用面向Java 虚拟机的其余编程语言实现并发应用程序。 6、《Java并发编程之美》 举荐理由: 此书通过图文联合、通俗易懂的解说形式帮忙大家实现多线程并发编程从入门到实际的飞跃!共分为三局部,第一部分为Java 并发编程根底篇,次要解说Java 并发编程的基础知识、线程无关的常识和并发编程中的其余相干概念。第二局部为Java 并发编程高级篇,解说了Java 并发包中外围组件的实现原理,让读者知其然,也知其所以然。第三局部为Java 并发编程实际篇,次要解说并发组件的应用办法,以及在应用过程中容易遇到的问题和解决办法。 最初关注微信公众号【架构面试栈】,回复关键字“bfbc” 获取本期举荐中,咱们介绍了一些对于了解和应答高并发场景十分有帮忙的书籍。这些书籍内容涵盖了从实践到实际、从架构设计到性能调优的各个方面,旨在帮忙读者更好地了解高并发的概念和原理,并提供一些实用的解决方案和技巧。心愿读者在学习的过程中可能放弃实际与实践相结合的态度,只有通过理论利用并一直总结经验,能力真正把握高并发开发的要点和技巧。 本文由mdnice多平台公布

September 2, 2023 · 1 min · jiezi

关于后端:MySQL-InnoDB-的所有锁

InnoDB 锁介绍共享锁和独占锁InnoDB实现规范的行级锁定,其中有两种类型的锁, 共享 ( S) 锁和独占 ( X) 锁。 共享 ( S) 锁容许持有锁的事务读取一行 。独占 ( X) 锁容许持有锁的事务更新或删除行 。如果事务在 row 上T1持有共享 ( S) 锁r,则来自某个不同事务T2 的对 row 锁的申请r将按如下形式解决: 能够立刻授予锁T2申请 。S后果,T1和T2 都S锁定了r.不能立刻授予锁定 T2申请 。如果事务在 row 上T1持有排他 ( X) 锁,则无奈立刻授予r来自某个不同事务T2对任一类型锁的申请。r相同,事务T2必须期待事务T1开释其对 row 的锁定r。 意向锁InnoDB反对多粒度锁,容许行锁和表锁并存。例如,诸如 在指定表上LOCK TABLES ... WRITE获取排他锁(一个锁)的语句。X为了使多粒度级别的锁定变得切实可行,InnoDB请应用 意向锁。意向锁是表级锁,批示事务稍后对表中的行须要哪种类型的锁(共享或独占)。意向锁有两种类型: 动向共享锁( IS) 示意事务打算在表中的各个行上设置 共享 锁 。动向排他锁 ( )IX示意事务打算在表中的各个行上设置排他锁。例如,SELECT ... FOR SHARE设置一个IS锁,并 SELECT ... FOR UPDATE设置一个IX锁。 动向锁定协定如下: 在事务能够获取表中行的共享锁之前,它必须首先获取IS表上的锁或更强锁。在事务能够获取表中一行的排他锁之前,它必须首先获取IX 表上的锁。下表总结了表级锁类型兼容性。 XIXSISX抵触抵触抵触抵触IX抵触兼容的抵触兼容的S抵触抵触兼容的兼容的IS抵触兼容的兼容的兼容的如果申请事务与现有锁兼容,则将锁授予申请事务,但如果它与现有锁抵触,则不会授予该锁。事务期待,直到开释抵触的现有锁。如果锁定申请与现有锁定抵触并且因为会导致死锁而无奈授予 ,则会产生谬误。 意向锁不会阻塞除全表申请(例如,LOCK TABLES ... WRITE)之外的任何内容。意向锁的次要目标是表明有人正在锁定一行,或者将要锁定表中的一行。 ...

September 2, 2023 · 3 min · jiezi

关于后端:2023年8月文章一览

2023年8月编程人总共更新了17篇文章。 1.2023年7月文章一览 2.Programming Abstractions in C浏览笔记:p72-p75 3.RIP Bram Moolenar 4.Programming abstractions in C浏览笔记:p76-p83 5.Programming abstractions in C浏览笔记:p84-p87 6.Programming abstractions in C浏览笔记:p88-p90 7.Programming abstractions in C浏览笔记:p91-p106 8.Programming abstractions in C浏览笔记:p107-p110 9.boilerplate 10.Programming abstractions in C浏览笔记: p114-p117 11.Programming abstractions in C浏览笔记: p118-p122 12.Programming abstractions in C浏览笔记:p123-p126 13.Programming abstractions in C浏览笔记:p127-p129 14.Programming abstractions in C浏览笔记:p130-p131 15.Programming abstractions in C浏览笔记:p132-p137 16.Programming abstractions in C浏览笔记:p138 17.Programming abstractions in C浏览笔记:p139-p143 《2023年7月文章一览》中写到“受台风“杜苏芮”的残余环流影响,雨从7月下到了8月。”,杜苏芮从福建来到仅一个多月,苏拉便造访广东。此刻,里面正下着小雨。 8月,VIM的作者Bram Moolenar永远的来到了咱们。 8月的文章大部分都是对于《Programming Abstractions in C》的浏览笔记。接下来的几个月根本也都是这类文章,本意是通过这种形式示范在计算机领域如何通过浏览一本教材学习计算机技术。这个过程是漫长而波折的,会遇到很多问题。当然,这样的形式办法也不仅仅实用于计算机领域,其它畛域也是如此,要害是咱们要去做,同时在做的过程中不断改进,取得一些侧面的反馈,进而一直晋升,把握这门技术。 ...

September 2, 2023 · 1 min · jiezi

关于后端:quarkus依赖注入之二bean的作用域

欢送拜访我的GitHub这里分类和汇总了欣宸的全副原创(含配套源码):https://github.com/zq2599/blog_demos对于bean的作用域(scope)官网材料:https://lordofthejars.github.io/quarkus-cheat-sheet/#_injection作为《quarkus依赖注入》系列的第二篇,持续学习一个重要的知识点:bean的作用域(scope),每个bean的作用域是惟一的,不同类型的作用域,决定了各个bean实例的生命周期,例如:何时何处创立,又何时何处销毁bean的作用域在代码中是什么样的?回顾前文的代码,如下,<font color="blue">ApplicationScoped</font>就是作用域,表明bean实例以单例模式始终存活(只有利用还存活着),这是业务开发中罕用的作用域类型:@ApplicationScopedpublic class ClassAnnotationBean { public String hello() { return "from " + this.getClass().getSimpleName(); }}作用域有多种,如果按起源辨别一共两大类:quarkus内置和扩大组件中定义,本篇聚焦quarkus的内置作用域上面是整顿好的作用域一览,接下来会一一解说graph LRL1(作用域) --> L2-1(内置)L1 --> L2-2(扩大组件)L2-1 --> L3-1(惯例作用域)L2-1 --> L3-2(伪作用域)L3-1 --> L4-1(ApplicationScoped)L3-1 --> L4-2(RequestScoped)L3-1 --> L4-3(SessionScoped)L3-2 --> L4-4(Singleton)L3-2 --> L4-5(Dependent)L2-2 --> L3-6(例如 : TransactionScoped)惯例作用域和伪作用域惯例作用域,quarkus官网称之为<font color="blue">normal scope</font>,包含:ApplicationScoped、RequestScoped、SessionScoped三种伪作用域称之为<font color="red">pseudo scope</font>,包含:Singleton、RequestScoped、Dependent两种接下来,用一段最平时的代码来揭示惯例作用域和伪作用域的区别上面的代码中,ClassAnnotationBean的作用域ApplicationScoped就是<font color="blue">normal scope</font>,如果换成<font color="red">Singleton</font>就是<font color="red">pseudo scope</font>了@ApplicationScopedpublic class ClassAnnotationBean { public String hello() { return "from " + this.getClass().getSimpleName(); }}再来看应用ClassAnnotationBean的代码,如下所示,是个再平时不过的依赖注入@Path("/classannotataionbean")public class ClassAnnotationController { @Inject ClassAnnotationBean classAnnotationBean; @GET @Produces(MediaType.TEXT_PLAIN) public String get() { return String.format("Hello RESTEasy, %s, %s", LocalDateTime.now(), classAnnotationBean.hello()); }}当初问题来了,ClassAnnotationBean是何时被实例化的?有以下两种可能:第一种:ClassAnnotationController被实例化的时候,classAnnotationBean会被注入,这时ClassAnnotationBean被实例化第二种:<font color="blue">get</font>办法第一次被调用的时候,classAnnotationBean真正发挥作用,这时ClassAnnotationBean被实例化所以,一共有两个工夫点:注入时和get办法首次执行时,作用域不同,这两个工夫点做的事件也不同,上面用表格来解释工夫点惯例作用域伪作用域注入的时候注入的是一个代理类,此时ClassAnnotationBean并未实例化触发ClassAnnotationBean实例化get办法首次执行的时候1. 触发ClassAnnotationBean实例化2. 执行惯例业务代码1. 执行惯例业务代码至此,您应该明确两种作用域的区别了:伪作用域的bean,在注入的时候实例化,惯例作用域的bean,在注入的时候并未实例化,只有它的办法首次执行的时候才会实例化,如下图 ...

September 2, 2023 · 2 min · jiezi

关于后端:10分钟搞懂敏捷度量

麻利团队须要选取一些要害指标对生产力、开发流程、产品质量进行度量,从而一直优化开发过程,晋升团队效率。原文: Agile Metrics — What Matters and Why? 麻利曾经在几十年内霸占了软件开发行业,每个技术组织要么是麻利的,要么是在向麻利转型的过程中,能够将它们统称为"麻利组织"!传统项目管理指标,如生产力、进度差别、老本差别等,在麻利零碎中岂但没用,而且事实上可能事与愿违。 有很多指标实用于麻利零碎。问题是,哪些指标才是真正重要的?上面将介绍如何抉择一个对大多数环境和组织都有用的麻利度量子集。 为简略起见,咱们将度量规范分为以下三类: 生产率、稳定性和品质,如下所示。 生产力(Productivity)以下是无关无效利用资源以交付后果的要害指标。 OKR(指标)奉献重要的一点是如何掂量团队为实现组织或业务单元的战略目标付出了多少致力。例如,在每个Sprint中,均匀60%的团队能力用于OKR。现实状况下,50%或更多的致力应该用于OKR或公司战略目标。 价值传递(Value Delivered)这个指标有助于度量每个Sprint交付的价值。在以产品为主导的组织中,优先级公式或矩阵以与开发团队评估工作故事点雷同的形式实现价值评估。例如,WSJF(Weighted Short Job First, 加权短作业优先)优先排序办法依据业务、危险升高、工夫关键性和机会实现来评估价值点。RICE办法估算逾越范畴和影响的价值点。 燃尽图(Burndown)燃尽图是一种简略的对一组工作所获得停顿进行可视化的办法。X轴示意工夫盒的工作集,Y轴示意工夫盒内的增量工夫单位。燃尽图用于监控整个release、epic和sprint工作的超时实现状况。强烈推荐sprint燃尽图,它有助于在sprint期间放弃团队每天的工作进度。 流速(Velocity)狭义上讲,麻利流速示意每个sprint中实现的故事点。这有助于基于故事点估算实现工作主体所需的sprint次数。流速有许多变体: 最大流速、均匀流速和最佳流速。最好抉择最佳流速,即依据验收规范,在没有任何未修复缺点的状况下,每个sprint交付工作主体的均匀故事点数量。 前置工夫(Lead Time)前置工夫示意从创立工作项(Story, Feature或Epic)到实现所破费的工夫。这是一个很好的掂量团队效率的规范。交付工夫越短,团队将想法或未实现的申请转化为可工作软件的效率就越高。 周期时间(Cycle Time)周期时间示意从工作项(Story, Feature或Epic)开始到实现所破费的工夫。这是掂量团队开发、测试和公布过程效率的好办法。周期时间越短,团队的开发、测试和公布过程就越高效。 累积流程图(CFD, Cumulative Flow Diagram)累积流程图提供了从开始到完结的整个启动、开发、测试和公布过程的快照,是一个简略的可视化工具,能够让咱们立刻辨认瓶颈。 净推荐值(Net Promoter Score)净推荐值是推荐者和诽谤者之间差别的百分比分数。顾客被要求给出一个从1到10的分数,示意他们向其他人举荐产品的可能性有多大。9分和10分是踊跃者,8分和9分是被动者,6分及以下是诽谤者。NPS能够说是所有指标中最重要的,因为客户是决定团队是否交付了任何有价值的货色的最佳利益相关者。 稳定性(Stability)以下是将帮忙团队确保交付过程(包含开发、测试和部署)以稳固、可预测和可继续的形式运行的度量指标。 打算实现比(Planned to Done Ratio)打算实现比示意在工夫框完结时按计划实现的工作或工作项的百分比,能够让咱们理解团队正确评估工作、解决阻碍、技能差距以及及时交付的能力,指标是超过80%。亲密关注这一指标将确保在长期内具备更高的可预测性。 在制品(Work In Progress, WIP)在制品是看板中的要害指标,也能够在Scrum中看到它。WIP是正在解决的工作项的数量,其目标是限度正在进行的工作,以缩小上下文切换,使团队及时解决阻塞。现实状况下,咱们的指标应该是每个Scrum团队成员一次实现1-2个工作。 准时公布率(On-time Release Rate)这是在公布日期按计划实现公布的百分比,示意团队在按时实现公布方面的可预测性。数字越高,从新布局和重组的需要就越低,而这些会导致团队能力的重大节约。 失败部署(Failed Deployments)示意在给定工夫范畴内失败的部署数量,波及生产部署和低级环境的部署,是对代码稳定性的度量,并显示开发团队是否在Sprint完结时筹备好了潜在的可公布代码,也是对环境稳定性的一种掂量。 团队流动率(Team Turnover Rate)当波及到稳定性时,这是最重要的指标之一。到职率示意麻利团队成员来到团队和被替换的比率。团队成员流动的老本很高,招聘、晋升技能、团队常识的散失等等都是老本。肯定水平的散失不可避免,但如果超出了行业程度,就应该设法解决。一般来说,科技行业的人员流动率在每年10%到15%之间。员工散失的三大起因是: 薪酬、职业倒退机会和工作条件。所以你晓得如果人员流动率很高该怎么做了吧。 幸福指数(Happiness Score)与CSAT(客户满意度评分, Customer Satisfaction Score)相似,通常以5分的规范对团队均匀幸福感进行评分。该考察通常作为Sprint回顾的一部分进行,并随着工夫的推移进行跟踪,以监督一个又一个Sprint的偏差。幸福指数与到职率间接相干,幸福指数与到职率成反比,幸福指数越高,到职率越低! 品质(Quality)上面给出了一些要害指标,帮忙团队确保交付的代码具备可承受的品质。 缺点解决工夫(Defect Resolution Time)缺点解决工夫(DRT, Defect Resolution Time)或均匀解决工夫(MTTR, Mean Time To Resolution)是开发团队解决缺点所需的均匀工夫,越短越好。均匀DRT或MTTR通常跟踪所有环境中的缺点。DRT的SLA因组织和团队而异,一般来说,团队应该将最大DRT的指标定为要害缺点1天,高缺点1-2天,中等缺点5-7天,低缺点10-14天。MTTR与客户满意度呈负相关,因而很重要。 ...

September 2, 2023 · 1 min · jiezi

关于后端:Go-map转json

在Go中如何返回前端 字段名称/数量都不确定的json数据? 之前用Go写web服务,返回给前端的json格局的接口,有哪些要返回的字段都是明确的。都是事后定义一个构造体,json.Marshal一下即可~ 但当有的场景,要返回哪些字段不确定时,就无奈应用struct的形式。 还能够用map package mainimport ( "encoding/json" "fmt")func main() { Map2Json()}func Map2Json() { mapInstance := make(map[string]interface{}) mapInstance["Name"] = "cs" mapInstance["Age"] = 28 mapInstance["Address"] = "杭州" relation := make(map[string]interface{}) relation["father"] = "cuixxxxxxx" relation["mother"] = "yinxxxxx" relation["wife"] = "pengxx" mapInstance["Relation"] = relation pet := make(map[string]interface{}) pet["one"] = "弥弥懵" pet["two"] = "黄橙橙" pet["three"] = "呆呆" pet["four"] = "皮瓜瓜" pet["five"] = "斑斑" mapInstance["Cat"] = pet jsonStr, err := json.Marshal(mapInstance) fmt.Println("err is:", err) fmt.Println("jsonStr is:", string(jsonStr))}输入为: ...

September 2, 2023 · 1 min · jiezi

关于后端:Linux系列vmware虚拟机网络配置详解

非原创原文地址 首发博客地址 系列文章地址 vmware为咱们提供了三种网络工作模式,它们别离是:Bridged(桥接模式)、NAT(网络地址转换模式)、Host-Only(仅主机模式)。 关上vmware虚拟机,咱们能够在选项栏的“编辑”下的“虚构网络编辑器”中看到VMnet0(桥接模式)、VMnet1(仅主机模式)、VMnet8(NAT模式),那么这些都是有什么作用呢?其实,咱们当初看到的VMnet0示意的是用于桥接模式下的虚构交换机;VMnet1示意的是用于仅主机模式下的虚构交换机;VMnet8示意的是用于NAT模式下的虚构交换机。 同时,在主机上对应的有VMware Network Adapter VMnet1和VMware Network AdapterVMnet8两块虚构网卡,它们别离作用于仅主机模式与NAT模式下。在“网络连接”中咱们能够看到这两块虚构网卡,如果将这两块卸载了,能够在vmware的“编辑”下的“虚构网络编辑器”中点击“还原默认设置”,可从新将虚构网卡还原。 小伙伴看到这里,必定有疑难,为什么在真机上没有VMware Network Adapter VMnet0虚构网卡呢?那么接下来,咱们就一起来看一下这是为什么。 一、Bridged(桥接模式)什么是桥接模式?桥接模式就是将主机网卡与虚拟机虚构的网卡利用虚构网桥进行通信。在桥接的作用下,相似于把物理主机虚构为一个交换机,所有桥接设置的虚拟机连贯到这个交换机的一个接口上,物理主机也同样插在这个交换机当中,所以所有桥接下的网卡与网卡都是替换模式的,互相能够拜访而不烦扰。在桥接模式下,虚拟机ip地址须要与主机在同一个网段,如果须要联网,则网关与DNS须要与主机网卡统一。其网络结构如下图所示: 接下来,咱们就来实际操作,如何设置桥接模式。 首先,装置完零碎之后,在开启零碎之前,点击“编辑虚拟机设置”来设置网卡模式。 点击“网络适配器”,抉择“桥接模式”,而后“确定” 在进入零碎之前,咱们先确认一下主机的ip地址、网关、DNS等信息。 而后,进入零碎编辑网卡配置文件,命令为vi /etc/sysconfig/network-scripts/ifcfg-eth0 增加内容如下: 编辑实现,保留退出,而后重启虚拟机网卡,应用ping命令ping外网ip,测试是否联网。 能ping通外网ip,证实桥接模式设置胜利。 那主机与虚拟机之间的通信是否失常呢?咱们就用近程工具来测试一下。 主机与虚拟机通信失常。 这就是桥接模式的设置步骤,置信大家应该学会了如何去设置桥接模式了。桥接模式配置简略,但如果你的网络环境是ip资源很短少或对ip治理比拟严格的话,那桥接模式就不太实用了。如果真是这种状况的话,咱们该如何解决呢?接下来,咱们就来意识vmware的另一种网络模式:NAT模式。 二、NAT(地址转换模式)刚刚咱们说到,如果你的网络ip资源紧缺,然而你又心愿你的虚拟机可能联网,这时候NAT模式是最好的抉择。NAT模式借助虚构NAT设施和虚构DHCP服务器,使得虚拟机能够联网。其网络结构如下图所示: 在NAT模式中,主机网卡间接与虚构NAT设施相连,而后虚构NAT设施与虚构DHCP服务器一起连贯在虚构交换机VMnet8上,这样就实现了虚拟机联网。那么咱们会感觉很奇怪,为什么须要虚构网卡VMwareNetwork Adapter VMnet8呢?原来咱们的VMware Network Adapter VMnet8虚构网卡次要是为了实现主机与虚拟机之间的通信。在之后的设置步骤中,咱们能够加以验证。 首先,设置虚拟机中NAT模式的选项,关上vmware,点击“编辑”下的“虚构网络编辑器”,设置NAT参数及DHCP参数。 将虚拟机的网络连接模式批改成NAT模式,点击“编辑虚拟机设置”。 点击“网络适配器”,抉择“NAT模式” 而后开机启动零碎,编辑网卡配置文件,命令为vi /etc/sysconfig/network-scripts/ifcfg-eth0 具体配置如下: 编辑实现,保留退出,而后重启虚拟机网卡,动静获取ip地址,应用ping命令ping外网ip,测试是否联网。 之前,咱们说过VMware Network Adapter VMnet8虚构网卡的作用,那咱们当初就来测试一下。 如此看来,虚拟机能联通外网,的确不是通过VMware Network Adapter VMnet8虚构网卡,那么为什么要有这块虚构网卡呢? ...

September 1, 2023 · 1 min · jiezi

关于后端:面试题精讲SpringBoot的传播机制详解

首发博客地址 系列文章地址 Spring Boot 是基于 Spring 框架的疾速开发框架,提供了许多便捷的个性和机制来简化开发过程。在 Spring Boot 中,事务的流传机制是通过@Transactional 注解来实现的。 @Transactional 注解能够用于办法、类或接口上,用于标识办法或类中的所有办法须要进行事务管理。通过设置@Transactional 注解的 propagation 属性,能够指定事务的流传行为。 事务的流传行为分为以下几种: REQUIRED:示意以后办法必须在一个事务内运行。如果以后曾经存在事务,则退出该事务;如果以后不存在事务,则创立一个新的事务。SUPPORTS:示意以后办法反对事务。如果以后存在事务,则退出该事务;如果以后不存在事务,则以非事务形式运行。MANDATORY:示意以后办法必须在一个事务内运行。如果以后不存在事务,则抛出异样。REQUIRES_NEW:示意以后办法必须在一个新的事务内运行。如果以后存在事务,则挂起该事务并创立一个新的事务。NOT_SUPPORTED:示意以后办法不反对事务。如果以后存在事务,则挂起该事务。NEVER:示意以后办法不反对事务。如果以后存在事务,则抛出异样。NESTED:示意以后办法必须在一个嵌套事务内运行。如果以后存在事务,则在嵌套事务内运行;如果以后不存在事务,则创立一个新的事务。上面是一个应用 Spring Boot 流传机制的示例: @Service@Transactional(propagation = Propagation.REQUIRED)public class UserService { @Autowired private UserRepository userRepository; public void createUser(User user) { // 保留用户信息 userRepository.save(user); // 调用其余办法,如果其余办法也有@Transactional注解,则会参加到以后事务中 updateUserStatus(user.getId()); } @Transactional(propagation = Propagation.REQUIRED) public void updateUserStatus(Long userId) { // 更新用户状态 userRepository.updateStatus(userId); }}在下面的示例中,UserService 类的 createUser 办法应用了@Transactional 注解,并设置了流传行为为 REQUIRED,示意该办法必须在一个事务内运行。在该办法中,先保留用户信息到数据库,而后调用了 updateUserStatus 办法。因为 updateUserStatus 办法也应用了@Transactional 注解,并且流传行为也为 REQUIRED,所以它会参加到以后事务中,保障了两个办法的操作在同一个事务内执行。 通过应用@Transactional 注解,咱们能够不便地管制事务的流传行为,实现对数据库操作的事务管理。 本文由mdnice多平台公布 ...

September 1, 2023 · 1 min · jiezi

关于后端:驶向高效运营StarRocks-助力蔚来汽车数据分析再升级

作者:蔚来汽车数字化业务发展部大数据团队 小编导读:蔚来汽车是一家全球化的智能电动汽车公司,是高端智能汽车市场的先驱及领跑者。蔚来致力于通过提供高性能的智能电动汽车与极致用户体验,为用户发明愉悦的生存形式。为了晋升外部大数据分析的效率,蔚来陆续尝试了多种组件,如 Apache Druid、TiDB 和 Apache Doris,最终抉择了StarRocks,落地场景蕴含:用户画像平台、数据经营平台、BI 自助取数和整车三电可靠性数据库。引入 StarRocks 之后,在不同场景下别离有 4-8 倍的晋升。OLAP 架构演进 蔚来汽车外部有丰盛的 OLAP 应用场景需要,包含销售潜在客户人群圈选、供应链/生产/物流时效看板、车主用车行为剖析、车辆电池报警监控、售后培修归因等。 为了晋升大数据分析的效率,咱们陆续尝试了多种组件,如 Apache Druid、TiDB 和 Apache Doris,最终咱们抉择了StarRocks。相较于同类 OLAP 产品,StarRocks 体现出以下显著劣势: 反对较高水平的并发(主键模型)实时与离线剖析的双重反对反对明细和聚合模型反对肯定水平的更新优良的 Rollup 和物化视图能力,显著晋升了查问效率兼容 MySQL 协定,开发和应用老本比拟低全面的向量化引擎,反对 SIMD 指令,读写性能十分优异,满足咱们的要求架构简洁,运维老本比拟低首先咱们来疾速回顾下StarRocks的架构。StarRocks 架构简洁,整个零碎的外围只有 FE(Frontend)、BE(Backend)两类服务过程,不依赖任何内部组件,不便部署与保护。FE 和 BE 模块都能够在线程度扩大,元数据和业务数据都有正本机制,确保整个零碎无单点。StarRocks 提供 MySQL 协定接口,反对规范 SQL 语法。用户可通过 MySQL 客户端不便地查问和剖析 StarRocks 中的数据。FE 是 StarRocks 的前端节点,负责管理元数据,治理客户端连贯,进行查问布局,查问调度等工作。每个 FE 节点都会在内存保留一份残缺的元数据,这样每个 FE 节点都可能提供无差别的服务。BE 是 StarRocks 的后端节点,负责数据存储、SQL执行等工作。 (StarRocks 架构简洁且提供 MySQL 协定接口) 在咱们的大数据架构中,来自 Kafka/Hive 的业务/用户数据源,通过 Broker Load/Routine Load/Stream Load/Flink Connector 等多种离线/实时导入形式写入 StarRocks,次要用来存储 DWD/DWS/ADS 层的数据,用于离线和实时指标的疾速剖析。咱们深度自研的 DataSight 一站式数据治理与开发平台,曾经集成了 StarRocks,反对通过配置化形式不便的读写 StarRocks。将历史工作迁徙到 StarRocks 后,改善和收益不言而喻。无论是查问速度还是运维老本,都失去了晋升。以某车辆数据指标的 BI 服务为例,过来该指标采纳 Druid 和 Cassandra 两种数据库存储,在迁徙到 StarRocks 后,通过正当的 Rollup 策略,均匀查问提早从 2s+ 升高到 500ms,查问效率进步 4-5 倍,并且仅需应用一种 OLAP 查问引擎。目前,公司已有 20 多个业务线开始应用 StarRocks,广泛应用于研发、生产制作以及用户车辆经营等多个畛域的业务 BI 看板和指标大屏。 ...

September 1, 2023 · 3 min · jiezi

关于后端:深入解读-MongoDB-CDC-的设计与实现

作者:千浪@阿里云研发工程师MongoDB CDC 概述MongoDB 是当下风行的一个基于文档的非关系性数据库。MongoDB CDC [1] 是 Flink CDC 社区 [2] 提供的一个用于捕捉变更数据(Change Data Capturing)的 Flink 连接器,可连贯到 MongoDB 数据库和汇合,并捕捉其中的文档减少、更新、替换、删除等变更操作,生成规范的 Flink Changelog 事件流,反对通过 Flink SQL 或 DataStream API 进行数据加工, 加工之后能够不便地写入到 Flink 所反对的各种上游零碎中。 MongoDB CDC 外围性能全增量一体化读取在理论的业务场景中,经常须要同时采集 MongoDB 数据库中的存量数据以及增量数据。MongoDB CDC 可能一体化地读取全量数据和增量数据。在启动选项配置为 initial 模式时,CDC 会首先对指标汇合进行扫描,并对现存的每一条数据各发送一条 Insert 记录;快照实现后,CDC 会主动转换为增量模式,开始捕捉连接器启动后到来的变更数据。期间反对在任意时刻的故障复原,且保障提供不丢不重的准确一次(Exactly-Once)语义。 反对多种生产模式针对不同的场景需要,MongoDB CDC 能够设定为从以下模式中启动: latest 模式 在此模式下,MongoDB CDC 不会解决启动前曾经存在的数据,只针对启动后到来的变更数据产生变更记录。这意味着连接器只能读取在连接器启动之后的数据更改。initial 模式 在此模式下,MongoDB CDC 会先对全副存量数据进行快照,待快照实现后再开始捕捉变更数据。timestamp 模式 在此模式下,MongoDB CDC 会捕捉给定的工夫戳之后产生的变更数据。工夫戳的取值必须在 MongoDB 的无效日志记录范畴内。反对产生残缺变更事件流MongoDB 6.0 之前的版本默认不会提供变更前文档及被删除文档的数据;利用这些信息只能实现 Upsert 语义(即缺失了 Update Before 数据条目)。但在 Flink 中许多有用的算子操作都依赖残缺的 Insert、Update Before、Update After、Delete 变更流。如果须要补充缺失的变更前事件,一个天然的思路是在 Flink 状态中缓存所有文档的以后版本快照;在遇到被更新或删除的文档时,查表即可得悉变更前的状态。然而在最坏的状况下,这种操作可能须要保留相当于 100% 原始数据量的记录。 ...

September 1, 2023 · 4 min · jiezi

关于后端:PaimonStarRocks-湖仓一体数据分析方案

摘要:本文整顿自阿里云高级开发工程师曾庆栋(曦乐)在 Streaming Lakehouse Meetup 的分享。内容次要分为四个局部: 传统数据仓库剖析实现计划简介Paimon+StarRocks 构建湖仓一体数据分析实现计划StarRocks 与 Paimon 联合的应用形式与实现原理StarRocks 社区湖仓剖析将来布局点击查看原文视频 & 演讲PPT 一、传统数据仓库剖析实现计划简介传统数据仓库剖析的实现是一个典型 Lambda 架构,通过下图咱们能够看出传统架构次要分为两层:下层是实时链路层,上层是离线链路层。它们的数据通过左侧的数据摄入层,通过不同门路将数据对立整合到像 Kafka 这样的音讯队列中间件中,而后将数据分为两份雷同的数据,别离由实时链路和批量链路进行解决,最终汇总到数据服务层,实现对用户提供数据分析服务的能力。 Lambda 架构的呈现次要是因为用户对于实时剖析需要的呈现,以及流解决技术的逐步成熟。然而它也有一些显著的弊病,如上图所示,它须要保护两套零碎,这就会导致部署老本和人力老本都会减少。当业务变更的时候,也须要批改两套零碎来适应业务的变动。 随着流解决技术的逐步成熟,Lambda 架构之后又推出了 Kappa 架构,如下图所示。 Kappa 架构是应用流解决链路来代替原来的 Lambda 架构,因为流解决的成熟,所以通过一套零碎去实现实时和离线的计算成为可能。 Kappa 架构有一个前提,它认为对于历史数据的反复计算,在非必要的状况下是不必进行的。这就使得当用户须要从新计算历史数据或是呈现新业务变动的时候,往往须要将整个数据摄入阶段的过程重放一次。在大量生产历史数据的状况下,必然造成资源节约,并遇到一些瓶颈。 二、Paimon+StarRocks 构建湖仓一体数据分析实现计划2.1 数据湖核心第一个计划是 Paimon 和 StarRocks 构建湖仓一体数据分析的数据湖核心计划。 StarRocks 自身是一个 MPP 的数据库,同时能够外接多种格局的数据湖组件,能够以单纯作为查问引擎去外接数据湖组件,实现查问性能。如上图,通过 StarRocks 或 Spark 都能够对 ODS 等数据层的 Paimon 组件进行查问。 在这个架构里,Paimon 通过对数据的落盘和索引,补救了上文介绍的 Kappa 架构中音讯队列中间件在数据的批改、回溯、查问等方面的有余,从而使得这个架构的容错率更高,反对的能力也更宽泛。同时在批处理方面,Paimon 也能够齐全兼容 HIVE 的能力。 2.2 减速查问第二个计划是 Paimon 和 StarRocks 构建湖仓一体数据分析的减速查问计划。 它与第一个计划的区别是简直整个零碎都由 StarRocks 独自实现。当数据接入 Paimon,使它作为 ODS 层之后,通过 StarRocks 的表面个性来读取 Paimon 上的数据,建设一层物化视图来作为 DWD 层。 ...

September 1, 2023 · 2 min · jiezi

关于后端:开发规范系列二Java后台开发规范

首发博客地址https://blog.zysicyj.top/ 前言提到Java开发标准,那么大家能想到的根本就是阿里巴巴Java开发手册,这个手册的内容很丰盛,然而呢篇幅太长,很多人都记不住,那么怎么办呢?好在阿里巴巴提供了代码扫描插件,不便咱们开发时发现问题并及时批改。 如何应用该插件?参考这篇文章:【插件】Java开发标准配套Idea阿里巴巴代码扫描 手册内容{% pdf /static/pdf/Java开发手册(黄山版).pdf %} 我的项目对立规约工具类对立应用Hutool,非必要不要自定义工具类controller返回的每个实体须要新建一个Vo封装controller承受的参数对立应用Param封装Do类不容许增加额定字段业务之间传输应用Dto类封装跨模块,接口调用不容许间接传DO,须要封装成Dto单机事务必须加上@Transactional注解分布式事务必须加上@Seata注解对立应用Mybatis语法,不要应用JPAID对立应用Leaf雪花算法获取参数传递应用POJO传递,尽量不要应用Map办法参数超出屏幕宽度(个别3到5个)封装成对象接管办法命名规定 删除:del*更新:update*增加:insert*单个查问:select*批量查问:list*分页:page*导出:export*导入:import*返回布尔值的办法:iz*校验:check*填充:fill*类名命名规定 拦截器:*Handler过滤器:*Filter枚举:*Enum常量:*Constant监听器:*Listener配置类:*Config变量命名规定(全副驼峰) 动态常量:大写,下划线分隔 例如: USER_NAME_GLOBAL部分常量:大写,下划线分隔 例如:USER_NAME全局变量:*Global 例如:userNameGlobalList类型:*List 例如:userListMap类型: *Map 例如:userByIdMapSet类型: *Set 例如:userSet示意数量: *Num 例如: userTotalNum示意判断: iz** 例如:izLeader倡议阅读文章如何应用校验【hibernate validator】(二)申明和验证Bean束缚【hibernate validator】(三)申明和验证办法束缚【hibernate validator】(四)内插束缚谬误音讯【hibernate validator】(五)分组束缚【hibernate validator】(六)创立自定义束缚 开发标准MySQL开发标准后盾开发标准前端开发标准代码提交标准本文由mdnice多平台公布

September 1, 2023 · 1 min · jiezi

关于后端:设计一个极简交易所

设计一个极简交易所设计要点: 三路数据流 (交易数据、市场数据、交易落库) 的不同时延要求 来,间接上图! 第 1 步:客户通过经纪商 (华泰、安全等) 的网页或挪动应用程序下单。 第 2 步:经纪商将订单发送至交易所。 第 3 步:交易所的客户网关 (Client Gateway) 执行验证、费率限度、身份验证、数据规范化等操作,并将订单发送给订单治理 (Order Manager)。 第 4 步:订单治理依据风险管理 (Risk Manager) 设定的规定执行危险查看 (Risk Checks)。 第 5 步:危险查看通过后,订单治理会查看钱包中是否有足够的余额。 第 6-7 步:订单被发送到匹配引擎 (Matching Engine)。如果找到匹配订单,匹配引擎会发回成交回报。订单和执行后果都须要先在排序器 (Sequencer) 中定序,以确保公平性。 第 8 - 10 步:将执行后果一路传回客户端。 第 11-12 步:市场数据(包含k线图和订单簿)被发送到数据服务 (Data Service) 进行整合。经纪商查问数据服务以获取最新的市场数据。 第 13 步:交易报告模块 (Reporter) 整合必要的报告字段 (如用户ID、价格、数量、订单类型、已成交数量、残余数量),并将数据写入数据库进行长久化保留。交易报告模块尽管不在交易的要害门路 (Critical Path) 上,然而所存储的数据对于生成各种客户报表和监管报表尤其重要。 证券交易所的设计要求超低时延。大多数互联网利用能够承受数百毫秒的提早,但证券交易所却须要微秒级别的时延。 大家感兴趣的话,咱们能够独自介绍一下超低时延的设计要点 (和编程语言无关)。欢送点赞留言提出你的宝贵意见! 图解架构设计,关注公众号:ByteByteGo

September 1, 2023 · 1 min · jiezi

关于后端:ES系列一简介与安装

首发博客地址首发博客地址 系列文章地址 为什么要学习 ES?弱小的全文搜寻和检索性能:Elasticsearch 是一个开源的分布式搜寻和剖析引擎,应用倒排索引和分布式计算等技术,提供了弱小的全文搜寻和检索性能。学习 ES 能够把握如何构建简单的查问、应用各种过滤器和聚合操作来优化搜寻后果。实时数据分析和解决:ES 反对实时数据的索引和查问,可用于解决大规模的实时数据。学习 ES 能够理解如何应用 ES 进行实时数据的剖析和解决,包含日志剖析、事件处理、实时监控等。分布式存储和扩展性:ES 是一个分布式系统,能够将数据分布在多个节点上,以进步存储容量和查问性能。学习 ES 能够帮忙理解如何搭建和治理分布式 ES 集群,以及如何优化集群的性能和可靠性。文档导入和解决:ES 反对各种数据源的导入和解决,包含数据库、文件、API 等。学习 ES 能够把握如何将不同数据源的数据导入到 ES 中,并进行相应的解决和转换。日志剖析和搜索引擎优化:ES 在日志剖析和搜索引擎优化方面有很大的利用价值。学习 ES 能够学会如何利用 ES 进行日志的实时剖析和搜寻,以及如何优化搜索引擎的性能和相关性。全文搜索引擎的开发和利用:ES 是一个十分风行的全文搜索引擎,许多企业和我的项目都在应用 ES 构建全文搜寻性能。学习 ES 能够提供开发全文搜索引擎的技能和教训,为职业倒退削减竞争力。总结起来大略就是: 分布式搜索引擎大数据实时剖析引擎官网官网地址 ES 倒退历史Elasticsearch (ES)的倒退历史能够追溯到 2004 年,过后 Shay Banon 创立了一个名为 Compass 的开源我的项目,作为一个基于 Lucene 的全文搜索引擎库。 随着工夫的推移,Compass 逐步倒退成为一个独立的搜索引擎,但在 2009 年,Shay Banon 决定从新设计和重构该我的项目,以解决一些困扰他的设计和架构问题。于是,他创立了一个新的我的项目,命名为"elasticsearch",并于 2010 年开源公布。 以下是 ES 的次要倒退里程碑: 2010 年:Elasticsearch 首次开源公布。它基于 Apache Lucene 构建,提供了一个分布式搜寻和剖析引擎,用于实时数据的索引和查问。2013 年:Elasticsearch 正式成为 Elastic 公司的外围产品,并开始受到宽泛关注和采纳。此时,Elasticsearch 曾经成为开源搜索引擎的领导者之一。2014 年:Elasticsearch 公布了 1.0 版本,这是一个重要的里程碑,标记着 ES 的稳定性和成熟度。1.0 版本引入了一些重要的个性和改良,如聚合操作和索引别名等。2015 年:Elasticsearch 公布了 2.0 版本,引入了许多重要的性能和改良,包含复合索引、文档级别的更新和删除、分布式索引排序等。2016 年:Elasticsearch 公布了 5.0 版本,这是一个重要的版本公布,引入了许多重大的改良和变动。5.0 版本引入了新的分布式文档存储形式,并且废除了一些旧的性能和 API。2019 年:Elasticsearch 公布了 7.0 版本,这是一个重要的版本公布,引入了许多重要的性能和改良。7.0 版本引入了 Elasticsearch 的新分布式协调引擎,称为"Zen 2",以进步集群的稳定性和性能。2022 年:Elasticsearch 公布了 8.0 版本,这是一个重要的版本公布,引入了许多重要的性能和改良。原生反对 NLP,速度、扩大和检索相关性晋升,通过原生矢量搜寻进步搜寻相关性,默认开启平安性能随着工夫的推移,Elasticsearch 一直发展壮大,成为一个功能强大、可靠性高的分布式搜寻和剖析引擎。它被广泛应用于各种场景,包含日志剖析、实时数据处理、全文搜寻和商业智能等。并且,Elastic 公司也推出了其余产品,如 Kibana、Logstash 和 Beats 等,构建了一个残缺的数据分析和可视化平台,被称为"Elastic Stack"或"ELK Stack"。 ...

September 1, 2023 · 3 min · jiezi

关于后端:quarkus依赖注入之一创建bean

欢送拜访我的GitHub这里分类和汇总了欣宸的全副原创(含配套源码):https://github.com/zq2599/blog_demos对于依赖注入对一名java程序员来说,依赖注入应该是个相熟的概念,简略的说就是:我要用XXX,但我不负责XXX的生产以下代码来自spring官网,serve办法要应用MyComponent类的doWork办法,然而不负责MyComponent对象的实例化,只有用注解Autowired润饰成员变量myComponent,spring环境会负责为myComponent赋值一个实例@Servicepublic class MyService { @Autowired MyComponent myComponent; public String serve() { myComponent.doWork(); return "success"; }}对于依赖注入,网上有很多优良文章,这里就不开展了,咱们要关注的是quarkus框架的依赖注入对于《quarkus依赖注入》系列《quarkus依赖注入》共六篇文章,整体规划上隶属于《quarkus实战》系列,但专一于依赖注入的知识点和实战如果您相熟spring的依赖注入,那么浏览本系列时会发现quarkus与spring之间有太多相似之处,很多中央一看就懂本篇概览作为《quarkus依赖注入》的开篇,本文先介绍CDI,再学习如何创立bean实例,全文内容如下graph LRL1(本篇内容) --> L2-1(官网揭示)L1 --> L2-2(CDI)L1 --> L2-3(创立bean)L2-2 --> L3-1(对于CDI)L2-2 --> L3-2(对于bean)L2-3 --> L3-3(注解润饰在类上)L2-3 --> L3-4(注解润饰在办法上)L2-3 --> L3-5(注解润饰在成员变量上)L2-3 --> L3-6(扩大组件中的synthetic bean)学习quarkus的依赖注入之前,来自官网的揭示十分重要官网揭示在应用依赖注入的时候,quankus官网倡议<font color="red">不要应用公有变量</font>(用默认可见性,即雷同package内可见),因为GraalVM将利用制作成二进制可执行文件时,编译器名为<font color="blue">Substrate VM</font>,操作公有变量须要用到反射,而GraalVM应用反射的限度,导致动态编译的文件体积增大Quarkus is designed with Substrate VM in mind. For this reason, we encourage you to use *package-private* scope instead of *private*.对于CDI《 Contexts and Dependency Injection for Java 2.0》,简称CDI,该标准是对JSR-346的更新,quarkus对依赖注入的反对就是基于此标准实现的从 2.0 版开始,CDI 面向 Java SE 和 Jakarta EE 平台,Java SE 中的 CDI 和 Jakarta EE 容器中的 CDI 共享core CDI 中定义的个性。简略看下CDI标准的内容(请原谅欣宸的英语水平):该标准定义了一组弱小的补充服务,有助于改良利用程序代码的构造给有状态对象定义了生命周期,这些对象会绑定到上下文,上下文是可扩大的简单的、平安的依赖注入机制,还有开发和部署阶段抉择依赖的能力与Expression Language (EL)集成装璜注入对象的能力(集体想到了AOP,你拿到的对象其实是个代理)拦截器与对象关联的能力事件告诉模型web会话上下文一个SPI:容许<font color="blue">便携式扩大</font>与<font color="blue">容器</font>的集成(integrate cleanly )对于CDI的beanCDI的实现(如quarkus),容许对象做这些事件:绑定到生命周期上下文注入与拦截器和装璜器关联通过触发和察看事件,以涣散耦合的形式交互上述场景的对象统称为<font color="red">bean</font>,上下文中的 bean 实例称为<font color="blue">上下文实例</font>,上下文实例能够通过依赖注入服务注入到其余对象中对于CDI的背景常识就介绍到这里吧,接下来要写代码了源码下载本篇实战的残缺源码可在GitHub下载到,地址和链接信息如下表所示(https://github.com/zq2599/blog_demos)名称链接备注我的项目主页https://github.com/zq2599/blog_demos该我的项目在GitHub上的主页git仓库地址(https)https://github.com/zq2599/blog_demos.git该我的项目源码的仓库地址,https协定git仓库地址(ssh)git@github.com:zq2599/blog_demos.git该我的项目源码的仓库地址,ssh协定这个git我的项目中有多个文件夹,本次实战的源码在<font color="blue">quarkus-tutorials</font>文件夹下,如下图红框<img src="https://typora-pictures-1253575040.cos.ap-guangzhou.myqcloud.com/image-20220312091203116.png" alt="image-20220312091203116" style="zoom: 80%;" /><font color="blue">quarkus-tutorials</font>是个父工程,外面有多个module,本篇实战的module是<font color="red">basic-di</font>,如下图红框<img src="https://typora-pictures-1253575040.cos.ap-guangzhou.myqcloud.com/image-20220312091404031.png" alt="image-20220312091404031" style="zoom:80%;" />创立demo工程您能够参考《quarkus实战之二:利用的创立、构建、部署》,创立个最简略的web工程,默认生成一个web服务类HobbyResource.java,代码如下,前面的演示代码都写在这个工程中package com.bolingcavalry;import javax.ws.rs.GET;import javax.ws.rs.Path;import javax.ws.rs.Produces;import javax.ws.rs.core.MediaType;import java.time.LocalDateTime;@Path("/actions")public class HobbyResource { @GET @Produces(MediaType.TEXT_PLAIN) public String hello() { return "Hello RESTEasy, " + LocalDateTime.now(); }}接下来,从最根底的创立bean实例创立开始创立bean实例:注解润饰在类上先来看看spring是如何创立bean实例的,回顾文章刚开始的那段代码,myComponent对象来自哪里?持续看spring官网的demo,如下所示,用<font color="blue">Component</font>注解润饰在类上,spring就会实例化MyComponent对象并注册在bean容器中,须要用此bean的时候用Autowired注解就能够注入了@Componentpublic class MyComponent { public void doWork() {}}quarkus框架下也有相似形式,演示类ClassAnnotationBean.java如下,用注解<font color="blue">ApplicationScoped</font>去润饰ClassAnnotationBean.类,如此quarkus就会实例化此类并放入容器中package com.bolingcavalry.service.impl;import javax.enterprise.context.ApplicationScoped;@ApplicationScopedpublic class ClassAnnotationBean { public String hello() { return "from " + this.getClass().getSimpleName(); }}这种注解润饰在类上的bean,被quarkus官网成为<font color="blue">class-based beans</font>应用bean也很简略,如下,用注解<font color="blue">Inject</font>润饰ClassAnnotationBean类型的成员变量即可package com.bolingcavalry;import com.bolingcavalry.service.impl.ClassAnnotationBean;import javax.inject.Inject;import javax.ws.rs.GET;import javax.ws.rs.Path;import javax.ws.rs.Produces;import javax.ws.rs.core.MediaType;import java.time.LocalDateTime;@Path("/classannotataionbean")public class ClassAnnotationController { @Inject ClassAnnotationBean classAnnotationBean; @GET @Produces(MediaType.TEXT_PLAIN) public String hello() { return String.format("Hello RESTEasy, %s, %s", LocalDateTime.now(), classAnnotationBean.hello()); }}如何验证上述代码是否无效?运行服务,再用浏览器拜访<font color="blue">classannotataionbean</font>接口,肉眼判断返回内容是否符合要求,这样尽管可行,但总感觉会被讥嘲低效...还是写一段单元测试代码吧,如下所示,留神要用<font color="blue">QuarkusTest</font>注解润饰测试类(不然服务启动有问题),测试方法中查看了返回码和body,如果后面的依赖注入没问题,则上面的测试应该能通过才对package com.bolingcavalry;import com.bolingcavalry.service.impl.ClassAnnotationBean;import io.quarkus.test.junit.QuarkusTest;import org.junit.jupiter.api.Test;import static io.restassured.RestAssured.given;import static org.hamcrest.CoreMatchers.containsString;@QuarkusTestclass ClassAnnotationControllerTest { @Test public void testGetEndpoint() { given() .when().get("/classannotataionbean") .then() .statusCode(200) // 查看body内容,是否含有ClassAnnotationBean.hello办法返回的字符串 .body(containsString("from " + ClassAnnotationBean.class.getSimpleName())); }}执行命令<font color="blue">mvn clean test -U</font>开始测试,控制台输入如下,提醒测试通过[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0[INFO] [INFO] ------------------------------------------------------------------------[INFO] BUILD SUCCESS[INFO] ------------------------------------------------------------------------[INFO] Total time: 5.702 s[INFO] Finished at: 2022-03-12T15:48:45+08:00[INFO] ------------------------------------------------------------------------如果您的开发工具是IDEA,也能够用它的图形化工具执行测试,如下图,能失去更丰盛的测试信息 ...

September 1, 2023 · 3 min · jiezi

关于后端:PingCode-DevOps-团队企业CICD流水线可能会遇到的问题及解法

CICD 流水线是指一系列自动化的构建、测试和部署步骤,用于将应用程序从开发到生产环境的过程。在 CICD 流水线中,每个步骤都是自动化的,并且在实现后会触发下一个步骤的执行。 CICD 的价值CICD 流水线能够帮忙团队更快地交付产品,缩小手动谬误,并进步软件品质。通过自动化构建、测试和部署过程,团队能够更快地检测和修复谬误,并更快地将新性能推向市场。 CICD 工具链通常由8个局部组成 源代码治理:用于存储和管理应用程序代码的工具,代码治理是 CICD 工具链的根底,提供了代码的版本控制、合作和治理性能,例如 GitLab、GitHub、Bitbucket 等。构建工具:将源代码编译成可执行文件或软件包的工具,例如 Maven、Gradle、Webpack 等。测试工具:自动化执行测试用例并生成测试报告的工具,例如 JUnit、Selenium 等。镜像构建:构建和治理容器镜像的工具,例如 Docker、Kaniko 等。制品治理:寄存业务镜像的仓库,在利用部署时须要拉取。例如:Harbor、Registry、云厂商公有仓库等。监控工具:用于监控流水线运行过程中的状态,如资源占用、负载状况,为流水线性能优化提供数据根底。例如:Prometheus、Grafana、EFK 。部署工具:用于将代码构建实现的制品公布到指标环境中,例如 Jenkins、GitLab CI、Travis CI 等。自动化工具:用于代替扩散脚本执行各种自动化类操作,使执行流程更加清晰有序。例如:Ansible、Puppet 等。 CICD 的演进历史从CI/CD倒退历史来说能够大抵分为以下几个阶段: 1、人工公布阶段:开发或运维人员通常须要手动构建和部署应用程序。这种办法十分耗时且容易出错,因为它须要手动执行多个步骤,并且容易脱漏某些步骤。 2、脚本公布阶段:咱们称之为“半自动化”阶段,人工手动操作的步骤重大困扰了开发和运维人员,过于耗时耗力以及手动执行具备肯定的不可靠性存在。于是开始寻求用脚本来代替一部分人工操作,如 shell、python 脚本,但长此以往仍然耗费开发运维人员大量工夫老本,公布不够标准仍然在继续 3、自动化公布阶段: 为了进一步标准公布流程,躲避人为操作所带来的危险,进步公布效率,少数公司开始构建本人的 CI/CD 公布零碎,这样的益处是无需人工染指,脚本内容不易被篡改。 4、智能化公布阶段:人工智能大数据时代,一些优良的公司曾经开启智能化 CI/CD 零碎,通过引入数据分析、智能预测伎俩,进一步优化公布流程、进步公布效率。 在这四个阶段中,每个阶段都是在前一个阶段的根底上倒退而来的,并且每个阶段都能够提供更高效、更牢靠和更平安的软件交付过程。 进入自动化时代当前,CI/CD 效率虽失去了大幅晋升,但架构的保护过程中仍然会遇到各种各样的问题须要解决,上面我将介绍大多数企业在整个保护过程中可能会遇到的流水线问题以及优化计划。 企业CICD流水线可能会遇到的问题Jenkins 当属业内继续集成老大哥,有着丰盛的插件,实用于大型流水线计划的建设以及大多数场景,受到不少企业用户的追捧,所以本文次要基于 Jenkins 建设的流水线计划为外围从运维角度来讲述可能存在的瓶颈及优化点。 1、Jenkins Master 与 Worker 共用宿主机带来的失联问题有些企业为了不便部署以及尽可能的节俭服务器资源抉择 Jenkins Master 与 Worker 共用宿主机,当流水线数量较少或 stage 消耗资源较少时无显著感知。随着我的项目越来越多,流水线数量的也随之增多,这种架构开始呈现瓶颈,多个 Job 并行构建占用资源较多导致系统负载增高,Master 与Worker 之间的通信也会受到烦扰,重连超时导致 Job 最终失败。 倡议优化计划: Jenkins Master 与 Worker 拆散部署,能够容许Worker有短暂的高负载稳定,不至于拖垮所有流水线Jenkins Master 优化连接时间相干参数Worker 主机负载高优化kubelet 配置系统资源预留,保障系统过程的稳定性kubelet 限度 maxPods 来硬性管制并行构建数,超出限度会进入队列期待Jenkinsfile 中 PodTemplate 局部容器减少 resourceLimitCpu 参数限度最大应用CPU额度这一点是避免某个Pod无限度应用资源导致卡死 ...

August 31, 2023 · 1 min · jiezi