《淘宝技术这十年》读书笔记

news2024/11/28 3:35:37

一. 分布式时代

在系统发展的过程中,架构师的眼光至关重要,作为程序员,只要把功能实现即可,但作为架构师,要考虑系统的扩展性、重用性,对于这种敏锐的感觉,有人说是一种“代码洁癖”。淘宝早期有几个架构师就具备了这种感觉,周锐虹开发的Webx是一个扩展性很强的框架,行癫在这个框架上插入了数据分库路由的模块、Session框架等。在做淘宝后台系统时,同样需要这几个模块,行癫指导我把这些模块单独打成JAR包。

上面说的都是比较小的复用模块,到2006年,我们做了一个商品类目属性的改造,在类目中引入了属性的概念。项目代号叫“泰山”,这是一个举足轻重的项目,这个改变是一个划时代的创新。

在这之前三年时间内,商品的分类都是按照树状一级一级的节点来分的,随着商品数量增长,类目也变得越来越深、复杂。这样,买家如果查找一件商品,就要逐级打开类目,找商品之前要弄清商品的分类。一个很严重的问题,例如男装里有T恤、T恤下面有耐克、耐克有纯棉的,女装也有T恤、T恤下面还是有耐克、耐克下有纯棉,那是先分男女装,再分款式、品牌和材质呢?还是先分品牌,再分款式、材质和男女装呢?

这时一灯说品牌、款式、材质等都可以叫做“属性”,属性是类似Tag(标签)的一个概念,与类目相比更加灵活,这样也缩减了类目的深度。这个思想解决了分类的难题!

从系统角度来看,我们建立了“属性”这样一个数据结构,由于除了类目的子节点有属性外,父节点也可能有属性,于是类目属性合起来也是一个结构化的数据对象。把它独立出来作为一个服务,叫做Catserver(Category Server)。跟类目属性密切关联的商品搜索功能独立出来,叫做Hesper(金星)。Catserver和Hesper供淘宝的前后台系统调用。

现在淘宝的商品类目属性已经是全球最大的,几乎没有什么类目的商品在淘宝上找不到(除违禁品),但最初的类目属性改造完之后,缺乏属性数据,尤其是数码类。从哪里弄这些数据呢?我们跟“中关村在线”合作,拿到了很多数据。

有了类目属性给运营工作带来了很大的便利,我们知道淘宝的运营主要就是类目的运营,什么季节推出什么商品,都要在类目属性上做调整,让买家容易找到。所属商品的卖家要编辑一次自己的商品,如冬天把羽绒衣调整到女装一级目录下,但随着商品量的增长,卖家的工作量越来越大。

到了2008年,我们研究了超市里前后台商品的分类,发现超市前后台商品可以随季节和关联来调整摆放场景(例如著名的啤酒和尿布的关联),后台仓库里要按照自然类目来存储,二者密切关联,却又相互分开。淘宝前台展示的是根据运营需要摆放商品的类目和属性。改造后的类目属性服务取名为Forest(森林,与类目属性有点神似。Catserver还用于提供卖家授权、品牌服务、关键词等相关服务)。类目属性的服务化是淘宝在系统服务化方面做的第一个探索。

2.一种常见的编码错误

虽然个别架构师具备了“代码洁癖”,但淘宝前台系统的业务量和代码量还是呈爆炸式的增长。

业务方总在后面催,开发人员不够就继续招人,招来的人根本看不懂原来的业务,只好摸索着在“合适的地方”加上一些“合适的代码”,看看运行起来像那么回事后,就发布上线。

在这样的恶性循环中,系统越来越肿,业务的耦合性越来越高(高内聚、低耦合),开发的效率越来越低。借用当时较流行的一句话:“你写一段代码,编译一下能通过,半个小时过去了;编译一下没通过,半天就过去了。”在这种情况下,系统出错的概率也逐步增长,这让开发人员苦不堪言。感觉现在很多公司招实习生都是这种感觉。

2007年年底的时候,研发部空降了一位从硅谷来的高管——空闻大师。他是一位温厚的长者,他告诉我们一切要以稳定为中心,所有影响系统稳定的因素都要解决掉。例如:每做一个日常修改,都必须对整个系统回归测试一遍;多个日常修改如果放在一个版本中,要是一个功能没有测试通过,整个系统都不能发布。我们把这个叫做“火车模型”,即任何一个乘客没有上车,都不许发车。这样做最直接的后果就是火车一直晚点,新功能上线更慢,我们能明显感觉到业务放的不满,压力非常大。

现在回过头来看,其实我们并没有理解背后的思路。正是在这种要求下,我们不得不开始改变些东西,例如:把回归测试日常化,每天晚上都跑一遍整个系统的回归。

另外,在这种要求下,我们不得不对这个超级复杂的系统做肢解和重构,其中复用性最高的一个模块:用户信息模块开始拆分出来,我们叫它UIC(User Information Center)。在UIC中,它只处理最基础的用户信息操作,例如getUserById、getUserByName等。

在另一方面,还有两个新兴的业务对系统基础功能的拆分也提出了要求。在那时候,我们做了淘宝旅行(trip.taobao.com)和淘宝彩票(caipiao.taobao.com)两个新业务,这两个新业务在商品的展示和交易的流程上都跟主站的业务不一样,机票是按照航班信息展示的,彩票是按照双色球、数字和足球的赛程来展示的。但用到的会员功能和交易功能是与主站差不多的,当时做起来很纠结,因为如果在主站中做,会有一大半跟主站无关的东西,如果重新做一个,会有很多重复建设。

最终我们决定不再给主站添乱了,就另起炉灶做了两个新的业务系统,从查询商品、购买商品、评价反馈、查看订单这一整个流程都重新写了一套。现在在“我的淘宝”中查看交易记录,还能发现“已买到的宝贝”中把机票和彩票另外列出来了,他们没加入到普通订单中。

当时如果已经把会员、交易、商品、评价这些模块都拆分出来,就不用什么都重做一遍了。

到2008年初,整个主动系统(有了机票、彩票系统之后,把原来的系统叫做主站)的容量已经达到了瓶颈,商品数在1亿个以上,PV在2.5亿个以上,会员数超过了5000万个。这时Oracle的连接池数量都不够用了,数据库的容量到了极限,即使上层系统加机器也无法继续扩容,我们只有把底层的基础服务继续拆分,从底层开始扩容,上层才能扩展,这才能容纳未来三五年的增长。

于是我们启动了一个更大的项目,即把交易这个核心业务模块拆分出来。

原来的淘宝交易除了跟商品管理耦合在一起,还在支付宝和淘宝之间转换,跟支付宝耦合在一起,这会导致系统很复杂,用户体验也很不好。我们把交易的底层业务拆分出来,叫交易中心(TradeCenter,TC),所谓底层业务,就如创建订单、减库存、修改订单状态等原子型的操作;交易的上层业务叫交易管理(TradeManager,TM)例如拍下一件普通商品要对订单、库存、物流进行操作,拍下虚拟商品不需要对物流进行操作,这些在TM中完成。

#p#

3.业务模块化

类目属性、用户中心、交易中心,随着这些模块逐步拆分和服务化改造,我们在系统架构方面也积累了不少经验。到2008年年底就做了一个更大的项目,把淘宝所有的业务都模块化,这是继2004年从LAMP架构到Java架构之间的第二次脱胎换骨。

我们对这个项目取了一个很霸气的名字——“五彩石”(女娲炼石补天用的石头)。这个系统重构的工作非常惊险,有人称为“给一架高速飞行的飞机换发动机”。他们把淘宝的系统拆分成了如下架构。

其中,UIC和Forest在上文已说过,TC、IC、SC分别是交易中心(Trade Center)、商品中心(Item Center)、店铺中心(Shop Center),这些中心级别的服务只提供原子级的业务逻辑,如根据ID查找商品、创建交易、减少库存等操作。

再往上一次是业务系统TM(Trade Manager,交易业务)、IM(Item Manager,商品业务)、SM(Shop Manager,后来改名叫SS,即Shop System,店铺业务)、Detail(商品详情)。

拆分之后,系统之间的交互关系变得非常复杂。

系统这么拆分的好处显而易见,拆分之后每个系统可以单独部署,业务简单,方便扩容;有大量可重用的模块便于开发新的业务;能够做到专人专事,让技术人员更加专注于某一个领域。

这样要解决的问题也很明显,拆分后,系统之间还是必须要打交道的,越往底层的系统,调用它的客户越多,这要求底层系统必须具有超大规模的容量和非常高的可用性。

另外,拆分之后的系统如何通信?这里需要两种中间件系统,一种是实时调用的中间件(淘宝的HSF,高性能服务框架),一种是异步消息通知的中间件(淘宝的Notify)。另外,一个需要解决的问题是用户在A系统登录后,到B系统的时候,用户的登录信息怎么保存?这又设计一个Session框架。再者,还有一个软件工程方面的问题,这么多层的一套系统,怎么去测试它?

二. 中间件

1.HSF

其实互联网网站发展过程类似于超市经营(此处省略超市销售收银的例子,可以想象下沃尔玛排队购物付款的场景吧),只是在技术层面用其他名词来表达而已,例如:有集群、分工、负载均衡、根据QoS分配资源等。

集群:所有收银员提供的都是收银功能,每个收银员都可以完成收款,可以认为所有的收银员构成了一个集群。互联网集群会受限于调度、数据库、机房等。

分工:收银员和打扫卫生的人分开,这种分工容易解决,而这种分工在互联网中是一项重要而复杂的技术,涉及的主要有按功能和数据库的不同拆分系统等。如何拆分和拆分后如何交互是需要面临的两个挑战。隐藏会有高性能通信框架、SOA平台、消息中间件、分布式数据层等基础产品的诞生。

负载均衡:让每个收银台排队差不多长,设立小件通道、团购通道、VIP通道等,这些都可认为是集群带来的负载均衡的问题,从技术层面上实现自然比生活中复杂得多。

根据QoS(Quality of Service,服务质量)分配资源:部分员工仅在晚上加班的机制在生活中不难实现,但对互联网应用而言,就是一件复杂而且极具挑战的事。

而且生活中面对用户增长的情况下,想出这些招应该不难。不过要掌握以上四点涉及的技术就相当复杂了,而且互联网中涉及的其他很多技术还没有在这个例子中展现出来。例如缓存、CDN等优化手段;运转状况监测、功能降级、资源劣化、流控等可用性手段;自建机房、硬件组装等成本控制手段。因此,构建一个互联网网站确实是不容易的,技术含量十足,当然,经营一家超市也不简单。

服务拆分之后,如何取得我需要的服务呢?

在“电视机”上,把每个集群能提供的服务显示出来。你不需要关心哪个人为你服务,当你有需要的时候,头顶的电视机会告诉你哪个服务在哪个区域。当你去到这个区域时,系统会给你找到一个最快的服务通道。

这就是HSF(High-Speed Service Framework)的设计思想:

服务的提供者启动时通过HSF框架向ConfigServer(类似超市的电视机)注册服务信息(接口、版本、超时时间、序列化方式等),ConfigServer上定义了所有可供调用的服务(同一个服务也可能有不同的版本);

服务调用者启动时向ConfigServer注册对哪些服务感兴趣(接口、版本),当服务提供者的信息变化时,ConfigServer向赶兴趣的服务调用者推送新的服务信息列表;调用者在调用时则根据服务信息的列表直接访问相应的服务提供者,无须经过ConfigServer。

我们注意ConfigServer并不会把服务提供者的IP地址推送给服务的调用者,HSF框架会根据负载状况来选择具体的服务器,返回结果给调用者,这不仅统一了服务调用的方式,也实现了“软负载均衡”。平时ConfigServer通过和服务提供者的心跳来感应服务提供者的存活状态。

在HSF的支持下,服务集群对调用者来说是“统一”的,服务之间是“隔离”的,这保证了服务的扩展性和应用的统一性。再加上HSF本身提供的“软负载均衡”,服务层对应用层来说就是一片“私有云”了。

HSF框架以SAR包的方式部署到Jboss、Jetty或Tomcat下,在应用启动时,HSF(High-Speed Service Framework,在开发团队内部有一些人称HSF为“好舒服”)服务随机启用。HSF旨在为淘宝的应用提供一个分布式的服务框架,HSF从分布式应用层面以及统一的发布/调用方式层面为大家提供支持,更容易地开发分布式应用或使用公用功能模块,而不用考虑分布式领域中的各种细节技术,例如:远程通讯、性能损耗、调用的透明化、同步异步调用的问题。

HSF是一个分布式的标准Service方式的RPC(RemoteProcedure Call Protocol,远程过程调用协议)框架。Service的定义基于OSGI的方式,通讯层采用TCP/IP协议。

HSF系统目前每天承担300亿次以上的服务调用,一些读者可能会疑问:既然淘宝的服务化是渐进式的,那么在HSF出现之前,系统之间的调用采用什么方式呢?

这个有点“五花八门”。对于类目的调用方式是Forest打包成一个JAR包,在应用启动时装载到内存中,仅这个JAR包所占用的内存就有800MB之多(因为淘宝的类目数据庞大),对于当时一般只有2GB内存的开发机来说,加载完类目信息后,机器运行速度就非常慢。对于用户信息(UIC)来说,一开始调用方式是Hessian接口,还有一些系统是通过WebService、Socket甚至是HTTP请求来相互调用的。

每种调用方式都涉及各种超时、信息的加解/密、参数的定义等问题,由此可见,在没有HSF之前,系统之间的调用是错综复杂的。而随着系统拆分得越来越多,必须由一个统一的中间层来处理这种问题,HSF就是在这种背景下诞生的。

#p#

2.Notify

HSF解决了服务调用的问题,我们再提出一个很早就说过的问题:用户在银行的网关付钱后,银行需要通知到支付宝,但银行的系统不一定能发出通知;如果通知发出了,不一定能通知到;如果通知到了,不一定不重复通知一遍。

这个状况在支付宝持续了很长时间,非常痛苦。支付宝从淘宝剥离出来时,淘宝和支付宝之间的通信也面临同样的问题,支付宝架构师鲁肃提出用MQ(Message Queue)的方式来解决这个问题,我负责淘宝这边读取消息的模块。但消息数量上来后,常常造成拥堵,消息的顺序也会出错,系统挂掉消息也会挂掉。

然后鲁肃提出做一个系统框架上的解决方案,把要发出的通知存到数据库中,如果实时发送失败,再用一个时间程序来周期性地发送这些通知,系统记录下消息中间状态和时间戳,这样就保证了消息一定能发出,也一定能通知到,且通知带有时间顺序,甚至可以实现失去性的操作。

(PS:这个技术感觉以前做Android类似微信的随手拍软件时非常适用)

在“千岛湖”项目和“五彩石”项目后,淘宝系统拆分成了很多个,他们之间也需要类似的通知。例如,拍下一件商品,在交易管理系统中完成时,它需要通知商品管理系统减少库存,同时旺旺服务系统发送旺旺提醒,通知物流系统上门取货,通知SNS系统分享订单,通知公安局的系统这是骗子等等。

用户一次请求,在底层系统可能产生10次的消息通知。这一大堆的通知信息是异步调用的(如果同步,系统耦合在一起就达不到拆分的目的),这些消息通知需要一个强大的系统提供支持,从消息的数量级上看,比支付宝和淘宝之间的消息量又上了一个层次,于是按照类似的思路,一个更加强大的消息中间件系统就诞生了,它的名字叫做Notify。

Notify是一个分布式的消息中间件系统,支持消息的订阅、发送和消费,其架构图如下所示:

NotifyServer在ConfigServer上注册消息服务,消息的客户端通过ConfigServer订阅消息服务。某个客户端调用NotifyServer发送一条消息,NotifyServer负责把消息发送到所有订阅这个消息的客户端(参照HSF图)。

为了保证消息一定能发出,且对方一定能收到,消息数据本身就需要记录下来,这些信息存放在数据库中。由于消息具有中间状态(已发送、未发送等),应用系统通过Notify可以实现分布式事物——BASE(基本可用Basically Available、软状态Soft State、最终一致Eventually Consistent)。

NotifyServer可以水平扩展,NotifyClient也可以水平扩展,数据库也可以水平扩展。从理论上讲,这个消息系统的吞吐量时没有上限的,现在Notify系统每天承载了淘宝10亿次以上的消息通知。

下图展示了创建一笔交易后,TC(交易中心)向Notify发送一条消息,后续Notify所完成的一系列消息通知。

3.TDDL

有了HSF和Notify的支持,在应用级别中,整个淘宝网的系统可以拆分了,还有一个制约系统规模的更重要的因素就是数据库,也必须拆分。

前面讲过淘宝很早就对数据进行过分库的处理,上层系统连接多个数据库,中间有一个叫做DBRoute的路由来对数据进行统一访问。DBRoute对数据进行多库的操作、数据的整合,让上层系统像操作一个数据库一样操作多个库。随着数据量的增长,对于库表的分发有了更高的要求。例如,你的商品数据到了百亿级别时,任何一个库都无法存放了,于是分成2个、4个…1024个、2048个。分成这么多,数据能存放了,那怎么查询它?

这时候,数据查询的中间件就要能够承担这个重任了,它对上层来说,必须像查询一个数据库一样来查询数据,还要想查询一个数据库一样快(每条查询在几毫秒内完成),TDDL就承担了这样一个工作。

另外,加上数据的备份、复制、主备切换等功能,这一套系统都在TDDL中完成。在外面有些系统也用DAL(数据访问层)这个概念来命名这个中间件。TDDL实现了下面三个主要的特性:

1).数据访问路由——将针对数据的读写请求发送到最适合的地方

2).数据的多向非对称复制——一次写入,多点读取

3).数据存储的自由扩展——不再受限于单台机器的容量瓶颈与速度瓶颈,平滑迁移

下图展示了TDDL所处的位置:

大家逐渐发现,如果按照业务的发展规模和速度,那么使用高端存储和小型机的Oracle存储的成本将难以控制,于是降低成本就成了必然。如何能够在不影响业务正常发展的前提下,解决成本问题呢?

“对一部分数据库使用MySQL”,DBA们的决策是这样,于是分布式数据层的重担就落到了华黎的头上。当时的需求如下:对外统一一切数据访问、支持缓存和文件存储系统、能够在Oracle和MySQL之间自由切换、支持搜索引擎。

那么,如何实现分布式Join(连接)?(跨节点后简单Join就会变成M*N台机器的合并,代价太大)如何实现高速多维度查询?如何实现分布式事务?

于是动手我们自己做,名字叫Taobao Distributed Data Layer(TDDL,外号“头都打了”),学习开源的Amoeba Proxy。这就是TDDL 1.0时代。

粗略统计下来,TDDL已经走过了4年时间,满足了近700个业务应用的使用需求。其中有交易商品评价用户等核心数据,也有不那么有名的中小型应用。量变产生质变,如何能够更好地帮助这些业务以更低的成本完成业务需求,将成为数据层未来最重要的挑战。

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

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

相关文章

使用双屏时两个屏幕的色调、亮度不一样如何设置?

当使用双屏时,即使两个屏幕的型号一致也可能存在色差的问题(色调不一致,亮度不一致),以下是解决此问题的方法。 Step1.同时按下两个屏幕下方的ok按钮 Step2.此时会进入显示器的OSD界面 Step3.通过按键切换菜单 Step4.…

节省35% MCU开发成本的红外智能洗手器运用方案,N9300-S16音乐芯片

随着全国人民生活水平的逐步提升以及近期疫情影响,公民的健康保护意识也越来越强,洗手液越来越被人们重视以及提倡,即时在受疫情影响是2022年洗手液市场规模也是上升至恐怖34亿元产值;而近年来自动感应洗手液器凭借实用性、便携性…

APP测试面试题快问快答(三)

11. App安装测试的主要内容有哪些? App是客户端程序,客户端程序就需要进行安装才能使用,因此需要测试安装、卸载、升级测试 关注点:正常场景、异常场景。 正常场景: 1. 在不同的操作系统上安装 2. 从不同的安装渠…

windows10安装ElasticSearch

一 安装 Java环境 ElasticSearch使用Java开发的,依赖Java环境,安装 ElasticSearch 之前,需要先安装一个较新版本的 Java,jdk 1.8版本太低了,需要安装jdk 11或更高版本。 Java安装方法请参考 Java 15环境安装 。 二 …

详解字典树原理,代码分析leetcode208. 实现 Trie (前缀树)

0、引言 本文介绍一种能够偶快速查找字符串的树形数据结构-----字典树。介绍其原理,以及通过leetcode208题目这个实例,用数组动手实现一棵字典树,并完成其增、查字符串、查字符串前缀的功能。 1、字典树的应用场景 询问一个单词b&#xff0c…

Mujoco 加载机器人模型(三)

目录 .1 简介 1.1 urdf概述 ​编辑 1.2 导出urdf为可用的xml​编辑 1.3 导出测试​编辑 .2 修改 2.1 添加平面和物体 2.2 关节修改 2.2.1 group 2.2.2 关节修改 2.2.3 关节 解压提供的ur5后 修改compiler的 meshdir路径 <mujoco model"ur5"><compi…

一条耗时100ms的SQL把系统搞崩了

一个项目上线了两个月&#xff0c;除了一些反馈的优化和小Bug之外&#xff0c;项目一切顺利。前期是属于推广阶段&#xff0c;可能使用人员没那么多&#xff0c;当然对于项目部署肯定提前想到并发量了&#xff0c;所以早就把集群安排上&#xff0c;而且还在测试环境搞了一下压测…

2023年的深度学习入门指南(15) - 大模型的幻觉

2023年的深度学习入门指南(15) - 大模型的幻觉 大模型的能力最另人惊讶的&#xff0c;一个是强大的能力&#xff0c;另一个就是时不时一本正经地胡说八道。如果你用的是小一点的模型&#xff0c;可能还见过输出循环内容之类的情况。我们将这种生成不良内容的现象称为幻觉-hall…

3d动画用云渲染靠谱吗?

3d动画是一种利用计算机技术制作的动画形式&#xff0c;它可以模拟真实世界的物体和场景&#xff0c;创造出各种惊人的效果和视觉体验。3d动画广泛应用于影视、游戏、广告、教育等领域&#xff0c;成为当今最流行的艺术表现形式之一。据统计&#xff0c;2019年全球3d动画市场规…

吴恩达老师《机器学习》课后习题1之线性回归

在学习这些内容之前&#xff0c;需要学习python数据分析相关内容&#xff1a; numpy&#xff1a;科学计算库&#xff0c;处理多维数组&#xff0c;进行数据分析 pandas&#xff1a;基于numpy的一种工具&#xff0c;该工具是为了解决数据分析任务而创建的 matplotlib&#xff1a…

Atcoder Beginner Contest 297

A - Double Click AC代码&#xff1a; #include<iostream> #include<algorithm> #include<cstring> using namespace std; const int N110; int t[N]; int main() {int n,d;cin>>n>>d;for(int i1;i<n;i) cin>>t[i];bool flagfalse;i…

数据结构05:树的定义与双亲表示法[持续更新中]

参考用书&#xff1a;王道考研《2024年 数据结构考研复习指导》 参考用书配套视频&#xff1a;5.1.1 树的定义和基本术语_哔哩哔哩_bilibili 特别感谢&#xff1a; Chat GPT老师[部分名词解释、修改BUG]、BING老师[封面图]~ 备注&#xff1a;博文目前是未完成的状态&#xff…

【数据结构】哈希表(Map和Set)

文章目录 Map和Set模型MapTreeMap和HashMap对比Entry<K,V>常用方法 SetTreeSet和HashSet对比常用方法 OJ练习只出现一次数字复制带随机指针的链表宝石与石头坏键盘打字前K个高频单词 哈希表哈希表所用数据结构解决哈希冲突闭散列开散列 避免哈希冲突哈希函数设计负载因子…

springboot bean的生命周期

Spring Boot是一个非常流行的Java框架&#xff0c;它提供了许多功能&#xff0c;使开发人员可以快速构建和部署应用程序。其中一个非常重要的功能是Spring Boot Bean的生命周期。在本文中&#xff0c;我们将深入探讨Spring Boot Bean的生命周期&#xff0c;以及如何最大化利用它…

光伏发电系统最大功率跟踪控制MATLAB仿真模型(电导增量法+扰动观察法)

光伏发电系统最大功率跟踪控制MATLAB仿真模型&#xff08;电导增量法扰动观察法参考文献&#xff09;资源-CSDN文库https://download.csdn.net/download/weixin_56691527/87878528 模型介绍&#xff1a; 模型主要包含光伏电池模块、直流升压模块、以及最大功率跟踪控制模块。…

深度学习--神经网络全面知识点总结(持续更新中)

文章目录 神经网络基础1.1 什么是神经网络&#xff1f;1.2 神经元和激活函数1.3 前向传播和反向传播1.4 损失函数和优化算法 深度神经网络2.1 卷积神经网络&#xff08;CNN&#xff09;2.2 循环神经网络&#xff08;RNN&#xff09;2.3 长短期记忆网络&#xff08;LSTM&#xf…

C#可视化 商品信息管理系统(具体做法及全部代码)

目录 题目&#xff1a; 效果图&#xff1a; 数据库&#xff1a; 做法&#xff1a; 主页面添加menustrip&#xff0c;之后添加两个窗体双击事件&#xff0c;双击下拉区域就好了。 添加界面 查询按钮功能 datagirdview设置 全部代码&#xff1a; DBHelper类 From1主窗体代…

【并发篇】01 java中的线程状态

Java线程分为6种状态&#xff1a; &#xff08;1&#xff09;新建NEW&#xff1a;用new关键字创建的线程就是新建状态&#xff0c;这时候还没有和系统底层真正的线程关联起来&#xff0c;还仅仅只是一个java对象&#xff0c;所以这个时候这个线程不会被系统分配给cpu。 &#…

【云原生】docker

容器化越来越受欢迎&#xff0c;因为容器是&#xff1a; ●灵活&#xff1a;即使是最复杂的应用也可以集装箱化。 ●轻量级&#xff1a;容器利用并共享主机内核。 ●可互换&#xff1a;可以即时部署更新和升级。 ●便携式&#xff1a;可以在本地构建&#xff0c;部署到云&#…

shel脚本基础1——变量基础、脚本运算符

文章目录 一、变量基础二、bash变量类型三、脚本基础知识3.1 脚本测试命令3.2 shell运算符3.3 命令逻辑关系3.4 bash条件判断3.4.1 条件测试的表达式3.4.2 整数测试3.4.2 字符测试3.4.3 文件测试3.4.4 组合测试条件 一、变量基础 变量的含义&#xff1a; 变量可以通过变量名访问…