• 关于 移动查询处理是什么 的搜索结果

问题

【精品回答】移动推送

montos 2020-04-09 09:57:11 14 浏览量 回答数 1

回答

首先,我们先来聊聊各类数据模型。下列相关信息参考自Emil Eifrem的博文及NoSQL数据库说明。文档类数据库传承:受Lotus Notes启发而来。数据模型:文档汇总,包括键-值汇总。实例: CouchDB, MongoDB优势: 数据建模自然、程序员易于上手、开发流程短、兼容网页模式、便于达成CRUD(即添加、查询、更新及删除的简称)。图形类数据库传承:来自 Euler 及图形理论。数据模型:节点及关系,二者结合能够保持键-值间的成对状态实例: AllegroGraph, InfoGrid, Neo4j优势:轻松玩转复杂的图形问题、处理速度快关系类数据库传承:源自 E. F. Codd在大型共享数据库中所提出的数据关系模型理论数据模型:以关系组为基础实例: VoltDB, Clustrix, MySQL优势:性能强大、联机事务处理系统扩展性好、支持SQL访问、视图直观、擅长处理交易关系、与程序员间的交互效果优异面向对象类数据库传承:源自图形数据库方面的研究成果数据模型: 对象实例: Objectivity, Gemstone优势:擅长处理复杂的对象模型、快速的键-值访问及键-功能访问并且兼具图形数据库的各类功能键-值存储传承: Amazon Dynamo中的paper概念及分布式hash表数据模型:对成对键-值的全局化汇总实例: Membase, Riak优势:尺寸掌控得当、擅长处理持续的小规模读写需求、速度快、程序员易于上手BigTable Clones传承自:谷歌BigTable中的paper概念数据模型:纵列群,即在某个表格模型中,每行在理论上至少可以有一套单独的纵列配置实例: HBase, Hypertable, Cassandra优势:尺寸掌控得当、擅长应对大规模写入负载、可用性高、支持多数据中心、支持映射简化数据结构类服务传承: 不明实例: Redis数据模型: 执行过程基于索引、列表、集合及字符串值优势:为数据库应用引入前所未有的新鲜血液网格类数据库传承:源自数据网格及元组空间研究数据模型:基于空间的构架实例: GigaSpaces, Coherence优势:优良的性能表现及上佳的交易处理扩展性我们该为自己的应用程序选择哪套方案?选择的关键在于重新思考我们的应用程序如何依据不同数据模型及不同产品进行有针对性的协同工作。即用正确的数据模型处理对应的现实任务、用正确的产品解决对应的现实问题。要探究哪类数据模型能够切实为我们的应用程序提供帮助,可以参考“到底NoSQL能在我们的工作中发挥什么作用?”一文。在这篇文章中,我试着将各种不同特性、不同功能的常用创建系统中的那些非常规的应用实例综合起来。将应用实例中的客观需求与我们的选择联系起来。这样大家就能够逆向分析出我们的基础架构中适合引入哪些产品。至于具体结论是NoSQL还是SQL,这已经不重要了。关注数据模型、产品特性以及自身需要。产品总是将各种不同的功能集中起来,因此我们很难单纯从某一类数据模型构成方式的角度直接找到最合用的那款。对功能及特性的需求存在优先级,只要对这种优先级具备较为清晰的了解,我们就能够做出最佳选择。如果我们的应用程序需要…复杂的交易:因为没人愿意承受数据丢失,或者大家更倾向于一套简单易用的交易编程模式,那么请考虑使用关系类或网格类数据库。例如:一套库存系统可能需要完整的ACID(即数据库事务执行四要素:原子性、一致性、隔离性及持久性)。顾客选中了一件产品却被告知没有库存了,这类情况显然容易引起麻烦。因为大多数时候,我们想要的并不是额外补偿、而只是选中的那件货品。若是以扩展性为优先,那么NoSQL或SQL都能应对自如。这种情况下我们需要关注那些支持向外扩展、分类处理、实时添加及移除设备、负载平衡、自动分类及整理并且容错率较高的系统。要求持续保有数据库写入功能,则需要较高的可用性。在这种情况下不妨关注BigTable类产品,其在一致性方面表现出众。如有大量的小规模持续读写要求,也就是说工作负载处于波动状态,可以关注文档类、键-值类或是那些提供快速内存访问功能的数据库。引入固态硬盘作为存储媒介也是不错的选择。以社交网络为实施重点的话,我们首先想到的就是图形类数据库;其次则是Riak这种关系类数据库。具备简单SQL功能的常驻内存式关系数据库基本上就可以满足小型数据集合的需求。Redis的集合及列表操作也能发挥作用。如果我们的应用程序需要…在访问模式及数据类型多种多样的情况下,文档类数据库比较值得考虑。这类数据库不仅灵活性好,性能表现也可圈可点。需要完备的脱机报告与大型数据集的话,首选产品是Hadoop,其次则是支持映射简化的其它产品。不过仅仅支持映射简化还不足以提供如Hadoop一样上佳的处理能力。如果业务跨越数个数据中心,Bigtable Clone及其它提供分布式选项的产品能够应对由地域距离引起的延迟现象,并具备较好的分区兼容性。要建立CRUD应用程序,首选文档类数据库。这类产品简化了从外部访问复杂数据的过程。需要内置搜索功能的话,推荐Riak。要对数据结构中的诸如列表、集合、队列及发布/订阅信息进行操作,Redis是不二之选。其具备的分布式锁定、覆盖式日志及其它各种功能都会在这类应用状态下大放异彩。将数据以便于处理的形式反馈给程序员(例如以JSON、HTTP、REST、Javascript这类形式),文档类数据库能够满足这类诉求,键-值类数据库效果次之。如果我们的应用程序需要…以直观视图的形式进行同步交易,并且具备实时数据反馈功能,VoltDB算得上一把好手。其数据汇总以及时间窗口化的表现都非常抢眼。若是需要企业级的支持及服务水平协议,我们需要着眼于特殊市场。Membase就是这样一个例子。要记录持续的数据流,却找不到必要的一致性保障?BigTable Clone交出了令人满意的答卷,因为其工作基于分布式文件系统,所以可以应对大量的写入操作。要让操作过程变得尽可能简单,答案一定在托管或平台即服务类方案之中。它们存在的目的正是处理这类要求。要向企业级客户做出推荐?不妨考虑关系类数据库,因为它们的长项就是具备解决繁杂关系问题的技术。如果需要利用动态方式建立对象之间的关系以使其具有动态特性,图形类数据库能帮上大忙。这类产品往往不需要特定的模式及模型,因此可以通过编程逐步建立。S3这类存储服务则是为支持大型媒体信息而生。相比之下NoSQL系统则往往无法处理大型二进制数据块,尽管MongoDB本身具备文件服务功能。如果我们的应用程序需要…有高效批量上传大量数据的需求?我们还是得找点有对应功能的产品。大多数产品都无法胜任,因为它们不支持批量操作。文档类数据库或是键-值类数据库能够利用流畅的模式化系统提供便捷的上传途径,因为这两类产品不仅支持可选区域、添加区域及删除区域,而且无需建立完整的模式迁移框架。要实现完整性限制,就得选择一款支持SQL DLL的产品,并在存储过程或是应用程序代码中加以运行。对于协同工作极为依赖的时候就要选择图形类数据库,因为这类产品支持在不同实体间的迅速切换。数据的移动距离较短且不必经过网络时,可以在预存程序中做出选择。预存程序在关系类、网格类、文档类甚至是键-值类数据库中都能找到。如果我们的应用程序需要…键-值存储体系擅长处理BLOB类数据的缓存及存储问题。缓存可以用于应对网页或复杂对象的存储,这种方案能够降低延迟、并且比起使用关系类数据库来说成本也较低。对于数据安全及工作状态要求较高的话可以尝试使用定制产品,并且在普遍的工作范畴(例如向上扩展、调整、分布式缓存、分区及反规范化等等)之外一定要为扩展性(或其它方面)准备解决方案。多样化的数据类型意味着我们的数据不能简单用表格来管理或是用纵列来划分,其复杂的结构及用户组成(也可能还有其它各种因素)只有文档类、键-值类以及Bigtable Clone这些数据库才能应付。上述各类数据库都具备极为灵活的数据类型处理能力。有时其它业务部门会需要进行快速关系查询,引入这种查询方式可以使我们不必为了偶尔的查看而重建一切信息。任何支持SQL的数据库都能实现这类查询。至于在云平台上运行并自动充分利用云平台的功能——这种美好的愿望目前还只能是愿望。如果我们的应用程序需要…支持辅助索引,以便通过不同的关键词查找数据,这要由关系类数据库及Cassandra推出的新辅助索引系统共同支持才能实现。创建一套处于不断增长中的数据集合(真正天文数量级的数据)然而访问量却并不大,那么Bigtable Clone是最佳选择,因为它会将数据妥善安排在分布式文件系统当中。需要整合其它类型的服务并确保数据库提供延后写入同步功能?那最好的实现方式是捕捉数据库的各种变化并将其反馈到其它系统中以保障运作的一致性。通过容错性检查了解系统对供电中断、隔离及其它故障情况的适应程度。若是当前的某项技术尚无人问津、自己却感觉大有潜力可挖,不妨在这条路上坚持走下去。这种情况有时会带来意料之外的美好前景。尝试在移动平台上工作并关注CouchDB及移动版couchbase。哪种方案更好?25%的状态改善尚不足以让我们下决心选择NoSQL。选择标准是否恰当取决于实际情况。这类标准对你的方案有指导意义吗?如果你的公司尚处于起步阶段,并且需要尽快推出自己的产品,这时不要再犹豫不决了。无论是SQL还是NoSQL都可以作为参考。

a123456678 2019-12-02 03:00:14 0 浏览量 回答数 0

回答

算法是比较复杂又基础的学科,每个学编程的人都会学习大量的算法。而根据统计,以下这18个问题是面试中最容易遇到的,本文给出了一些基本答案,供算法方向工程师或对此感兴趣的程序员参考。 1)请简单解释算法是什么? 算法是一个定义良好的计算过程,它将一些值作为输入并产生相应的输出值。简单来说,它是将输入转换为输出的一系列计算步骤。 2)解释什么是快速排序算法? 快速排序算法能够快速排序列表或查询。它基于分割交换排序的原则,这种类型的算法占用空间较小,它将待排序列表分为三个主要部分: ·小于Pivot的元素 ·枢轴元素Pivot(选定的比较值) ·大于Pivot的元素 3)解释算法的时间复杂度? 算法的时间复杂度表示程序运行完成所需的总时间,它通常用大O表示法来表示。 4)请问用于时间复杂度的符号类型是什么? 用于时间复杂度的符号类型包括: ·Big Oh:它表示小于或等于目标多项式 ·Big Omega:它表示大于或等于目标多项式 ·Big Theta:它表示与目标多项式相等 ·Little Oh:它表示小于目标多项式 ·Little Omega:它表示大于目标多项式 5)解释二分法检索如何工作? 在二分法检索中,我们先确定数组的中间位置,然后将要查找的值与数组中间位置的值进行比较,若小于数组中间值,则要查找的值应位于该中间值之前,依此类推,不断缩小查找范围,直至得到最终结果。 6)解释是否可以使用二分法检索链表? 由于随机访问在链表中是不可接受的,所以不可能到达O(1)时间的中间元素。因此,对于链表来说,二分法检索是不可以的(对顺序链表或排序后的链表是可以用的)。 7)解释什么是堆排序? 堆排序可以看成是选择排序的改进,它可以定义为基于比较的排序算法。它将其输入划分为未排序和排序的区域,通过不断消除最小元素并将其移动到排序区域来收缩未排序区域。 8)说明什么是Skip list? Skip list数据结构化的方法,它允许算法在符号表或字典中搜索、删除和插入元素。在Skip list中,每个元素由一个节点表示。搜索函数返回与key相关的值的内容。插入操作将指定的键与新值相关联,删除操作可删除指定的键。 9)解释插入排序算法的空间复杂度是多少? 插入排序是一种就地排序算法,这意味着它不需要额外的或仅需要少量的存储空间。对于插入排序,它只需要将单个列表元素存储在初始数据的外侧,从而使空间复杂度为O(1)。 10)解释什么是“哈希算法”,它们用于什么? “哈希算法”是一个哈希函数,它使用任意长度的字符串,并将其减少为唯一的固定长度字符串。它用于密码有效性、消息和数据完整性以及许多其他加密系统。 11)解释如何查找链表是否有循环? 要知道链表是否有循环,我们将采用两个指针的方法。如果保留两个指针,并且在处理两个节点之后增加一个指针,并且在处理每个节点之后,遇到指针指向同一个节点的情况,这只有在链表有循环时才会发生。 12)解释加密算法的工作原理? 加密是将明文转换为称为“密文”的密码格式的过程。要转换文本,算法使用一系列被称为“键”的位来进行计算。密钥越大,创建密文的潜在模式数越多。大多数加密算法使用长度约为64到128位的固定输入块,而有些则使用流方法。 13)列出一些常用的加密算法? 一些常用的加密算法是: ·3-way ·Blowfish ·CAST ·CMEA ·GOST ·DES 和Triple DES ·IDEA ·LOKI等等 14)解释一个算法的最佳情况和最坏情况之间有什么区别? ·最佳情况:算法的最佳情况解释为算法执行最佳的数据排列。例如,我们进行二分法检索,如果目标值位于正在搜索的数据中心,则这就是最佳情况,最佳情况时间复杂度为0。 ·最差情况:给定算法的最差输入参考。例如快速排序,如果选择关键值的子列表的最大或最小元素,则会导致最差情况出现,这将导致时间复杂度快速退化到O(n2)。 15)解释什么是基数排序算法? 基数排序又称“桶子法”,是通过比较数字将其分配到不同的“桶里”来排序元素的。它是线性排序算法之一。 16)解释什么是递归算法? 递归算法是一个解决复杂问题的方法,将问题分解成较小的子问题,直到分解的足够小,可以轻松解决问题为止。通常,它涉及一个调用自身的函数。 17)提到递归算法的三个定律是什么? 所有递归算法必须遵循三个规律: ·递归算法必须有一个基点 ·递归算法必须有一个趋向基点的状态变化过程 ·递归算法必须自我调用 18)解释什么是冒泡排序算法? 冒泡排序算法也称为下沉排序。在这种类型的排序中,要排序的列表的相邻元素之间互相比较。如果它们按顺序排列错误,将交换值并以正确的顺序排列,直到最终结果“浮”出水面。 满意记得采纳哈

玄学酱 2019-12-02 01:18:44 0 浏览量 回答数 0

新用户福利专场,云服务器ECS低至102元/年

新用户专场,1核2G 102元/年起,2核4G 699.8元/年起

问题

Salesforce爱因斯坦聊天机器人介绍

赛思salesnow 2019-12-01 21:59:04 2144 浏览量 回答数 0

问题

如何在MySQL数据库中维护递归不变式?

保持可爱mmm 2019-12-01 21:58:03 4 浏览量 回答数 1

问题

ES 在数据量很大的情况下(数十亿级别)如何提高查询效率啊?【Java问答学堂】28期

剑曼红尘 2020-05-28 09:45:28 15 浏览量 回答数 1

回答

大数据是指无法在一定时间内用常规软件工具对其内容进行抓取、管理和处理的数据集合。大数据技术,是指从各种各样类型的数据中,快速获得有价值信息的能力。适用于大数据的技术,包括大规模并行处理(MPP)数据库,数据挖掘电网,分布式文件系统,分布式数据库,云计算平台,互联网,和可扩展的存储系统。   大数据有四个基本特征:一、数据体量巨大(Vomule),二、数据类型多样(Variety),三、处理速度快(Velocity),四、价值密度低(Value)。   在大数据的领域现在已经出现了非常多的新技术,这些新技术将会是大数据收集、存储、处理和呈现最强有力的工具。大数据处理一般有以下几种关键性技术:大数据采集、大数据预处理、大数据存储及管理、大数据分析及挖掘、大数据展现和应用(大数据检索、大数据可视化、大数据应用、大数据安全等)。   大数据处理之一:采集。大数据的采集是指利用多个数据库来接收发自客户端(Web、App或者传感器形式等)的数据,并且用户可以通过这些数据库来进行简单的查询和处理工作。比如,电商会使用传统的关系型数据库MySQL和Oracle等来存储每一笔事务数据,除此之外,Redis和MongoDB这样的NoSQL数据库也常用于数据的采集。   在大数据的采集过程中,其主要特点和挑战是并发数高,因为同时有可能会有成千上万的用户来进行访问和操作,比如火车票售票网站和淘宝,它们并发的访问量在峰值时达到上百万,所以需要在采集端部署大量数据库才能支撑。并且如何在这些数据库之间进行负载均衡和分片的确是需要深入的思考和设计。   大数据处理之二:导入和预处理。虽然采集端本身会有很多数据库,但是如果要对这些海量数据进行有效的分析,还是应该将这些来自前端的数据导入到一个集中的大型分布式数据库,或者分布式存储集群,并且可以在导入基础上做一些简单的清洗和预处理工作。也有一些用户会在导入时使用来自Twitter的Storm来对数据进行流式计算,来满足部分业务的实时计算需求。   导入与预处理过程的特点和挑战主要是导入的数据量大,每秒钟的导入量经常会达到百兆,甚至千兆级别。   大数据处理之三:统计和分析。统计与分析主要利用分布式数据库,或者分布式计算集群来对存储于其内的海量数据进行普通的分析和分类汇总等,以满足大多数常见的分析需求,在这方面,一些实时性需求会用到EMC的GreenPlum、Oracle的Exadata,以及基于MySQL的列式存储Infobright等,而一些批处理,或者基于半结构化数据的需求可以使用Hadoop。   统计与分析这部分的主要特点和挑战是分析涉及的数据量大,其对系统资源,特别是I/O会有极大的占用。   大数据处理之四:挖掘。与前面统计和分析过程不同的是,数据挖掘一般没有什么预先设定好的主题,主要是在现有数据上面进行基于各种算法的计算,从而起到预测(Predict)的效果,从而实现一些高级别数据分析的需求。比较典型算法有用于聚类的Kmeans、用于统计学习的SVM和用于分类的NaiveBayes,主要使用的工具有Hadoop的Mahout等。该过程的特点和挑战主要是用于挖掘的算法很复杂,并且计算涉及的数据量和计算量都很大,常用数据挖掘算法都以单线程为主。   整个大数据处理的普遍流程至少应该满足这四个方面的步骤,才能算得上是一个比较完整的大数据处理。   大数据的处理方式大致分为数据流处理方式和批量数据处理方式两种。数据流处理的方式适合用于对实时性要求比较高的场合中。并不需要等待所有的数据都有了之后再进行处理,而是有一点数据就处理一点,更多地要求机器的处理器有较快速的性能以及拥有比较大的主存储器容量,对辅助存储器的要求反而不高。批量数据处理方式是对整个要处理的数据进行切割划分成小的数据块,之后对其进行处理。重点在于把大化小——把划分的小块数据形成小任务,分别单独进行处理,并且形成小任务的过程中不是进行数据传输之后计算,而是将计算方法(通常是计算函数——映射并简化)作用到这些数据块最终得到结果。   当前,对大数据的处理分析正成为新一代信息技术融合应用的节点。移动互联网、物联网、社交网络、数字家庭、电子商务等是新一代信息技术的应用形态,这些应用不断产生大数据。通过对不同来源数据的管理、处理、分析与优化,将结果反馈到上述应用中,将创造出巨大的经济和社会价值。大数据也是信息产业持续高速增长的新引擎。面对大数据市场的新技术、新产品、新业态会不断涌现。在硬件与集成设备领域,大数据将对芯片、存储产业产生重要影响,还将催生一体化数据存储处理服务器、内存计算等市场。在软件与服务领域,大数据将引发数据快速处理分析、数据挖掘技术和软件产品的发展。大数据利用将成为提高核心竞争力的关键因素。各行各业的决策正在从“业务驱动”转变为“数据驱动”。对大数据的分析可以使零售商实时掌握市场动态并迅速做出应对;可以为商家制定更加精准有效的营销策略提供决策支持;可以帮助企业为消费者提供更加及时和个性化的服务;在医疗领域,可提高诊断准确性和药物有效性;在公共事业领域,大数据也开始发挥促进经济发展、维护社会稳定等方面的重要作用。大数据时代科学研究的方法手段将发生重大改变。例如,抽样调查是社会科学的基本研究方法。在大数据时代,可通过实时监测,跟踪研究对象在互联网上产生的海量行为数据,进行挖掘分析,揭示出规律性的东西,提出研究结论和对策。   目前大数据在医疗卫生领域有广为所知的应用,公共卫生部门可以通过覆盖全国的患者电子病历数据库进行全面疫情监测。5千万条美国人最频繁检索的词条被用来对冬季流感进行更及时准确的预测。学术界整合出2003年H5N1禽流感感染风险地图,研究发行此次H7N9人类病例区域。社交网络为许多慢性病患者提供了临床症状交流和诊治经验分享平台,医生借此可获得院外临床效果统计数据。基于对人体基因的大数据分析,可以实现对症下药的个性化治疗。   在医药研发方面,大数据的战略意义在于对各方面医疗卫生数据进行专业化处理,对患者甚至大众的行为和情绪的细节化测量成为可能,挖掘其症状特点、行为习惯和喜好等,找到更符合其特点或症状的药品和服务,并针对性的调整和优化。在医药研究开发部门或公司的新药研发阶段,能够通过大数据技术分析来自互联网上的公众疾病药品需求趋势,确定更为有效率的投入产品比,合理配置有限研发资源。除研发成本外,医药公司能够优化物流信息平台及管理,更快地获取回报,一般新药从研发到推向市场的时间大约为13年,使用数据分析预测则能帮助医药研发部门或企业提早将新药推向市场。   在疾病诊治方面,可通过健康云平台对每个居民进行智能采集健康数据,居民可以随时查阅,了解自身健康程度。同时,提供专业的在线专家咨询系统,由专家对居民健康程度做出诊断,提醒可能发生的健康问题,避免高危病人转为慢性病患者,避免慢性病患者病情恶化,减轻个人和医保负担,实现疾病科学管理。对于医疗卫生机构,通过对远程监控系统产生数据的分析,医院可以减少病人住院时间,减少急诊量,实现提高家庭护理比例和门诊医生预约量的目标。武汉协和医院目前也已经与市区八家社区卫生服务中心建立远程遥控联系,并将在未来提供“从医院到家”的服务。在医疗卫生机构,通过实时处理管理系统产生的数据,连同历史数据,利用大数据技术分析就诊资源的使用情况,实现机构科学管理,提高医疗卫生服务水平和效率,引导医疗卫生资源科学规划和配置。大数据还能提升医疗价值,形成个性化医疗,比如基于基因科学的医疗模式。   在公共卫生管理方面,大数据可以连续整合和分析公共卫生数据,提高疾病预报和预警能力,防止疫情爆发。公共卫生部门则可以通过覆盖区域的卫生综合管理信息平台和居民信息数据库,快速监测传染病,进行全面疫情监测,并通过集成疾病监测和响应程序,进行快速响应,这些都将减少医疗索赔支出、降低传染病感染率。通过提供准确和及时的公众健康咨询,将会大幅提高公众健康风险意识,同时也将降低传染病感染风险。   在居民健康管理方面,居民电子健康档案是大数据在居民健康管理方面的重要数据基础,大数据技术可以促进个体化健康事务管理服务,改变现代营养学和信息化管理技术的模式,更全面深入地从社会、心理、环境、营养、运动的角度来对每个人进行全面的健康保障服务,帮助、指导人们成功有效地维护自身健康。另外,大数据可以对患者健康信息集成整合,在线远程为诊断和治疗提供更好的数据证据,通过挖掘数据对居民健康进行智能化监测,通过移动设备定位数据对居民健康影响因素进行分析等等,进一步提升居民健康管理水平。   在健康危险因素分析方面,互联网、物联网、医疗卫生信息系统及相关信息系统等普遍使用,可以系统全面地收集健康危险因素数据,包括环境因素(利用GIS系统采集大气、土壤、水文等数据),生物因素(包括致病性微生物、细菌、病毒、真菌等的监测数据),经济社会因素(分析经济收入、营养条件、人口迁徙、城镇化、教育就业等因素数据),个人行为和心理因素,医疗卫生服务因素,以及人类生物遗传因素等,利用大数据技术对健康危险因素进行比对关联分析,针对不同区域、人群进行评估和遴选健康相关危险因素及制作健康监测评估图谱和知识库也成为可能,提出居民健康干预的有限领域和有针对性的干预计划,促进居民健康水平的提高。 答案来源于网络

养狐狸的猫 2019-12-02 02:15:59 0 浏览量 回答数 0

问题

【Java问答学堂】10期 es 在数据量很大的情况下(数十亿级别)如何提高查询效率啊?

剑曼红尘 2020-04-28 14:16:56 0 浏览量 回答数 1

回答

面试官心理分析 这个问题是肯定要问的,说白了,就是看你有没有实际干过 es,因为啥?其实 es 性能并没有你想象中那么好的。很多时候数据量大了,特别是有几亿条数据的时候,可能你会懵逼的发现,跑个搜索怎么一下 5~10s,坑爹了。第一次搜索的时候,是 5~10s,后面反而就快了,可能就几百毫秒。 你就很懵,每个用户第一次访问都会比较慢,比较卡么?所以你要是没玩儿过 es,或者就是自己玩玩儿 demo,被问到这个问题容易懵逼,显示出你对 es 确实玩儿的不怎么样? 面试题剖析 说实话,es 性能优化是没有什么银弹的,啥意思呢?就是不要期待着随手调一个参数,就可以万能的应对所有的性能慢的场景。也许有的场景是你换个参数,或者调整一下语法,就可以搞定,但是绝对不是所有场景都可以这样。 性能优化的杀手锏——filesystem cache 你往 es 里写的数据,实际上都写到磁盘文件里去了,查询的时候,操作系统会将磁盘文件里的数据自动缓存到 filesystem cache 里面去。 es 的搜索引擎严重依赖于底层的 filesystem cache,你如果给 filesystem cache 更多的内存,尽量让内存可以容纳所有的 idx segment file 索引数据文件,那么你搜索的时候就基本都是走内存的,性能会非常高。 性能差距究竟可以有多大?我们之前很多的测试和压测,如果走磁盘一般肯定上秒,搜索性能绝对是秒级别的,1秒、5秒、10秒。但如果是走 filesystem cache,是走纯内存的,那么一般来说性能比走磁盘要高一个数量级,基本上就是毫秒级的,从几毫秒到几百毫秒不等。 这里有个真实的案例。某个公司 es 节点有 3 台机器,每台机器看起来内存很多,64G,总内存就是 64 * 3 = 192G。每台机器给 es jvm heap 是 32G,那么剩下来留给 filesystem cache 的就是每台机器才 32G,总共集群里给 filesystem cache 的就是 32 * 3 = 96G 内存。而此时,整个磁盘上索引数据文件,在 3 台机器上一共占用了 1T 的磁盘容量,es 数据量是 1T,那么每台机器的数据量是 300G。这样性能好吗? filesystem cache 的内存才 100G,十分之一的数据可以放内存,其他的都在磁盘,然后你执行搜索操作,大部分操作都是走磁盘,性能肯定差。 归根结底,你要让 es 性能要好,最佳的情况下,就是你的机器的内存,至少可以容纳你的总数据量的一半。 根据我们自己的生产环境实践经验,最佳的情况下,是仅仅在 es 中就存少量的数据,就是你要用来搜索的那些索引,如果内存留给 filesystem cache 的是 100G,那么你就将索引数据控制在 100G 以内,这样的话,你的数据几乎全部走内存来搜索,性能非常之高,一般可以在 1 秒以内。 比如说你现在有一行数据。id,name,age .... 30 个字段。但是你现在搜索,只需要根据 id,name,age 三个字段来搜索。如果你傻乎乎往 es 里写入一行数据所有的字段,就会导致说 90% 的数据是不用来搜索的,结果硬是占据了 es 机器上的 filesystem cache 的空间,单条数据的数据量越大,就会导致 filesystem cahce 能缓存的数据就越少。其实,仅仅写入 es 中要用来检索的少数几个字段就可以了,比如说就写入 es id,name,age 三个字段,然后你可以把其他的字段数据存在 mysql/hbase 里,我们一般是建议用 es + hbase 这么一个架构。 hbase 的特点是适用于海量数据的在线存储,就是对 hbase 可以写入海量数据,但是不要做复杂的搜索,做很简单的一些根据 id 或者范围进行查询的这么一个操作就可以了。从 es 中根据 name 和 age 去搜索,拿到的结果可能就 20 个 doc id,然后根据 doc id 到 hbase 里去查询每个 doc id 对应的完整的数据,给查出来,再返回给前端。 写入 es 的数据最好小于等于,或者是略微大于 es 的 filesystem cache 的内存容量。然后你从 es 检索可能就花费 20ms,然后再根据 es 返回的 id 去 hbase 里查询,查 20 条数据,可能也就耗费个 30ms,可能你原来那么玩儿,1T 数据都放 es,会每次查询都是 5~10s,现在可能性能就会很高,每次查询就是 50ms。 数据预热 假如说,哪怕是你就按照上述的方案去做了,es 集群中每个机器写入的数据量还是超过了 filesystem cache 一倍,比如说你写入一台机器 60G 数据,结果 filesystem cache 就 30G,还是有 30G 数据留在了磁盘上。 其实可以做数据预热。 举个例子,拿微博来说,你可以把一些大V,平时看的人很多的数据,你自己提前后台搞个系统,每隔一会儿,自己的后台系统去搜索一下热数据,刷到 filesystem cache 里去,后面用户实际上来看这个热数据的时候,他们就是直接从内存里搜索了,很快。 或者是电商,你可以将平时查看最多的一些商品,比如说 iphone 8,热数据提前后台搞个程序,每隔 1 分钟自己主动访问一次,刷到 filesystem cache 里去。 对于那些你觉得比较热的、经常会有人访问的数据,最好做一个专门的缓存预热子系统,就是对热数据每隔一段时间,就提前访问一下,让数据进入 filesystem cache 里面去。这样下次别人访问的时候,性能一定会好很多。 冷热分离 es 可以做类似于 mysql 的水平拆分,就是说将大量的访问很少、频率很低的数据,单独写一个索引,然后将访问很频繁的热数据单独写一个索引。最好是将冷数据写入一个索引中,然后热数据写入另外一个索引中,这样可以确保热数据在被预热之后,尽量都让他们留在 filesystem os cache 里,别让冷数据给冲刷掉。 你看,假设你有 6 台机器,2 个索引,一个放冷数据,一个放热数据,每个索引 3 个 shard。3 台机器放热数据 index,另外 3 台机器放冷数据 index。然后这样的话,你大量的时间是在访问热数据 index,热数据可能就占总数据量的 10%,此时数据量很少,几乎全都保留在 filesystem cache 里面了,就可以确保热数据的访问性能是很高的。但是对于冷数据而言,是在别的 index 里的,跟热数据 index 不在相同的机器上,大家互相之间都没什么联系了。如果有人访问冷数据,可能大量数据是在磁盘上的,此时性能差点,就 10% 的人去访问冷数据,90% 的人在访问热数据,也无所谓了。 document 模型设计 对于 MySQL,我们经常有一些复杂的关联查询。在 es 里该怎么玩儿,es 里面的复杂的关联查询尽量别用,一旦用了性能一般都不太好。 最好是先在 Java 系统里就完成关联,将关联好的数据直接写入 es 中。搜索的时候,就不需要利用 es 的搜索语法来完成 join 之类的关联搜索了。 document 模型设计是非常重要的,很多操作,不要在搜索的时候才想去执行各种复杂的乱七八糟的操作。es 能支持的操作就那么多,不要考虑用 es 做一些它不好操作的事情。如果真的有那种操作,尽量在 document 模型设计的时候,写入的时候就完成。另外对于一些太复杂的操作,比如 join/nested/parent-child 搜索都要尽量避免,性能都很差的。 分页性能优化 es 的分页是较坑的,为啥呢?举个例子吧,假如你每页是 10 条数据,你现在要查询第 100 页,实际上是会把每个 shard 上存储的前 1000 条数据都查到一个协调节点上,如果你有个 5 个 shard,那么就有 5000 条数据,接着协调节点对这 5000 条数据进行一些合并、处理,再获取到最终第 100 页的 10 条数据。 分布式的,你要查第 100 页的 10 条数据,不可能说从 5 个 shard,每个 shard 就查 2 条数据,最后到协调节点合并成 10 条数据吧?你必须得从每个 shard 都查 1000 条数据过来,然后根据你的需求进行排序、筛选等等操作,最后再次分页,拿到里面第 100 页的数据。你翻页的时候,翻的越深,每个 shard 返回的数据就越多,而且协调节点处理的时间越长,非常坑爹。所以用 es 做分页的时候,你会发现越翻到后面,就越是慢。 我们之前也是遇到过这个问题,用 es 作分页,前几页就几十毫秒,翻到 10 页或者几十页的时候,基本上就要 5~10 秒才能查出来一页数据了。 有什么解决方案吗? 不允许深度分页(默认深度分页性能很差) 跟产品经理说,你系统不允许翻那么深的页,默认翻的越深,性能就越差。 类似于 app 里的推荐商品不断下拉出来一页一页的 类似于微博中,下拉刷微博,刷出来一页一页的,你可以用 scroll api,关于如何使用,自行上网搜索。 scroll 会一次性给你生成所有数据的一个快照,然后每次滑动向后翻页就是通过游标 scroll_id 移动,获取下一页下一页这样子,性能会比上面说的那种分页性能要高很多很多,基本上都是毫秒级的。 但是,唯一的一点就是,这个适合于那种类似微博下拉翻页的,不能随意跳到任何一页的场景。也就是说,你不能先进入第 10 页,然后去第 120 页,然后又回到第 58 页,不能随意乱跳页。所以现在很多产品,都是不允许你随意翻页的,app,也有一些网站,做的就是你只能往下拉,一页一页的翻。 初始化时必须指定 scroll 参数,告诉 es 要保存此次搜索的上下文多长时间。你需要确保用户不会持续不断翻页翻几个小时,否则可能因为超时而失败。 除了用 scroll api,你也可以用 search_after 来做,search_after 的思想是使用前一页的结果来帮助检索下一页的数据,显然,这种方式也不允许你随意翻页,你只能一页页往后翻。初始化时,需要使用一个唯一值的字段作为 sort 字段。 往期回顾: 【Java问答学堂】1期 为什么使用消息队列?消息队列有什么优点和缺点?Kafka、ActiveMQ、RabbitMQ、RocketMQ 都有什么区别,以及适合哪些场景? 【Java问答学堂】2期 如何保证消息队列的高可用? 【Java问答学堂】3期 如何保证消息不被重复消费?或者说,如何保证消息消费的幂等性? 【Java问答学堂】4期 如何保证消息的可靠性传输?(如何处理消息丢失的问题?) 【Java问答学堂】5期 如何保证消息的顺序性? 【Java问答学堂】6期 如何解决消息队列的延时以及过期失效问题? 【Java问答学堂】7期 如果让你写一个消息队列,该如何进行架构设计? 【Java问答学堂】8期 es 的分布式架构原理能说一下么(es 是如何实现分布式的啊)? 【Java问答学堂】9期 es 写入数据的工作原理是什么啊?es 查询数据的工作原理是什么啊?

剑曼红尘 2020-04-28 14:17:05 0 浏览量 回答数 0

问题

云服务器 ECS Linux 系统盘数据转移方法是什么

boxti 2019-12-01 22:04:21 1227 浏览量 回答数 0

问题

Redis 集群模式的工作原理能说一下么?【Java问答】36期

剑曼红尘 2020-06-12 15:07:18 2 浏览量 回答数 1

回答

ECS磁盘 我想在ECS 跨服务器进行数据拷贝,有没有知道实现方法的? Linux系统服务器重启或初始化系统之后,再登录服务器执行df -h查看磁盘挂载,发现数据不见了。这是为什么?能不能找回来? 重启服务器后发现/alidata目录所有数据丢失。怎么才能找回来呢? ECS Linux扩容格式化磁盘提示magic number in super-block while trying to open /dev/xvdb1 ? Linux 实例初始化系统盘后,怎样才能重新挂载数据盘? 如何在ECS 利用快照创建磁盘实现无损扩容数据盘? ECS云服务器磁盘FAQ云服务器磁盘I/O速度是多少? Linux 购买了数据盘,但是系统中看不到怎么办? ECS系统盘和数据盘二次分区FAQ,系统盘能否再次划分出一个分区用作数据存储? ECS系统盘和数据盘二次分区FAQ,数据盘能否再次划分出一个分区用作数据存储? ECS系统盘和数据盘二次分区FAQ,划分了多个分区的磁盘,做快照时是针对该分区的,还是针对磁盘的? ECS系统盘和数据盘二次分区FAQ,磁盘二次分区有哪些注意事项? ECS系统盘和数据盘二次分区FAQ,数据盘进行二次分区后,此时回滚快照后,数据盘是几个分区? 什么是可用区? 怎么根据服务器应用需求选择可用区? 按量付费云盘和云盘有什么区别? 按量付费云盘和普通云盘的性能和数据安全性一样吗,磁盘性能会有提升吗? 可以使用用户快照创建按量付费云盘吗? 什么是挂载点? 一块按量付费云盘可以挂载到多个 ECS 实例上吗? 一台 ECS 实例能同时挂载多少块按量付费云盘吗? 按量付费云盘能够挂载到包年包月和按量付费 ECS 实例上吗? 为什么挂载按量付费云盘时找不到我想挂载的 ECS 实例? 购买按量付费云盘后,挂载到目标 ECS 实例的挂载点是否还需要执行磁盘挂载操作? 我已经操作过续费变配,在续费变配期内是否还能将普通云盘转为按量付费云盘? ECS快照 为什么我的按量付费云盘没有自动快照了? 重新初始化磁盘时,我的快照会丢失吗? 更换系统盘时,我的快照会丢失吗? 卸载按量付费云盘时,我的磁盘会丢数据吗? 我能够卸载系统盘吗? 什么是独立云磁盘? 什么是可用区? 独立云磁盘跟现在的磁盘有什么区别? 服务器应用与可用区选择的选择关系是怎么样的? 独立云磁盘怎么收费? 独立云磁盘能够挂载到包年包月实例上吗? 独立云磁盘和普通云磁盘的磁盘性能和数据安全性一样吗,磁盘性能会有提升吗? 我的包年包月实例上不需要的磁盘能不能卸载? 为什么我的独立云磁盘和我的实例一起释放了? 为什么独立云磁盘挂载时找不到我想挂载的实例? 为什么我在本实例列表中选择独立云磁盘挂载时找不到我想要挂载的磁盘? 我删除磁盘的时候,快照会被保留吗? 为什么我的独立云磁盘没有自动快照了? 为什么我不能购买独立云磁盘? 一台实例能挂载多少块独立云磁盘? 卸载独立云磁盘时,我的磁盘会丢数据吗? 我的系统盘能够卸载吗? 什么是设备名? 为什么我在控制台上找不到重置磁盘,更换操作系统,回滚快照的操作了? 重新初始化磁盘时,我的快照会丢失吗? 更换系统盘时,我的快照会丢失吗? 为什么我的数据盘不能选择临时磁盘 独立云磁盘服务器的应用场景有哪些? 可以使用用户快照创建独立云磁盘吗? 独立云磁盘购买后挂载到目标实例的挂载点后,是否还需要执行磁盘挂载操作? 本地SSD盘“本地”是指? 本地SSD盘适合的用户场景有哪些? SSD盘相对之前的普通云盘性能提升多少,是否可以提供具体参数? 本地SSD盘是否支持在原ECS上进行添加或者将原云磁盘更换成本地SSD盘? 本地SSD盘购买后是否支持升级? SSD 云盘具备怎样的 I/O 性能? SSD云盘的数据可靠性是怎样的? SSD 云盘适合的应用场景有哪些? SSD 云盘相对普通云盘性能提升多少?是否可以提供具体参数? I/O 优化是什么概念?能将存量的 ECS 实例升级为 I/O 优化的实例吗? 是否支持将原普通云盘更换成 SSD 云盘? 如何购买 SSD 云盘,I/O 优化的实例及 SSD 云盘的价格是多少? 为什么 I/O 优化的实例有时启动比较耗时? 有些自定义镜像不支持创建 I/O 优化的实例,我该如何操作? 购买SSD云盘后是否支持升级? 使用了 I/O 优化实例和 SSD 云盘之后,Linux 系统在分区挂载的时候报错。 为什么我用 fio 测试性能时,会导致实例宕机? 云盘参数和性能测试工具及方法有推荐的吗? 我想扩容系统盘,求详细步骤! 所有块存储都支持系统盘扩容吗?有地域限制吗? 包年包月和按量付费的ECS实例都支持系统盘扩容吗? 新购ECS时,系统盘开始单独收费?老用户存量的系统盘如何收费? 新购ECS时,系统盘开始单独收费?老用户存量的系统盘如何收费?系统盘扩容是否需要停机操作? 系统盘扩容上线后,系统盘的容量范围多少? 哪些镜像支持系统盘扩容? 云服务器续费变配后,不支持更换系统盘时指定系统盘容量? 系统盘扩容之后是否支持再缩容? 扩容系统盘应注意的问题? 回滚磁盘报错,进行快照回滚的时候,出现如下错误提示: 执行回滚磁盘需要停止实例,并确保当前磁盘没有创建中的快照和没有更换过操作系统。 这是什么原因? 普通云盘和SSD云盘添加挂载信息时有哪些要注意的事项? 申请公测资格 什么是共享块存储? 共享块存储适用于哪些行业和业务场景? 为什么需要共享块存储? 如何正确使用共享块存储? 我能跨地域挂载共享块存储吗? 共享块存储产品规格有哪些? 我想知道阿里云产品的售卖模式和公测范围! 公测购买入口是哪,求链接! 有没有谁分享下共享块存储性能测试命令? 数据盘挂载问题导致数据无法访问,我要怎么排查问题? 我要怎样才能在Linux和Windows主机之间挂载ntfs格式云盘? 为什么ECS实例里文件系统和快照空间大小不一致?在ECS实例内删除文件后再打快照,发现快照容量并没有变小。 ECS实例如何优化快照使用成本? 在ECS实例里什么是快照商业化? 在ECS实例里,快照商业化后过渡优惠期是什么时候? 在ECS实例里,快照商业化的用户范围包括有哪些? 在ECS实例里,如果我已经开通了 OSS,快照会自动存到我的 OSS Bucket 吗?是否需要重新再创建一个 Bucket 来存储快照? 已经购买了 OSS 预付费存储包,同时在使用快照和 OSS 服务,那么存储包会优先抵扣哪个产品? 快照商业化之后,我希望继续使用,需要购买哪个产品,云盘还是对象存储OSS资源包? 快照商业化的收费模式是怎样的? 快照费用的计算方法是怎样的? 快照收费后,不停止自动快照是否就开始收取费用? 快照要收费了,之前的快照要被删除吗? 如果不想付费,之前的快照能继续使用吗? 快照收费后,之前创建的手动快照和自动快照都会收费吗? 快照收费前停止快照策略,需手动删除历史快照吗?正式收费后会直接删除我的历史快照吗? 快照收费以后,账户欠费对快照有什么影响? 如果账号欠费,有关联关系(创建过磁盘或者镜像)的快照,在欠费15天之后是否会被删除? 快照服务和块存储服务的关系,在收费方面的关系是什么? 快照容量是如何计算的,是等于磁盘大小吗? ECS实例内删除文件会减少空间占用吗? 为什么快照容量大于文件系统内看到的数据量? 参考快照增量说明,如中间快照被删除,后面的快照能否使用? 如何开通快照服务? 快照和镜像的关系? 如何在保留关联实例和磁盘的情况下,删除快照跟镜像,快照、实例、镜像之间的关系? 快照和块存储、OSS对象存储是什么关系? 一块云盘能否设置多个快照策略? 快照 2.0 服务包括哪些内容? 快照有什么用途? 快照 2.0 服务支持的云盘类型? 快照数量有什么限制? 快照保留时长怎样? 打快照对块存储 I/O 性能有多少影响? 快照怎么收费? 老的自动快照策略什么时候不可用? 老的快照策略产生的快照什么时候删除? 自动快照功能细节有哪些? 用户的自定义快照和自动快照有冲突吗? 我能保留其中想要的自动快照而让系统不删除吗? 如果一个自动快照被引用(用户创建自定义镜像或者磁盘),会导致自动快照策略执行失败吗? 我如果什么都没有设置,自动快照会启动吗? 自动快照能够删除吗? 自动快照具体在什么时间创建能看到吗? 我如何区分哪些快照是自动快照和用户快照? 更换系统盘、云服务器 ECS 到期后或手动释放磁盘时,自动快照会不会释放? 未随磁盘释放和更换系统盘释放的自动快照会一直保留吗? 云服务器 ECS 到期后或手动释放磁盘时,手工快照会不会释放? 我能单独制定某几块磁盘执行或取消自动快照吗? 云服务器 ECS 有没有自动备份? 磁盘无快照是否能够回滚或数据恢复? 快照回滚能否单独回滚某个分区或部分数据? 系统盘快照回滚是否会影响数据盘? 更换系统后,快照能否回滚? 在回滚快照前,有哪些注意事项? 怎样使ECS回滚快照后同步数据? 如何通过API配置定时自定义快照? 超出预付费存储包的流量,会怎么收费? ECS镜像 Aliyun Linux 17.01 特性有哪些,有说明文档吗? 云市场镜像有哪些功能? 镜像能带来哪些便利? 目前镜像支持哪些服务器环境和应用场景? 镜像是否安全? 选择了镜像后能更换吗? 镜像安装使用过程中出问题了怎么办? Docker私有镜像库是什么? 自定义镜像如何查看数据盘? 自定义镜像,如何卸载和删除 disk table 里的数据? 如何确认已经卸载数据盘,并可以新建自定义镜像? ECS 实例释放后,自定义镜像是否还存在? ECS 实例释放后,快照是否还存在? 用于创建自定义镜像的云服务器 ECS 实例到期或释放数据后,创建的自定义镜像是否受影响?使用自定义镜像开通的云服务器 ECS 实例是否受影响? 使用自定义镜像创建的 ECS 实例是否可以更换操作系统?更换系统后原来的自定义镜像是否还可以使用? 更换系统盘时另选操作系统,是否可以使用自定义镜像? 已创建的自定义镜像,是否可以用于更换另一台云服务器 ECS 的系统盘数据? 是否可以升级自定义镜像开通的云服务器 ECS 的 CPU、内存、带宽、硬盘等? 是否可以跨地域使用自定义镜像? 包年包月云服务器 ECS 的自定义镜像,是否可以用于开通按量付费的云服务器 ECS? ECS Windows企业版和标准版区别 什么情况下需要复制镜像? 可以复制哪些镜像? 当前有哪些支持镜像复制功能的地域? 复制一个镜像大概需要多久? 复制镜像怎么收费的? 在复制镜像过程中,源镜像和目标镜像有什么限制? 怎么复制我的云账号的镜像资源到其他云账号的其他地域? 复制镜像有镜像容量限制吗? 如何购买镜像市场镜像? 按次购买的镜像的使用期限是多久? 镜像市场的镜像支持退款吗? 镜像市场商业化后,还有免费的镜像市场镜像吗? 在杭州买了一个镜像市场的镜像,能否在北京创建ECS实例或者更换系统盘? ECS实例使用镜像市场的镜像,升级和续费ECS实例,需要为镜像继续付费吗? ECS实例使用镜像市场的镜像,实例释放后,继续购买ECS实例还可以免费使用该镜像吗? 使用镜像市场镜像创建ECS实例,该实例创建一个自定义镜像,使用该自定义镜像创建ECS实例需要为该镜像付费吗? 来源于镜像市场的镜像复制到其他地域创建ECS实例,是否需要为该镜像付费? 如果把来源于镜像市场的自定义镜像共享给其他账号(B)创建ECS实例,账号B是否需要为该镜像付费? 如果使用镜像市场的镜像或者来源于镜像市场的镜像进行更换系统盘,需要付费吗? ECS实例正在使用镜像市场的镜像,进行重置系统盘需要收费吗? 怎么调用ECS API,使用镜像市场镜像或者来源镜像市场的自定义镜像或者共享镜像,创建ECS实例和更换系统盘? 如果没有购买镜像市场的镜像或者来源于镜像市场的镜像,在调用ECS API 使用该镜像创建ECS实例和更换系统盘,会报错吗? 我的ESS是自动创建机器的,并且量是不固定,设置最小值为10台,最大值为100台,那么使用镜像市场的镜像如何保证我的的需求实例能正常弹出来? 镜像市场的镜像是否支持批量购买? 如果之前使用的镜像市场的镜像,已不存在该商品(如:jxsc000010、jxsc000019),怎能保证已经设置的弹性伸缩组的机器的正常弹出? 1个product code能否支持不同region的镜像? 我买了100 product code同样值的镜像,是否可以支持在所有的地域可用? 为什么有的ECS云服务器无法选择Windows操作系统? 操作系统是否要收费? 我能否自己安装或者升级操作系统? 服务器的登录用户名密码是什么? 能否更换或升级操作系统? 操作系统是否有图形界面? 如何选择操作系统? 操作系统自带 FTP 上传吗? 每个用户最多可以获得多少个共享镜像? 每个镜像最多可以共享给多少个用户? 使用共享镜像是否占用我的镜像名额? 使用共享镜像创建实例的时候存不存在地域限制? 我曾把自己账号中的某个自定义镜像共享给其他账号,现在我可以删除这个镜像吗 我把某个自定义镜像(M)的共享账号(A)给删除了,会有什么影响? 使用共享镜像创建实例存在什么样的风险? 我把自定义镜像共享给其他账号,存在什么风险? 我能把别人共享给我的镜像再共享给他人吗? 我把镜像共享给他人,还能使用该镜像创建实例吗? ECS Windows服务器桌面分辨率过高导致VNC花屏处理方法通过 管理终端 进入服务器后,把 Windows 服务器桌面分辨率设置过高,确定后,WebVNC 出现花屏。 ECS创建自定义镜像创建服务器为何需要注释挂载项 勾选"IO优化实例"选项导致购买ECS实例时无法选择云市场镜像 如何为 Linux 服务器安装 GRUB 历史Linux镜像的问题修复方案 如何处理 CentOS DNS 解析超时? 什么是镜像市场的包年包月和按周付费镜像? 预付费镜像能与哪种 ECS 实例搭配使用? 怎么购买预付费镜像?可以单独购买吗? 预付费镜像怎么付费? 预付费镜像到期了就不能用了吗?怎么继续使用? 购买预付费镜像后,如果我不想再使用这个镜像,能要求退款吗? 退款时,费用怎么结算? 预付费镜像能转换为按量付费镜像吗? 预付费镜像与其它镜像之间能互换吗?更换后费用怎么计算? 在哪里查看并管理我购买的预付费镜像? 使用预付费镜像制作的自定义镜像会收费吗?预付费镜像过期对于自定义镜像有什么影响? ECS 实例操作系统选择说明 阿里云支持哪些 SUSE 版本? SUSE 操作系统提供哪些服务支持? ECS安全组 如何检查 TCP 80 端口是否正常工作? 什么是安全组? 为什么在购买 ECS 实例的时候选择安全组? 安全组配置错误会造成哪些影响? 专有网络实例设置安全组规则时为什么不能设置公网规则? 创建 ECS 实例时我还没创建安全组怎么办? 为什么无法访问 25 端口? 为什么我的安全组里自动添加了很多规则? 为什么有些安全组规则的优先级是 110? 为什么我在安全组里放行了 TCP 80 端口,还是无法访问 80 端口? ECS安全组被添加内网ip地址了,是怎么回事? 能说明下ECS安全组中规则的优先级执行匹配顺序吗? ECS实例安全组默认的公网规则被删除导致无法ping通,ECS 服务器无法ping通,排查防火墙、网卡IP配置无误,回滚系统后仍然无法ping通。 我刚购买了ECS实例,如何选择及配置安全组? 没有添加默认安全组访问规则-导致通过API创建的ECS实例断网,要怎么恢复? 使用ECS安全组工具撤销之前账号间互通的操作 ECS网络 带宽与上传、下载速度峰值的有什么关系? 弹性公网IP在哪里可以查看流量和带宽监控信息? 我用的是ECS Ubuntu系统,要怎么单独禁用和启动内外网卡? ECS 实例子网划分和掩码是什么? ECS 实例网络带宽是否独享? 带宽单线还是双线,电信还是网通? 5 Mbps 带宽怎么理解? 带宽的价格是多少? 不同地域的 ECS 实例之间的内网是通的吗? 为何新建的 ECS 实例就有 200 Kbps 左右入网流量? 我的 ECS 实例经常能在 Web 日志中看到大量的恶意 IP 访问我的网站,疑有刷流量和恶意访问的嫌疑,询问云盾是否有屏蔽 IP 的功能? 包月ECS新购时是否可以选择带宽按照使用流量计费? 包月ECS带宽按流量计费是如何计费的? 目前使用的固定带宽计费,是否可以转换为带宽按流量计费? 是否可以随时调整流量带宽峰值? 续费变更配置时(比如到期时间为2015年3月31日,续费一个月到4月30日),如果将包月ECS按固定带宽计费改成按流量付费计费,操作以后在未生效前(3月31日前),是否还可以升级带宽? 续费变更配置时候将包月ECS带宽按流量计费改成按固定带宽计费,为什么我的带宽服务停掉了? 如果账号没有足够余额,欠费怎么办?ECS实例也会停掉吗? 带宽流量欠费是否有短信通知? 当带宽按照流量计费欠费时,是否可以对实例进行升级 CPU、内存操作? 欠费充值后带宽是自动恢复的吗? 包月带宽转流量计费后,流量价格是多少? ECS 服务器出现了异地登录怎么办? 爱哪里可以查看云服务器 ECS 公网流量统计总和? 我的ECS 实例对外 DDoS 攻击导致被锁定了,要如何处理 ? 什么是云服务器 ECS 的入网带宽和出网带宽? ECS云服务器如何禁用公网IP? ECS 实例停止(关机)后按量付费带宽仍产生流量,ECS 实例在控制台上状态为已停止,但按量付费的带宽每小时仍会产生不小的费用,且此时 ECS 实例正在遭受攻击,云盾控制台中 DDoS 防护中 ECS 的状态为清洗中。 访问ECS服务器的网站提示“由于你访问的URL可能对网站造成安全威胁,您的访问被阻断”,这是什么原因? 服务器黑洞是什么?求科普! 如果想确认该服务器的IP信息和地理位置,要在哪里去查询? 我想知道客户端本地到ECS服务器是不是丢包,要怎么测试? 内网和公共 NTP 服务器是什么?它们两个有什么区别 我能 ping 通但端口不通,这是端口的问题吗? 如何通过防火墙策略限制对外扫描行为? 我想用手机移动端网络路由跟踪探测,可以吗? 云监控中的ECS带宽和ECS控制台中看到的带宽不一致是什么原因? 云服务器ECS三张网卡有什么区别? Ubuntu系统ECS使用“如何通过防火墙策略限制对外扫描行为”脚本之后出现无法远程、数据库连接不上。 什么业务场景需要在专有网络(VPC)类型ECS购买PublicIP? 怎么购买专有网络(VPC)类型分配 PublicIP 的 ECS? 专有网络(VPC)类型 ECS 的 PublicIP 和 EIP 的区别? 专有网络(VPC)类型ECS的 PublicIP 的可以升级带宽吗? 专有网络(VPC)类型ECS的 PublicIP 可以解绑吗? 如果购买网络(VPC)类型 ECS 的时候,没有分配公网 IP,该怎么才能分配一个公网 IP? 怎么查询专有网络(VPC)类型 ECS 的 PublicIP 的监控数据? 怎么查询专有网络(VPC)类型ECS的按流量付费的 PublicIP 的账单? 专有网络和经典网络的 PublicIP 异同? 专有网络(VPC)类型 ECS 购买 PublicIP 的付费方式? ECS API 如何通过 API / SDK 实现不同账号 ECS 实例的内网通信? ECS API绑定公网IP报错:The IP is already in use分析 ECS API修改实例带宽不能指定时间范围吗? 所在可用区不支持相应磁盘类型-导致ECS API创建实例报错 用ECS API创建实例的时候,返回如下错误信息: "Code": "InvalidDataDiskCategory.NotSupported" 如何创建有公网 IP 的 ECS 实例? 通过API或SDK查询安全组规则无法显示所有的规则,这是怎么回事? 如何通过OpenAPI创建ECS实例的流程状态描述? 数据传输服务DTS实时同步功能,我想只同步表结构,要怎么做? 如何获取控制台RequestId? 阿里云中国站部分地域实例什么时候降价? ECS Linux 实例怎么设置 Locale 变量? 克隆ECS服务器的方法 其它国家和地区是否都可以提供经典网络和专有网络的类型呢?网络类型是否可以变更呢? 各个地域的网络覆盖范围是什么呢? 其他相关问题 不同地域的实例,价格一样吗? 如果我使用其它国家和地区的实例搭建了一个网站,我的用户将通过域名访问网站,这个域名需要 ICP 备案吗? 为什么有些实例规格只能在中国大陆地域购买,而在其它国家和地区无法购买? 可否将中国大陆地域的实例迁移到其它国家和地区呢? 如何在其它国家和地区部署 ECS 实例? 我要买其它国家和地区的实例,需要单独申请一个国际站账号吗? ——更多ECS相关问题—— · ECS故障处理百问合集

问问小秘 2020-01-02 15:49:17 0 浏览量 回答数 0

问题

【阿里云产品公测】简单日志服务SLS使用评测含教程

mr_wid 2019-12-01 21:08:11 36639 浏览量 回答数 20

问题

【技术干货】原来阿里云自助实验室的系统架构是这样的啊

驻云科技 2019-12-01 21:07:14 9011 浏览量 回答数 1

回答

92题 一般来说,建立INDEX有以下益处:提高查询效率;建立唯一索引以保证数据的唯一性;设计INDEX避免排序。 缺点,INDEX的维护有以下开销:叶节点的‘分裂’消耗;INSERT、DELETE和UPDATE操作在INDEX上的维护开销;有存储要求;其他日常维护的消耗:对恢复的影响,重组的影响。 需要建立索引的情况:为了建立分区数据库的PATITION INDEX必须建立; 为了保证数据约束性需要而建立的INDEX必须建立; 为了提高查询效率,则考虑建立(是否建立要考虑相关性能及维护开销); 考虑在使用UNION,DISTINCT,GROUP BY,ORDER BY等字句的列上加索引。 91题 作用:加快查询速度。原则:(1) 如果某属性或属性组经常出现在查询条件中,考虑为该属性或属性组建立索引;(2) 如果某个属性常作为最大值和最小值等聚集函数的参数,考虑为该属性建立索引;(3) 如果某属性经常出现在连接操作的连接条件中,考虑为该属性或属性组建立索引。 90题 快照Snapshot是一个文件系统在特定时间里的镜像,对于在线实时数据备份非常有用。快照对于拥有不能停止的应用或具有常打开文件的文件系统的备份非常重要。对于只能提供一个非常短的备份时间而言,快照能保证系统的完整性。 89题 游标用于定位结果集的行,通过判断全局变量@@FETCH_STATUS可以判断是否到了最后,通常此变量不等于0表示出错或到了最后。 88题 事前触发器运行于触发事件发生之前,而事后触发器运行于触发事件发生之后。通常事前触发器可以获取事件之前和新的字段值。语句级触发器可以在语句执行前或后执行,而行级触发在触发器所影响的每一行触发一次。 87题 MySQL可以使用多个字段同时建立一个索引,叫做联合索引。在联合索引中,如果想要命中索引,需要按照建立索引时的字段顺序挨个使用,否则无法命中索引。具体原因为:MySQL使用索引时需要索引有序,假设现在建立了"name,age,school"的联合索引,那么索引的排序为: 先按照name排序,如果name相同,则按照age排序,如果age的值也相等,则按照school进行排序。因此在建立联合索引的时候应该注意索引列的顺序,一般情况下,将查询需求频繁或者字段选择性高的列放在前面。此外可以根据特例的查询或者表结构进行单独的调整。 86题 建立索引的时候一般要考虑到字段的使用频率,经常作为条件进行查询的字段比较适合。如果需要建立联合索引的话,还需要考虑联合索引中的顺序。此外也要考虑其他方面,比如防止过多的所有对表造成太大的压力。这些都和实际的表结构以及查询方式有关。 85题 存储过程是一组Transact-SQL语句,在一次编译后可以执行多次。因为不必重新编译Transact-SQL语句,所以执行存储过程可以提高性能。触发器是一种特殊类型的存储过程,不由用户直接调用。创建触发器时会对其进行定义,以便在对特定表或列作特定类型的数据修改时执行。 84题 存储过程是用户定义的一系列SQL语句的集合,涉及特定表或其它对象的任务,用户可以调用存储过程,而函数通常是数据库已定义的方法,它接收参数并返回某种类型的值并且不涉及特定用户表。 83题 减少表连接,减少复杂 SQL,拆分成简单SQL。减少排序:非必要不排序,利用索引排序,减少参与排序的记录数。尽量避免 select *。尽量用 join 代替子查询。尽量少使用 or,使用 in 或者 union(union all) 代替。尽量用 union all 代替 union。尽量早的将无用数据过滤:选择更优的索引,先分页再Join…。避免类型转换:索引失效。优先优化高并发的 SQL,而不是执行频率低某些“大”SQL。从全局出发优化,而不是片面调整。尽可能对每一条SQL进行 explain。 82题 如果条件中有or,即使其中有条件带索引也不会使用(要想使用or,又想让索引生效,只能将or条件中的每个列都加上索引)。对于多列索引,不是使用的第一部分,则不会使用索引。like查询是以%开头。如果列类型是字符串,那一定要在条件中将数据使用引号引用起来,否则不使用索引。如果mysql估计使用全表扫描要比使用索引快,则不使用索引。例如,使用<>、not in 、not exist,对于这三种情况大多数情况下认为结果集很大,MySQL就有可能不使用索引。 81题 主键不能重复,不能为空,唯一键不能重复,可以为空。建立主键的目的是让外键来引用。一个表最多只有一个主键,但可以有很多唯一键。 80题 空值('')是不占用空间的,判断空字符用=''或者<>''来进行处理。NULL值是未知的,且占用空间,不走索引;判断 NULL 用 IS NULL 或者 is not null ,SQL 语句函数中可以使用 ifnull ()函数来进行处理。无法比较 NULL 和 0;它们是不等价的。无法使用比较运算符来测试 NULL 值,比如 =, <, 或者 <>。NULL 值可以使用 <=> 符号进行比较,该符号与等号作用相似,但对NULL有意义。进行 count ()统计某列的记录数的时候,如果采用的 NULL 值,会被系统自动忽略掉,但是空值是统计到其中。 79题 HEAP表是访问数据速度最快的MySQL表,他使用保存在内存中的散列索引。一旦服务器重启,所有heap表数据丢失。BLOB或TEXT字段是不允许的。只能使用比较运算符=,<,>,=>,= <。HEAP表不支持AUTO_INCREMENT。索引不可为NULL。 78题 如果想输入字符为十六进制数字,可以输入带有单引号的十六进制数字和前缀(X),或者只用(Ox)前缀输入十六进制数字。如果表达式上下文是字符串,则十六进制数字串将自动转换为字符串。 77题 Mysql服务器通过权限表来控制用户对数据库的访问,权限表存放在mysql数据库里,由mysql_install_db脚本初始化。这些权限表分别user,db,table_priv,columns_priv和host。 76题 在缺省模式下,MYSQL是autocommit模式的,所有的数据库更新操作都会即时提交,所以在缺省情况下,mysql是不支持事务的。但是如果你的MYSQL表类型是使用InnoDB Tables 或 BDB tables的话,你的MYSQL就可以使用事务处理,使用SET AUTOCOMMIT=0就可以使MYSQL允许在非autocommit模式,在非autocommit模式下,你必须使用COMMIT来提交你的更改,或者用ROLLBACK来回滚你的更改。 75题 它会停止递增,任何进一步的插入都将产生错误,因为密钥已被使用。 74题 创建索引的时候尽量使用唯一性大的列来创建索引,由于使用b+tree做为索引,以innodb为例,一个树节点的大小由“innodb_page_size”,为了减少树的高度,同时让一个节点能存放更多的值,索引列尽量在整数类型上创建,如果必须使用字符类型,也应该使用长度较少的字符类型。 73题 当MySQL单表记录数过大时,数据库的CRUD性能会明显下降,一些常见的优化措施如下: 限定数据的范围: 务必禁止不带任何限制数据范围条件的查询语句。比如:我们当用户在查询订单历史的时候,我们可以控制在一个月的范围内。读/写分离: 经典的数据库拆分方案,主库负责写,从库负责读。垂直分区: 根据数据库里面数据表的相关性进行拆分。简单来说垂直拆分是指数据表列的拆分,把一张列比较多的表拆分为多张表。水平分区: 保持数据表结构不变,通过某种策略存储数据分片。这样每一片数据分散到不同的表或者库中,达到了分布式的目的。水平拆分可以支撑非常大的数据量。 72题 乐观锁失败后会抛出ObjectOptimisticLockingFailureException,那么我们就针对这块考虑一下重试,自定义一个注解,用于做切面。针对注解进行切面,设置最大重试次数n,然后超过n次后就不再重试。 71题 一致性非锁定读讲的是一条记录被加了X锁其他事务仍然可以读而不被阻塞,是通过innodb的行多版本实现的,行多版本并不是实际存储多个版本记录而是通过undo实现(undo日志用来记录数据修改前的版本,回滚时会用到,用来保证事务的原子性)。一致性锁定读讲的是我可以通过SELECT语句显式地给一条记录加X锁从而保证特定应用场景下的数据一致性。 70题 数据库引擎:尤其是mysql数据库只有是InnoDB引擎的时候事物才能生效。 show engines 查看数据库默认引擎;SHOW TABLE STATUS from 数据库名字 where Name='表名' 如下;SHOW TABLE STATUS from rrz where Name='rrz_cust';修改表的引擎alter table table_name engine=innodb。 69题 如果是等值查询,那么哈希索引明显有绝对优势,因为只需要经过一次算法即可找到相应的键值;当然了,这个前提是,键值都是唯一的。如果键值不是唯一的,就需要先找到该键所在位置,然后再根据链表往后扫描,直到找到相应的数据;如果是范围查询检索,这时候哈希索引就毫无用武之地了,因为原先是有序的键值,经过哈希算法后,有可能变成不连续的了,就没办法再利用索引完成范围查询检索;同理,哈希索引也没办法利用索引完成排序,以及like ‘xxx%’ 这样的部分模糊查询(这种部分模糊查询,其实本质上也是范围查询);哈希索引也不支持多列联合索引的最左匹配规则;B+树索引的关键字检索效率比较平均,不像B树那样波动幅度大,在有大量重复键值情况下,哈希索引的效率也是极低的,因为存在所谓的哈希碰撞问题。 68题 decimal精度比float高,数据处理比float简单,一般优先考虑,但float存储的数据范围大,所以范围大的数据就只能用它了,但要注意一些处理细节,因为不精确可能会与自己想的不一致,也常有关于float 出错的问题。 67题 datetime、timestamp精确度都是秒,datetime与时区无关,存储的范围广(1001-9999),timestamp与时区有关,存储的范围小(1970-2038)。 66题 Char使用固定长度的空间进行存储,char(4)存储4个字符,根据编码方式的不同占用不同的字节,gbk编码方式,不论是中文还是英文,每个字符占用2个字节的空间,utf8编码方式,每个字符占用3个字节的空间。Varchar保存可变长度的字符串,使用额外的一个或两个字节存储字符串长度,varchar(10),除了需要存储10个字符,还需要1个字节存储长度信息(10),超过255的长度需要2个字节来存储。char和varchar后面如果有空格,char会自动去掉空格后存储,varchar虽然不会去掉空格,但在进行字符串比较时,会去掉空格进行比较。Varbinary保存变长的字符串,后面不会补\0。 65题 首先分析语句,看看是否load了额外的数据,可能是查询了多余的行并且抛弃掉了,可能是加载了许多结果中并不需要的列,对语句进行分析以及重写。分析语句的执行计划,然后获得其使用索引的情况,之后修改语句或者修改索引,使得语句可以尽可能的命中索引。如果对语句的优化已经无法进行,可以考虑表中的数据量是否太大,如果是的话可以进行横向或者纵向的分表。 64题 建立索引的时候一般要考虑到字段的使用频率,经常作为条件进行查询的字段比较适合。如果需要建立联合索引的话,还需要考虑联合索引中的顺序。此外也要考虑其他方面,比如防止过多的所有对表造成太大的压力。这些都和实际的表结构以及查询方式有关。 63题 存储过程是一些预编译的SQL语句。1、更加直白的理解:存储过程可以说是一个记录集,它是由一些T-SQL语句组成的代码块,这些T-SQL语句代码像一个方法一样实现一些功能(对单表或多表的增删改查),然后再给这个代码块取一个名字,在用到这个功能的时候调用他就行了。2、存储过程是一个预编译的代码块,执行效率比较高,一个存储过程替代大量T_SQL语句 ,可以降低网络通信量,提高通信速率,可以一定程度上确保数据安全。 62题 密码散列、盐、用户身份证号等固定长度的字符串应该使用char而不是varchar来存储,这样可以节省空间且提高检索效率。 61题 推荐使用自增ID,不要使用UUID。因为在InnoDB存储引擎中,主键索引是作为聚簇索引存在的,也就是说,主键索引的B+树叶子节点上存储了主键索引以及全部的数据(按照顺序),如果主键索引是自增ID,那么只需要不断向后排列即可,如果是UUID,由于到来的ID与原来的大小不确定,会造成非常多的数据插入,数据移动,然后导致产生很多的内存碎片,进而造成插入性能的下降。总之,在数据量大一些的情况下,用自增主键性能会好一些。 60题 char是一个定长字段,假如申请了char(10)的空间,那么无论实际存储多少内容。该字段都占用10个字符,而varchar是变长的,也就是说申请的只是最大长度,占用的空间为实际字符长度+1,最后一个字符存储使用了多长的空间。在检索效率上来讲,char > varchar,因此在使用中,如果确定某个字段的值的长度,可以使用char,否则应该尽量使用varchar。例如存储用户MD5加密后的密码,则应该使用char。 59题 一. read uncommitted(读取未提交数据) 即便是事务没有commit,但是我们仍然能读到未提交的数据,这是所有隔离级别中最低的一种。 二. read committed(可以读取其他事务提交的数据)---大多数数据库默认的隔离级别 当前会话只能读取到其他事务提交的数据,未提交的数据读不到。 三. repeatable read(可重读)---MySQL默认的隔离级别 当前会话可以重复读,就是每次读取的结果集都相同,而不管其他事务有没有提交。 四. serializable(串行化) 其他会话对该表的写操作将被挂起。可以看到,这是隔离级别中最严格的,但是这样做势必对性能造成影响。所以在实际的选用上,我们要根据当前具体的情况选用合适的。 58题 B+树的高度一般为2-4层,所以查找记录时最多只需要2-4次IO,相对二叉平衡树已经大大降低了。范围查找时,能通过叶子节点的指针获取数据。例如查找大于等于3的数据,当在叶子节点中查到3时,通过3的尾指针便能获取所有数据,而不需要再像二叉树一样再获取到3的父节点。 57题 因为事务在修改页时,要先记 undo,在记 undo 之前要记 undo 的 redo, 然后修改数据页,再记数据页修改的 redo。 Redo(里面包括 undo 的修改) 一定要比数据页先持久化到磁盘。 当事务需要回滚时,因为有 undo,可以把数据页回滚到前镜像的状态,崩溃恢复时,如果 redo log 中事务没有对应的 commit 记录,那么需要用 undo把该事务的修改回滚到事务开始之前。 如果有 commit 记录,就用 redo 前滚到该事务完成时并提交掉。 56题 redo log是物理日志,记录的是"在某个数据页上做了什么修改"。 binlog是逻辑日志,记录的是这个语句的原始逻辑,比如"给ID=2这一行的c字段加1"。 redo log是InnoDB引擎特有的;binlog是MySQL的Server层实现的,所有引擎都可以使用。 redo log是循环写的,空间固定会用完:binlog 是可以追加写入的。"追加写"是指binlog文件写到一定大小后会切换到下一个,并不会覆盖以前的日志。 最开始 MySQL 里并没有 InnoDB 引擎,MySQL 自带的引擎是 MyISAM,但是 MyISAM 没有 crash-safe 的能力,binlog日志只能用于归档。而InnoDB 是另一个公司以插件形式引入 MySQL 的,既然只依靠 binlog 是没有 crash-safe 能力的,所以 InnoDB 使用另外一套日志系统,也就是 redo log 来实现 crash-safe 能力。 55题 重做日志(redo log)      作用:确保事务的持久性,防止在发生故障,脏页未写入磁盘。重启数据库会进行redo log执行重做,达到事务一致性。 回滚日志(undo log)  作用:保证数据的原子性,保存了事务发生之前的数据的一个版本,可以用于回滚,同时可以提供多版本并发控制下的读(MVCC),也即非锁定读。 二进 制日志(binlog)    作用:用于主从复制,实现主从同步;用于数据库的基于时间点的还原。 错误日志(errorlog) 作用:Mysql本身启动,停止,运行期间发生的错误信息。 慢查询日志(slow query log)  作用:记录执行时间过长的sql,时间阈值可以配置,只记录执行成功。 一般查询日志(general log)    作用:记录数据库的操作明细,默认关闭,开启后会降低数据库性能 。 中继日志(relay log) 作用:用于数据库主从同步,将主库发来的bin log保存在本地,然后从库进行回放。 54题 MySQL有三种锁的级别:页级、表级、行级。 表级锁:开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低。 行级锁:开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。 页面锁:开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般。 死锁: 是指两个或两个以上的进程在执行过程中。因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。 死锁的关键在于:两个(或以上)的Session加锁的顺序不一致。 那么对应的解决死锁问题的关键就是:让不同的session加锁有次序。死锁的解决办法:1.查出的线程杀死。2.设置锁的超时时间。3.指定获取锁的顺序。 53题 当多个用户并发地存取数据时,在数据库中就会产生多个事务同时存取同一数据的情况。若对并发操作不加控制就可能会读取和存储不正确的数据,破坏数据库的一致性(脏读,不可重复读,幻读等),可能产生死锁。 乐观锁:乐观锁不是数据库自带的,需要我们自己去实现。 悲观锁:在进行每次操作时都要通过获取锁才能进行对相同数据的操作。 共享锁:加了共享锁的数据对象可以被其他事务读取,但不能修改。 排他锁:当数据对象被加上排它锁时,一个事务必须得到锁才能对该数据对象进行访问,一直到事务结束锁才被释放。 行锁:就是给某一条记录加上锁。 52题 Mysql是关系型数据库,MongoDB是非关系型数据库,数据存储结构的不同。 51题 关系型数据库优点:1.保持数据的一致性(事务处理)。 2.由于以标准化为前提,数据更新的开销很小。 3. 可以进行Join等复杂查询。 缺点:1、为了维护一致性所付出的巨大代价就是其读写性能比较差。 2、固定的表结构。 3、高并发读写需求。 4、海量数据的高效率读写。 非关系型数据库优点:1、无需经过sql层的解析,读写性能很高。 2、基于键值对,数据没有耦合性,容易扩展。 3、存储数据的格式:nosql的存储格式是key,value形式、文档形式、图片形式等等,文档形式、图片形式等等,而关系型数据库则只支持基础类型。 缺点:1、不提供sql支持,学习和使用成本较高。 2、无事务处理,附加功能bi和报表等支持也不好。 redis与mongoDB的区别: 性能:TPS方面redis要大于mongodb。 可操作性:mongodb支持丰富的数据表达,索引,redis较少的网络IO次数。 可用性:MongoDB优于Redis。 一致性:redis事务支持比较弱,mongoDB不支持事务。 数据分析:mongoDB内置了数据分析的功能(mapreduce)。 应用场景:redis数据量较小的更性能操作和运算上,MongoDB主要解决海量数据的访问效率问题。 50题 如果Redis被当做缓存使用,使用一致性哈希实现动态扩容缩容。如果Redis被当做一个持久化存储使用,必须使用固定的keys-to-nodes映射关系,节点的数量一旦确定不能变化。否则的话(即Redis节点需要动态变化的情况),必须使用可以在运行时进行数据再平衡的一套系统,而当前只有Redis集群可以做到这样。 49题 分区可以让Redis管理更大的内存,Redis将可以使用所有机器的内存。如果没有分区,你最多只能使用一台机器的内存。分区使Redis的计算能力通过简单地增加计算机得到成倍提升,Redis的网络带宽也会随着计算机和网卡的增加而成倍增长。 48题 除了缓存服务器自带的缓存失效策略之外(Redis默认的有6种策略可供选择),我们还可以根据具体的业务需求进行自定义的缓存淘汰,常见的策略有两种: 1.定时去清理过期的缓存; 2.当有用户请求过来时,再判断这个请求所用到的缓存是否过期,过期的话就去底层系统得到新数据并更新缓存。 两者各有优劣,第一种的缺点是维护大量缓存的key是比较麻烦的,第二种的缺点就是每次用户请求过来都要判断缓存失效,逻辑相对比较复杂!具体用哪种方案,可以根据应用场景来权衡。 47题 Redis提供了两种方式来作消息队列: 一个是使用生产者消费模式模式:会让一个或者多个客户端监听消息队列,一旦消息到达,消费者马上消费,谁先抢到算谁的,如果队列里没有消息,则消费者继续监听 。另一个就是发布订阅者模式:也是一个或多个客户端订阅消息频道,只要发布者发布消息,所有订阅者都能收到消息,订阅者都是平等的。 46题 Redis的数据结构列表(list)可以实现延时队列,可以通过队列和栈来实现。blpop/brpop来替换lpop/rpop,blpop/brpop阻塞读在队列没有数据的时候,会立即进入休眠状态,一旦数据到来,则立刻醒过来。Redis的有序集合(zset)可以用于实现延时队列,消息作为value,时间作为score。Zrem 命令用于移除有序集中的一个或多个成员,不存在的成员将被忽略。当 key 存在但不是有序集类型时,返回一个错误。 45题 1.热点数据缓存:因为Redis 访问速度块、支持的数据类型比较丰富。 2.限时业务:expire 命令设置 key 的生存时间,到时间后自动删除 key。 3.计数器:incrby 命令可以实现原子性的递增。 4.排行榜:借助 SortedSet 进行热点数据的排序。 5.分布式锁:利用 Redis 的 setnx 命令进行。 6.队列机制:有 list push 和 list pop 这样的命令。 44题 一致哈希 是一种特殊的哈希算法。在使用一致哈希算法后,哈希表槽位数(大小)的改变平均只需要对 K/n 个关键字重新映射,其中K是关键字的数量, n是槽位数量。然而在传统的哈希表中,添加或删除一个槽位的几乎需要对所有关键字进行重新映射。 43题 RDB的优点:适合做冷备份;读写服务影响小,reids可以保持高性能;重启和恢复redis进程,更加快速。RDB的缺点:宕机会丢失最近5分钟的数据;文件特别大时可能会暂停数毫秒,或者甚至数秒。 AOF的优点:每个一秒执行fsync操作,最多丢失1秒钟的数据;以append-only模式写入,没有任何磁盘寻址的开销;文件过大时,不会影响客户端读写;适合做灾难性的误删除的紧急恢复。AOF的缺点:AOF日志文件比RDB数据快照文件更大,支持写QPS比RDB支持的写QPS低;比RDB脆弱,容易有bug。 42题 对于Redis而言,命令的原子性指的是:一个操作的不可以再分,操作要么执行,要么不执行。Redis的操作之所以是原子性的,是因为Redis是单线程的。而在程序中执行多个Redis命令并非是原子性的,这也和普通数据库的表现是一样的,可以用incr或者使用Redis的事务,或者使用Redis+Lua的方式实现。对Redis来说,执行get、set以及eval等API,都是一个一个的任务,这些任务都会由Redis的线程去负责执行,任务要么执行成功,要么执行失败,这就是Redis的命令是原子性的原因。 41题 (1)twemproxy,使用方式简单(相对redis只需修改连接端口),对旧项目扩展的首选。(2)codis,目前用的最多的集群方案,基本和twemproxy一致的效果,但它支持在节点数改变情况下,旧节点数据可恢复到新hash节点。(3)redis cluster3.0自带的集群,特点在于他的分布式算法不是一致性hash,而是hash槽的概念,以及自身支持节点设置从节点。(4)在业务代码层实现,起几个毫无关联的redis实例,在代码层,对key进行hash计算,然后去对应的redis实例操作数据。这种方式对hash层代码要求比较高,考虑部分包括,节点失效后的代替算法方案,数据震荡后的自动脚本恢复,实例的监控,等等。 40题 (1) Master最好不要做任何持久化工作,如RDB内存快照和AOF日志文件 (2) 如果数据比较重要,某个Slave开启AOF备份数据,策略设置为每秒同步一次 (3) 为了主从复制的速度和连接的稳定性,Master和Slave最好在同一个局域网内 (4) 尽量避免在压力很大的主库上增加从库 (5) 主从复制不要用图状结构,用单向链表结构更为稳定,即:Master <- Slave1 <- Slave2 <- Slave3...这样的结构方便解决单点故障问题,实现Slave对Master的替换。如果Master挂了,可以立刻启用Slave1做Master,其他不变。 39题 比如订单管理,热数据:3个月内的订单数据,查询实时性较高;温数据:3个月 ~ 12个月前的订单数据,查询频率不高;冷数据:1年前的订单数据,几乎不会查询,只有偶尔的查询需求。热数据使用mysql进行存储,需要分库分表;温数据可以存储在ES中,利用搜索引擎的特性基本上也可以做到比较快的查询;冷数据可以存放到Hive中。从存储形式来说,一般情况冷数据存储在磁带、光盘,热数据一般存放在SSD中,存取速度快,而温数据可以存放在7200转的硬盘。 38题 当访问量剧增、服务出现问题(如响应时间慢或不响应)或非核心服务影响到核心流程的性能时,仍然需要保证服务还是可用的,即使是有损服务。系统可以根据一些关键数据进行自动降级,也可以配置开关实现人工降级。降级的最终目的是保证核心服务可用,即使是有损的。而且有些服务是无法降级的(如加入购物车、结算)。 37题 分层架构设计,有一条准则:站点层、服务层要做到无数据无状态,这样才能任意的加节点水平扩展,数据和状态尽量存储到后端的数据存储服务,例如数据库服务或者缓存服务。显然进程内缓存违背了这一原则。 36题 更新数据的时候,根据数据的唯一标识,将操作路由之后,发送到一个 jvm 内部队列中。读取数据的时候,如果发现数据不在缓存中,那么将重新读取数据+更新缓存的操作,根据唯一标识路由之后,也发送同一个 jvm 内部队列中。一个队列对应一个工作线程,每个工作线程串行拿到对应的操作,然后一条一条的执行。 35题 redis分布式锁加锁过程:通过setnx向特定的key写入一个随机值,并同时设置失效时间,写值成功既加锁成功;redis分布式锁解锁过程:匹配随机值,删除redis上的特点key数据,要保证获取数据、判断一致以及删除数据三个操作是原子的,为保证原子性一般使用lua脚本实现;在此基础上进一步优化的话,考虑使用心跳检测对锁的有效期进行续期,同时基于redis的发布订阅优雅的实现阻塞式加锁。 34题 volatile-lru:当内存不足以容纳写入数据时,从已设置过期时间的数据集中挑选最近最少使用的数据淘汰。 volatile-ttl:当内存不足以容纳写入数据时,从已设置过期时间的数据集中挑选将要过期的数据淘汰。 volatile-random:当内存不足以容纳写入数据时,从已设置过期时间的数据集中任意选择数据淘汰。 allkeys-lru:当内存不足以容纳写入数据时,从数据集中挑选最近最少使用的数据淘汰。 allkeys-random:当内存不足以容纳写入数据时,从数据集中任意选择数据淘汰。 noeviction:禁止驱逐数据,当内存使用达到阈值的时候,所有引起申请内存的命令会报错。 33题 定时过期:每个设置过期时间的key都需要创建一个定时器,到过期时间就会立即清除。该策略可以立即清除过期的数据,对内存很友好;但是会占用大量的CPU资源去处理过期的数据,从而影响缓存的响应时间和吞吐量。 惰性过期:只有当访问一个key时,才会判断该key是否已过期,过期则清除。该策略可以最大化地节省CPU资源,却对内存非常不友好。极端情况可能出现大量的过期key没有再次被访问,从而不会被清除,占用大量内存。 定期过期:每隔一定的时间,会扫描一定数量的数据库的expires字典中一定数量的key,并清除其中已过期的key。该策略是前两者的一个折中方案。通过调整定时扫描的时间间隔和每次扫描的限定耗时,可以在不同情况下使得CPU和内存资源达到最优的平衡效果。 32题 缓存击穿,一个存在的key,在缓存过期的一刻,同时有大量的请求,这些请求都会击穿到DB,造成瞬时DB请求量大、压力骤增。如何避免:在访问key之前,采用SETNX(set if not exists)来设置另一个短期key来锁住当前key的访问,访问结束再删除该短期key。 31题 缓存雪崩,是指在某一个时间段,缓存集中过期失效。大量的key设置了相同的过期时间,导致在缓存在同一时刻全部失效,造成瞬时DB请求量大、压力骤增,引起雪崩。而缓存服务器某个节点宕机或断网,对数据库服务器造成的压力是不可预知的,很有可能瞬间就把数据库压垮。如何避免:1.redis高可用,搭建redis集群。2.限流降级,在缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量。3.数据预热,在即将发生大并发访问前手动触发加载缓存不同的key,设置不同的过期时间。 30题 缓存穿透,是指查询一个数据库一定不存在的数据。正常的使用缓存流程大致是,数据查询先进行缓存查询,如果key不存在或者key已经过期,再对数据库进行查询,并把查询到的对象,放进缓存。如果数据库查询对象为空,则不放进缓存。一些恶意的请求会故意查询不存在的 key,请求量很大,对数据库造成压力,甚至压垮数据库。 如何避免:1:对查询结果为空的情况也进行缓存,缓存时间设置短一点,或者该 key 对应的数据 insert 了之后清理缓存。2:对一定不存在的 key 进行过滤。可以把所有的可能存在的 key 放到一个大的 Bitmap 中,查询时通过该 bitmap 过滤。 29题 1.memcached 所有的值均是简单的字符串,redis 作为其替代者,支持更为丰富的数据类型。 2.redis 的速度比 memcached 快很多。 3.redis 可以持久化其数据。 4.Redis支持数据的备份,即master-slave模式的数据备份。 5.Redis采用VM机制。 6.value大小:redis最大可以达到1GB,而memcache只有1MB。 28题 Spring Boot 推荐使用 Java 配置而非 XML 配置,但是 Spring Boot 中也可以使用 XML 配置,通过spring提供的@ImportResource来加载xml配置。例如:@ImportResource({"classpath:some-context.xml","classpath:another-context.xml"}) 27题 Spring像一个大家族,有众多衍生产品例如Spring Boot,Spring Security等等,但他们的基础都是Spring的IOC和AOP,IOC提供了依赖注入的容器,而AOP解决了面向切面的编程,然后在此两者的基础上实现了其他衍生产品的高级功能。Spring MVC是基于Servlet的一个MVC框架,主要解决WEB开发的问题,因为 Spring的配置非常复杂,各种xml,properties处理起来比较繁琐。Spring Boot遵循约定优于配置,极大降低了Spring使用门槛,又有着Spring原本灵活强大的功能。总结:Spring MVC和Spring Boot都属于Spring,Spring MVC是基于Spring的一个MVC框架,而Spring Boot是基于Spring的一套快速开发整合包。 26题 YAML 是 "YAML Ain't a Markup Language"(YAML 不是一种标记语言)的递归缩写。YAML 的配置文件后缀为 .yml,是一种人类可读的数据序列化语言,可以简单表达清单、散列表,标量等数据形态。它通常用于配置文件,与属性文件相比,YAML文件就更加结构化,而且更少混淆。可以看出YAML具有分层配置数据。 25题 Spring Boot有3种热部署方式: 1.使用springloaded配置pom.xml文件,使用mvn spring-boot:run启动。 2.使用springloaded本地加载启动,配置jvm参数-javaagent:<jar包地址> -noverify。 3.使用devtools工具包,操作简单,但是每次需要重新部署。 用

游客ih62co2qqq5ww 2020-03-27 23:56:48 0 浏览量 回答数 0

问题

五步教你如何学习前端开发

云效平台 2019-12-01 21:44:57 7061 浏览量 回答数 4

问题

达达O2O后台架构演进实践:从0到4000高并发请求背后的努力:报错

kun坤 2020-06-09 15:20:48 4 浏览量 回答数 1

回答

提交注册表单到后端处理时,调用第三方短信服务(手机号码,后端生成验证码),限制多少时间内重发。验证码可以保存数据库中有效时间,或者session中设置过期时间问题有些太开放,宽松制约。重新考虑一下需求;如你所说的确实是个问题。或者其他人解答一下手机号码注册,短信只作验证功能(省事,用户群体比较有质量,手机号码唯一性,防止恶意刷注册用户数)/邮箱验证也可以,用户体验上手机较好(后期还可以通过手机号码去分析用户) 如果每次登陆都用短信验证码(短信服务还是要钱的...这个一天登陆一多就懂) ######首先 非常感谢你这么认真的回答。 我看完后 再回复你。先谢谢你###### 1. 你们服务端生成 短信 内容 提交到他们那,验证码可以放到缓存里,用户确定的时候检查缓存.写一个公共的服务组件, Linux可用crontab Win可用定时任务,在指定时间段内 每分钟查询下数据库,提交到短信提供商.最好不要使用短信登陆. ######关于问题1 ,一般都是用户前台输入手机号,点击获取验证码按钮后先在自己服务器根据短信服务商的接口规范生成url(包括验证码的生成,生成之后保存在session或者数据库中),然后用curl发请求,收到一个唯一的短信id就表示发送成功了(但是有可能是对方服务器出了问题,收到了id用户还没收到短信,我遇到过这个问题,最后他们换了一个线路解决了)###### 引用来自“p2ng”的评论 提交注册表单到后端处理时,调用第三方短信服务(手机号码,后端生成验证码),限制多少时间内重发。验证码可以保存数据库中有效时间,或者session中设置过期时间问题有些太开放,宽松制约。重新考虑一下需求;如你所说的确实是个问题。或者其他人解答一下手机号码注册,短信只作验证功能(省事,用户群体比较有质量,手机号码唯一性,防止恶意刷注册用户数)/邮箱验证也可以,用户体验上手机较好(后期还可以通过手机号码去分析用户) 如果每次登陆都用短信验证码(短信服务还是要钱的...这个一天登陆一多就懂) 回复1: 一般大家的普通做法是 保持数据库中还是SESSION中 还是内存中啊。  验证码好像就是临时的吧。 这个手机验证码 是需要我自定义生成吗? 我做过登陆图形验证码。用户输入后判断下。就行。提交一次重新生成。 但这个貌似可以提交多次,直到你输入正确的短信验证码是吧? 回复2: 举个简单例子吧: 我加入要做个提醒的功能。  我在web网站上 设置好时间,设置后内容。然后我当天那个时间收到这个短信内容。 我就是提供给会员这个事情。  比如我做一个比赛预告的WEB页面,用户点击比赛前1小时短信提醒我。  回复3: 每次短信登陆的确很麻烦也很费钱。 但类似微博就是这种的啊。 可以提供手机短信登陆的啊。 短信登陆唯一好处就是 用户注册/登陆都一样的,这样用户注册的时候就没有密码设置这一项,用户第一次实用的体验度会很好。。。。 ###### 引用来自“金马超”的评论 你们服务端生成 短信 内容 提交到他们那,验证码可以放到缓存里,用户确定的时候检查缓存.写一个公共的服务组件, Linux可用crontab Win可用定时任务,在指定时间段内 每分钟查询下数据库,提交到短信提供商.最好不要使用短信登陆. 回复1: 大体思路我明白了,只是之前没做过短信注册这个模块。 我看看第三方1069通道的 应该不难。 或者网上搜搜下 回复2: linux的crontab定时任务和win我都会,但我的意思是 一个用户 写周四下午3点 那我这边就执行一个定时任务会不会太浪费了?也太多了? 或者你说,每分钟查下数据库 也就是每隔一分钟执行一个php脚本文件,遍历循环下? 有的话就发 没有的 就不发。 就等于轮询? 这样是不是很耗费服务器资源? 有没有其他解解方法 回复3: 你的意思是 短信注册可以,然后引导用户设置密码。 但手机短信登陆不建议ma? 但我的意思,像weibo就是手机短信验证码直接登陆 携程也是这样 还有一种是你说的只能手机+密码来登陆 那我的意思是,如果二者并行,怎么设计这个表。。。 ###### 引用来自“西南茂”的评论关于问题1 ,一般都是用户前台输入手机号,点击获取验证码按钮后先在自己服务器根据短信服务商的接口规范生成url(包括验证码的生成,生成之后保存在session或者数据库中),然后用curl发请求,收到一个唯一的短信id就表示发送成功了(但是有可能是对方服务器出了问题,收到了id用户还没收到短信,我遇到过这个问题,最后他们换了一个线路解决了) 回复1: 你的流程是   用户填手机号---》用户点击提交获取验证码--》服务器生成一个验证码---》这个验证码通过sdk 用curl发送到短信运营商---》短信运营商服务器收到后发到用户手机号上---》 用户收到输入这个验证码--》我们后台核对  OK? ######对,差不多就是这个流程###### 引用来自“金马超”的评论 你们服务端生成 短信 内容 提交到他们那,验证码可以放到缓存里,用户确定的时候检查缓存.写一个公共的服务组件, Linux可用crontab Win可用定时任务,在指定时间段内 每分钟查询下数据库,提交到短信提供商.最好不要使用短信登陆. 引用来自“kacc850”的评论 回复1: 大体思路我明白了,只是之前没做过短信注册这个模块。 我看看第三方1069通道的 应该不难。 或者网上搜搜下 回复2: linux的crontab定时任务和win我都会,但我的意思是 一个用户 写周四下午3点 那我这边就执行一个定时任务会不会太浪费了?也太多了? 或者你说,每分钟查下数据库 也就是每隔一分钟执行一个php脚本文件,遍历循环下? 有的话就发 没有的 就不发。 就等于轮询? 这样是不是很耗费服务器资源? 有没有其他解解方法 回复3: 你的意思是 短信注册可以,然后引导用户设置密码。 但手机短信登陆不建议ma? 但我的意思,像weibo就是手机短信验证码直接登陆 携程也是这样 还有一种是你说的只能手机+密码来登陆 那我的意思是,如果二者并行,怎么设计这个表。。。 写成一个公共的组件...   这个服务从指定的一张表里查询数据 eg  ID 内容 下发时间 手机号 ... 只要代码没问题的话  对服务器来说不会是什么太大的问题.嗯   是这样的,不建议短信登陆,可以用短信找回密码. 你们公司不是微博/携程,没人家那种财力,最好不要这么做, 而且短信这个行业也不是你想的那么简单,提交就能发的. 如果要并行的话,单独建立一张表用来记录短信登陆比较好. 用户表只放基本信息,短信登陆表 带上用户名,手机号,登陆时间,IP可有可无. 和用户表稍微关联下就行. ######硕达通短信平台,发验证码5秒到,发通知5秒到,速度快,到达率98%以上,成功计费(失败不计费)实时状态报告(成功失败一目了然)支持上下行 北京硕达通  www.shdat.com  买短信有红包!######凌凯短信:快/3秒响应 ·12年品牌塑造,三网(移动、联通、电信)通道,覆盖所有手机号码 ·3秒快速响应,行业领先(www.028lk.com)######雨林木风短信平台,三网合一,五秒达到,到达率99%,欢迎站内信哟~~~~

kun坤 2020-06-11 10:43:41 0 浏览量 回答数 0

回答

Android平台进行数据存储的五大方式,分别如下: 1 使用SharedPreferences存储数据 2 文件存储数据 3 SQLite数据库存储数据 4 使用ContentProvider存储数据 5 网络存储数据 下面详细讲解这五种方式的特点 第一种: 使用SharedPreferences存储数据 适用范围:保存少量的数据,且这些数据的格式非常简单:字符串型、基本类型的值。比如应用程序的各种配置信息(如是否打开音效、是否使用震动效果、小游戏的玩家积分等),解锁口 令密码等 核心原理:保存基于XML文件存储的key-value键值对数据,通常用来存储一些简单的配置信息。通过DDMS的File Explorer面板,展开文件浏览树,很明显SharedPreferences数据总是存储在/data/data/<package name>/shared_prefs目录下。SharedPreferences对象本身只能获取数据而不支持存储和修改,存储修改是通过SharedPreferences.edit()获取的内部接口Editor对象实现。 SharedPreferences本身是一 个接口,程序无法直接创建SharedPreferences实例,只能通过Context提供的getSharedPreferences(String name, int mode)方法来获取SharedPreferences实例,该方法中name表示要操作的xml文件名,第二个参数具体如下: Context.MODE_PRIVATE: 指定该SharedPreferences数据只能被本应用程序读、写。 Context.MODE_WORLD_READABLE: 指定该SharedPreferences数据能被其他应用程序读,但不能写。 Context.MODE_WORLD_WRITEABLE: 指定该SharedPreferences数据能被其他应用程序读,写 Editor有如下主要重要方法: SharedPreferences.Editor clear():清空SharedPreferences里所有数据 SharedPreferences.Editor putXxx(String key , xxx value): 向SharedPreferences存入指定key对应的数据,其中xxx 可以是boolean,float,int等各种基本类型据 SharedPreferences.Editor remove(): 删除SharedPreferences中指定key对应的数据项 boolean commit(): 当Editor编辑完成后,使用该方法提交修改 实际案例:运行界面如下 这里只提供了两个按钮和一个输入文本框,布局简单,故在此不给出界面布局文件了,程序核心代码如下: 、class ViewOcl implements View.OnClickListener{ @Override public void onClick(View v) { switch(v.getId()){ case R.id.btnSet: //步骤1:获取输入值 String code = txtCode.getText().toString().trim(); //步骤2-1:创建一个SharedPreferences.Editor接口对象,lock表示要写入的XML文件名,MODE_WORLD_WRITEABLE写操作 SharedPreferences.Editor editor = getSharedPreferences("lock", MODE_WORLD_WRITEABLE).edit(); //步骤2-2:将获取过来的值放入文件 editor.putString("code", code); //步骤3:提交 editor.commit(); Toast.makeText(getApplicationContext(), "口令设置成功", Toast.LENGTH_LONG).show(); break; case R.id.btnGet: //步骤1:创建一个SharedPreferences接口对象 SharedPreferences read = getSharedPreferences("lock", MODE_WORLD_READABLE); //步骤2:获取文件中的值 String value = read.getString("code", ""); Toast.makeText(getApplicationContext(), "口令为:"+value, Toast.LENGTH_LONG).show(); break; } } } 、读写其他应用的SharedPreferences: 步骤如下 1、在创建SharedPreferences时,指定MODE_WORLD_READABLE模式,表明该SharedPreferences数据可以被其他程序读取 2、创建其他应用程序对应的Context: Context pvCount = createPackageContext("com.tony.app", Context.CONTEXT_IGNORE_SECURITY);这里的com.tony.app就是其他程序的包名 3、使用其他程序的Context获取对应的SharedPreferences SharedPreferences read = pvCount.getSharedPreferences("lock", Context.MODE_WORLD_READABLE); 4、如果是写入数据,使用Editor接口即可,所有其他操作均和前面一致。 SharedPreferences对象与SQLite数据库相比,免去了创建数据库,创建表,写SQL语句等诸多操作,相对而言更加方便,简洁。但是SharedPreferences也有其自身缺陷,比如其职能存储boolean,int,float,long和String五种简单的数据类型,比如其无法进行条件查询等。所以不论SharedPreferences的数据存储操作是如何简单,它也只能是存储方式的一种补充,而无法完全替代如SQLite数据库这样的其他数据存储方式。 第二种: 文件存储数据 核心原理: Context提供了两个方法来打开数据文件里的文件IO流 FileInputStream openFileInput(String name); FileOutputStream(String name , int mode),这两个方法第一个参数 用于指定文件名,第二个参数指定打开文件的模式。具体有以下值可选: MODE_PRIVATE:为默认操作模式,代表该文件是私有数据,只能被应用本身访问,在该模式下,写入的内容会覆盖原文件的内容,如果想把新写入的内容追加到原文件中。可 以使用Context.MODE_APPEND MODE_APPEND:模式会检查文件是否存在,存在就往文件追加内容,否则就创建新文件。 MODE_WORLD_READABLE:表示当前文件可以被其他应用读取; MODE_WORLD_WRITEABLE:表示当前文件可以被其他应用写入。 除此之外,Context还提供了如下几个重要的方法: getDir(String name , int mode):在应用程序的数据文件夹下获取或者创建name对应的子目录 File getFilesDir():获取该应用程序的数据文件夹得绝对路径 String[] fileList():返回该应用数据文件夹的全部文件 public String read() { try { FileInputStream inStream = this.openFileInput("message.txt"); byte[] buffer = new byte[1024]; int hasRead = 0; StringBuilder sb = new StringBuilder(); while ((hasRead = inStream.read(buffer)) != -1) { sb.append(new String(buffer, 0, hasRead)); } inStream.close(); return sb.toString(); } catch (Exception e) { e.printStackTrace(); } return null; } public void write(String msg){ // 步骤1:获取输入值 if(msg == null) return; try { // 步骤2:创建一个FileOutputStream对象,MODE_APPEND追加模式 FileOutputStream fos = openFileOutput("message.txt", MODE_APPEND); // 步骤3:将获取过来的值放入文件 fos.write(msg.getBytes()); // 步骤4:关闭数据流 fos.close(); } catch (Exception e) { e.printStackTrace(); } } openFileOutput()方法的第一参数用于指定文件名称,不能包含路径分隔符“/” ,如果文件不存在,Android 会自动创建它。创建的文件保存在/data/data//files目录,如: /data/data/cn.tony.app/files/message.txt, 下面讲解某些特殊文件读写需要注意的地方: 读写sdcard上的文件 其中读写步骤按如下进行: 1、调用Environment的getExternalStorageState()方法判断手机上是否插了sd卡,且应用程序具有读写SD卡的权限,如下代码将返回true Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED) 2、调用Environment.getExternalStorageDirectory()方法来获取外部存储器,也就是SD卡的目录,或者使用"/mnt/sdcard/"目录 3、使用IO流操作SD卡上的文件 注意点:手机应该已插入SD卡,对于模拟器而言,可通过mksdcard命令来创建虚拟存储卡 必须在AndroidManifest.xml上配置读写SD卡的权限 // 文件写操作函数 private void write(String content) { if (Environment.getExternalStorageState().equals( Environment.MEDIA_MOUNTED)) { // 如果sdcard存在 File file = new File(Environment.getExternalStorageDirectory() .toString() + File.separator + DIR + File.separator + FILENAME); // 定义File类对象 if (!file.getParentFile().exists()) { // 父文件夹不存在 file.getParentFile().mkdirs(); // 创建文件夹 } PrintStream out = null; // 打印流对象用于输出 try { out = new PrintStream(new FileOutputStream(file, true)); // 追加文件 out.println(content); } catch (Exception e) { e.printStackTrace(); } finally { if (out != null) { out.close(); // 关闭打印流 } } } else { // SDCard不存在,使用Toast提示用户 Toast.makeText(this, "保存失败,SD卡不存在!", Toast.LENGTH_LONG).show(); } } // 文件读操作函数 private String read() { if (Environment.getExternalStorageState().equals( Environment.MEDIA_MOUNTED)) { // 如果sdcard存在 File file = new File(Environment.getExternalStorageDirectory() .toString() + File.separator + DIR + File.separator + FILENAME); // 定义File类对象 if (!file.getParentFile().exists()) { // 父文件夹不存在 file.getParentFile().mkdirs(); // 创建文件夹 } Scanner scan = null; // 扫描输入 StringBuilder sb = new StringBuilder(); try { scan = new Scanner(new FileInputStream(file)); // 实例化Scanner while (scan.hasNext()) { // 循环读取 sb.append(scan.next() + "\n"); // 设置文本 } return sb.toString(); } catch (Exception e) { e.printStackTrace(); } finally { if (scan != null) { scan.close(); // 关闭打印流 } } } else { // SDCard不存在,使用Toast提示用户 Toast.makeText(this, "读取失败,SD卡不存在!", Toast.LENGTH_LONG).show(); } return null; } 复制代码 第三种:SQLite存储数据 SQLite是轻量级嵌入式数据库引擎,它支持 SQL 语言,并且只利用很少的内存就有很好的性能。现在的主流移动设备像Android、iPhone等都使用SQLite作为复杂数据的存储引擎,在我们为移动设备开发应用程序时,也许就要使用到SQLite来存储我们大量的数据,所以我们就需要掌握移动设备上的SQLite开发技巧 SQLiteDatabase类为我们提供了很多种方法,上面的代码中基本上囊括了大部分的数据库操作;对于添加、更新和删除来说,我们都可以使用 1 db.executeSQL(String sql); 2 db.executeSQL(String sql, Object[] bindArgs);//sql语句中使用占位符,然后第二个参数是实际的参数集 除了统一的形式之外,他们还有各自的操作方法: 1 db.insert(String table, String nullColumnHack, ContentValues values); 2 db.update(String table, Contentvalues values, String whereClause, String whereArgs); 3 db.delete(String table, String whereClause, String whereArgs);以上三个方法的第一个参数都是表示要操作的表名;insert中的第二个参数表示如果插入的数据每一列都为空的话,需要指定此行中某一列的名称,系统将此列设置为NULL,不至于出现错误;insert中的第三个参数是ContentValues类型的变量,是键值对组成的Map,key代表列名,value代表该列要插入的值;update的第二个参数也很类似,只不过它是更新该字段key为最新的value值,第三个参数whereClause表示WHERE表达式,比如“age > ? and age < ?”等,最后的whereArgs参数是占位符的实际参数值;delete方法的参数也是一样 下面给出demo 数据的添加 1.使用insert方法 复制代码1 ContentValues cv = new ContentValues();//实例化一个ContentValues用来装载待插入的数据2 cv.put("title","you are beautiful");//添加title3 cv.put("weather","sun"); //添加weather4 cv.put("context","xxxx"); //添加context5 String publish = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")6 .format(new Date());7 cv.put("publish ",publish); //添加publish8 db.insert("diary",null,cv);//执行插入操作复制代码2.使用execSQL方式来实现 String sql = "insert into user(username,password) values ('Jack Johnson','iLovePopMuisc');//插入操作的SQL语句db.execSQL(sql);//执行SQL语句数据的删除 同样有2种方式可以实现 String whereClause = "username=?";//删除的条件String[] whereArgs = {"Jack Johnson"};//删除的条件参数db.delete("user",whereClause,whereArgs);//执行删除使用execSQL方式的实现 String sql = "delete from user where username='Jack Johnson'";//删除操作的SQL语句db.execSQL(sql);//执行删除操作数据修改 同上,仍是2种方式 ContentValues cv = new ContentValues();//实例化ContentValuescv.put("password","iHatePopMusic");//添加要更改的字段及内容String whereClause = "username=?";//修改条件String[] whereArgs = {"Jack Johnson"};//修改条件的参数db.update("user",cv,whereClause,whereArgs);//执行修改使用execSQL方式的实现 String sql = "update user set password = 'iHatePopMusic' where username='Jack Johnson'";//修改的SQL语句db.execSQL(sql);//执行修改数据查询 下面来说说查询操作。查询操作相对于上面的几种操作要复杂些,因为我们经常要面对着各种各样的查询条件,所以系统也考虑到这种复杂性,为我们提供了较为丰富的查询形式: 1 db.rawQuery(String sql, String[] selectionArgs); 2 db.query(String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy); 3 db.query(String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit); 4 db.query(String distinct, String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit); 上面几种都是常用的查询方法,第一种最为简单,将所有的SQL语句都组织到一个字符串中,使用占位符代替实际参数,selectionArgs就是占位符实际参数集; 各参数说明: table:表名称colums:表示要查询的列所有名称集selection:表示WHERE之后的条件语句,可以使用占位符selectionArgs:条件语句的参数数组groupBy:指定分组的列名having:指定分组条件,配合groupBy使用orderBy:y指定排序的列名limit:指定分页参数distinct:指定“true”或“false”表示要不要过滤重复值Cursor:返回值,相当于结果集ResultSet最后,他们同时返回一个Cursor对象,代表数据集的游标,有点类似于JavaSE中的ResultSet。下面是Cursor对象的常用方法: 复制代码 1 c.move(int offset); //以当前位置为参考,移动到指定行 2 c.moveToFirst(); //移动到第一行 3 c.moveToLast(); //移动到最后一行 4 c.moveToPosition(int position); //移动到指定行 5 c.moveToPrevious(); //移动到前一行 6 c.moveToNext(); //移动到下一行 7 c.isFirst(); //是否指向第一条 8 c.isLast(); //是否指向最后一条 9 c.isBeforeFirst(); //是否指向第一条之前 10 c.isAfterLast(); //是否指向最后一条之后 11 c.isNull(int columnIndex); //指定列是否为空(列基数为0) 12 c.isClosed(); //游标是否已关闭 13 c.getCount(); //总数据项数 14 c.getPosition(); //返回当前游标所指向的行数 15 c.getColumnIndex(String columnName);//返回某列名对应的列索引值 16 c.getString(int columnIndex); //返回当前行指定列的值 复制代码实现代码 复制代码String[] params = {12345,123456};Cursor cursor = db.query("user",columns,"ID=?",params,null,null,null);//查询并获得游标if(cursor.moveToFirst()){//判断游标是否为空 for(int i=0;i<cursor.getCount();i++){ cursor.move(i);//移动到指定记录 String username = cursor.getString(cursor.getColumnIndex("username"); String password = cursor.getString(cursor.getColumnIndex("password")); } }复制代码通过rawQuery实现的带参数查询 复制代码Cursor result=db.rawQuery("SELECT ID, name, inventory FROM mytable");//Cursor c = db.rawQuery("s name, inventory FROM mytable where ID=?",new Stirng[]{"123456"}); result.moveToFirst(); while (!result.isAfterLast()) { int id=result.getInt(0); String name=result.getString(1); int inventory=result.getInt(2); // do something useful with these result.moveToNext(); } result.close();复制代码 在上面的代码示例中,已经用到了这几个常用方法中的一些,关于更多的信息,大家可以参考官方文档中的说明。 最后当我们完成了对数据库的操作后,记得调用SQLiteDatabase的close()方法释放数据库连接,否则容易出现SQLiteException。 上面就是SQLite的基本应用,但在实际开发中,为了能够更好的管理和维护数据库,我们会封装一个继承自SQLiteOpenHelper类的数据库操作类,然后以这个类为基础,再封装我们的业务逻辑方法。 这里直接使用案例讲解:下面是案例demo的界面 SQLiteOpenHelper类介绍 SQLiteOpenHelper是SQLiteDatabase的一个帮助类,用来管理数据库的创建和版本的更新。一般是建立一个类继承它,并实现它的onCreate和onUpgrade方法。 方法名 方法描述SQLiteOpenHelper(Context context,String name,SQLiteDatabase.CursorFactory factory,int version) 构造方法,其中 context 程序上下文环境 即:XXXActivity.this; name :数据库名字; factory:游标工厂,默认为null,即为使用默认工厂; version 数据库版本号 onCreate(SQLiteDatabase db) 创建数据库时调用onUpgrade(SQLiteDatabase db,int oldVersion , int newVersion) 版本更新时调用getReadableDatabase() 创建或打开一个只读数据库getWritableDatabase() 创建或打开一个读写数据库首先创建数据库类 复制代码 1 import android.content.Context; 2 import android.database.sqlite.SQLiteDatabase; 3 import android.database.sqlite.SQLiteDatabase.CursorFactory; 4 import android.database.sqlite.SQLiteOpenHelper; 5 6 public class SqliteDBHelper extends SQLiteOpenHelper { 7 8 // 步骤1:设置常数参量 9 private static final String DATABASE_NAME = "diary_db";10 private static final int VERSION = 1;11 private static final String TABLE_NAME = "diary";12 13 // 步骤2:重载构造方法14 public SqliteDBHelper(Context context) {15 super(context, DATABASE_NAME, null, VERSION);16 }17 18 /*19 * 参数介绍:context 程序上下文环境 即:XXXActivity.this 20 * name 数据库名字 21 * factory 接收数据,一般情况为null22 * version 数据库版本号23 */24 public SqliteDBHelper(Context context, String name, CursorFactory factory,25 int version) {26 super(context, name, factory, version);27 }28 //数据库第一次被创建时,onCreate()会被调用29 @Override30 public void onCreate(SQLiteDatabase db) {31 // 步骤3:数据库表的创建32 String strSQL = "create table "33 + TABLE_NAME34 + "(tid integer primary key autoincrement,title varchar(20),weather varchar(10),context text,publish date)";35 //步骤4:使用参数db,创建对象36 db.execSQL(strSQL);37 }38 //数据库版本变化时,会调用onUpgrade()39 @Override40 public void onUpgrade(SQLiteDatabase arg0, int arg1, int arg2) {41 42 }43 }复制代码正如上面所述,数据库第一次创建时onCreate方法会被调用,我们可以执行创建表的语句,当系统发现版本变化之后,会调用onUpgrade方法,我们可以执行修改表结构等语句。 我们需要一个Dao,来封装我们所有的业务方法,代码如下: 复制代码 1 import android.content.Context; 2 import android.database.Cursor; 3 import android.database.sqlite.SQLiteDatabase; 4 5 import com.chinasoft.dbhelper.SqliteDBHelper; 6 7 public class DiaryDao { 8 9 private SqliteDBHelper sqliteDBHelper;10 private SQLiteDatabase db;11 12 // 重写构造方法13 public DiaryDao(Context context) {14 this.sqliteDBHelper = new SqliteDBHelper(context);15 db = sqliteDBHelper.getWritableDatabase();16 }17 18 // 读操作19 public String execQuery(final String strSQL) {20 try {21 System.out.println("strSQL>" + strSQL);22 // Cursor相当于JDBC中的ResultSet23 Cursor cursor = db.rawQuery(strSQL, null);24 // 始终让cursor指向数据库表的第1行记录25 cursor.moveToFirst();26 // 定义一个StringBuffer的对象,用于动态拼接字符串27 StringBuffer sb = new StringBuffer();28 // 循环游标,如果不是最后一项记录29 while (!cursor.isAfterLast()) {30 sb.append(cursor.getInt(0) + "/" + cursor.getString(1) + "/"31 + cursor.getString(2) + "/" + cursor.getString(3) + "/"32 + cursor.getString(4)+"#");33 //cursor游标移动34 cursor.moveToNext();35 }36 db.close();37 return sb.deleteCharAt(sb.length()-1).toString();38 } catch (RuntimeException e) {39 e.printStackTrace();40 return null;41 }42 43 }44 45 // 写操作46 public boolean execOther(final String strSQL) {47 db.beginTransaction(); //开始事务48 try {49 System.out.println("strSQL" + strSQL);50 db.execSQL(strSQL);51 db.setTransactionSuccessful(); //设置事务成功完成 52 db.close();53 return true;54 } catch (RuntimeException e) {55 e.printStackTrace();56 return false;57 }finally { 58 db.endTransaction(); //结束事务 59 } 60 61 }62 }复制代码我们在Dao构造方法中实例化sqliteDBHelper并获取一个SQLiteDatabase对象,作为整个应用的数据库实例;在增删改信息时,我们采用了事务处理,确保数据完整性;最后要注意释放数据库资源db.close(),这一个步骤在我们整个应用关闭时执行,这个环节容易被忘记,所以朋友们要注意。 我们获取数据库实例时使用了getWritableDatabase()方法,也许朋友们会有疑问,在getWritableDatabase()和getReadableDatabase()中,你为什么选择前者作为整个应用的数据库实例呢?在这里我想和大家着重分析一下这一点。 我们来看一下SQLiteOpenHelper中的getReadableDatabase()方法: 复制代码 1 public synchronized SQLiteDatabase getReadableDatabase() { 2 if (mDatabase != null && mDatabase.isOpen()) { 3 // 如果发现mDatabase不为空并且已经打开则直接返回 4 return mDatabase; 5 } 6 7 if (mIsInitializing) { 8 // 如果正在初始化则抛出异常 9 throw new IllegalStateException("getReadableDatabase called recursively"); 10 } 11 12 // 开始实例化数据库mDatabase 13 14 try { 15 // 注意这里是调用了getWritableDatabase()方法 16 return getWritableDatabase(); 17 } catch (SQLiteException e) { 18 if (mName == null) 19 throw e; // Can't open a temp database read-only! 20 Log.e(TAG, "Couldn't open " + mName + " for writing (will try read-only):", e); 21 } 22 23 // 如果无法以可读写模式打开数据库 则以只读方式打开 24 25 SQLiteDatabase db = null; 26 try { 27 mIsInitializing = true; 28 String path = mContext.getDatabasePath(mName).getPath();// 获取数据库路径 29 // 以只读方式打开数据库 30 db = SQLiteDatabase.openDatabase(path, mFactory, SQLiteDatabase.OPEN_READONLY); 31 if (db.getVersion() != mNewVersion) { 32 throw new SQLiteException("Can't upgrade read-only database from version " + db.getVersion() + " to " 33 + mNewVersion + ": " + path); 34 } 35 36 onOpen(db); 37 Log.w(TAG, "Opened " + mName + " in read-only mode"); 38 mDatabase = db;// 为mDatabase指定新打开的数据库 39 return mDatabase;// 返回打开的数据库 40 } finally { 41 mIsInitializing = false; 42 if (db != null && db != mDatabase) 43 db.close(); 44 } 45 }复制代码在getReadableDatabase()方法中,首先判断是否已存在数据库实例并且是打开状态,如果是,则直接返回该实例,否则试图获取一个可读写模式的数据库实例,如果遇到磁盘空间已满等情况获取失败的话,再以只读模式打开数据库,获取数据库实例并返回,然后为mDatabase赋值为最新打开的数据库实例。既然有可能调用到getWritableDatabase()方法,我们就要看一下了: 复制代码public synchronized SQLiteDatabase getWritableDatabase() { if (mDatabase != null && mDatabase.isOpen() && !mDatabase.isReadOnly()) { // 如果mDatabase不为空已打开并且不是只读模式 则返回该实例 return mDatabase; } if (mIsInitializing) { throw new IllegalStateException("getWritableDatabase called recursively"); } // If we have a read-only database open, someone could be using it // (though they shouldn't), which would cause a lock to be held on // the file, and our attempts to open the database read-write would // fail waiting for the file lock. To prevent that, we acquire the // lock on the read-only database, which shuts out other users. boolean success = false; SQLiteDatabase db = null; // 如果mDatabase不为空则加锁 阻止其他的操作 if (mDatabase != null) mDatabase.lock(); try { mIsInitializing = true; if (mName == null) { db = SQLiteDatabase.create(null); } else { // 打开或创建数据库 db = mContext.openOrCreateDatabase(mName, 0, mFactory); } // 获取数据库版本(如果刚创建的数据库,版本为0) int version = db.getVersion(); // 比较版本(我们代码中的版本mNewVersion为1) if (version != mNewVersion) { db.beginTransaction();// 开始事务 try { if (version == 0) { // 执行我们的onCreate方法 onCreate(db); } else { // 如果我们应用升级了mNewVersion为2,而原版本为1则执行onUpgrade方法 onUpgrade(db, version, mNewVersion); } db.setVersion(mNewVersion);// 设置最新版本 db.setTransactionSuccessful();// 设置事务成功 } finally { db.endTransaction();// 结束事务 } } onOpen(db); success = true; return db;// 返回可读写模式的数据库实例 } finally { mIsInitializing = false; if (success) { // 打开成功 if (mDatabase != null) { // 如果mDatabase有值则先关闭 try { mDatabase.close(); } catch (Exception e) { } mDatabase.unlock();// 解锁 } mDatabase = db;// 赋值给mDatabase } else { // 打开失败的情况:解锁、关闭 if (mDatabase != null) mDatabase.unlock(); if (db != null) db.close(); } } }复制代码大家可以看到,几个关键步骤是,首先判断mDatabase如果不为空已打开并不是只读模式则直接返回,否则如果mDatabase不为空则加锁,然后开始打开或创建数据库,比较版本,根据版本号来调用相应的方法,为数据库设置新版本号,最后释放旧的不为空的mDatabase并解锁,把新打开的数据库实例赋予mDatabase,并返回最新实例。 看完上面的过程之后,大家或许就清楚了许多,如果不是在遇到磁盘空间已满等情况,getReadableDatabase()一般都会返回和getWritableDatabase()一样的数据库实例,所以我们在DBManager构造方法中使用getWritableDatabase()获取整个应用所使用的数据库实例是可行的。当然如果你真的担心这种情况会发生,那么你可以先用getWritableDatabase()获取数据实例,如果遇到异常,再试图用getReadableDatabase()获取实例,当然这个时候你获取的实例只能读不能写了 最后,让我们看一下如何使用这些数据操作方法来显示数据,界面核心逻辑代码: 复制代码public class SQLiteActivity extends Activity { public DiaryDao diaryDao; //因为getWritableDatabase内部调用了mContext.openOrCreateDatabase(mName, 0, mFactory); //所以要确保context已初始化,我们可以把实例化Dao的步骤放在Activity的onCreate里 @Override protected void onCreate(Bundle savedInstanceState) { diaryDao = new DiaryDao(SQLiteActivity.this); initDatabase(); } class ViewOcl implements View.OnClickListener { @Override public void onClick(View v) { String strSQL; boolean flag; String message; switch (v.getId()) { case R.id.btnAdd: String title = txtTitle.getText().toString().trim(); String weather = txtWeather.getText().toString().trim();; String context = txtContext.getText().toString().trim();; String publish = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss") .format(new Date()); // 动态组件SQL语句 strSQL = "insert into diary values(null,'" + title + "','" + weather + "','" + context + "','" + publish + "')"; flag = diaryDao.execOther(strSQL); //返回信息 message = flag?"添加成功":"添加失败"; Toast.makeText(getApplicationContext(), message, Toast.LENGTH_LONG).show(); break; case R.id.btnDelete: strSQL = "delete from diary where tid = 1"; flag = diaryDao.execOther(strSQL); //返回信息 message = flag?"删除成功":"删除失败"; Toast.makeText(getApplicationContext(), message, Toast.LENGTH_LONG).show(); break; case R.id.btnQuery: strSQL = "select * from diary order by publish desc"; String data = diaryDao.execQuery(strSQL); Toast.makeText(getApplicationContext(), data, Toast.LENGTH_LONG).show(); break; case R.id.btnUpdate: strSQL = "update diary set title = '测试标题1-1' where tid = 1"; flag = diaryDao.execOther(strSQL); //返回信息 message = flag?"更新成功":"更新失败"; Toast.makeText(getApplicationContext(), message, Toast.LENGTH_LONG).show(); break; } } } private void initDatabase() { // 创建数据库对象 SqliteDBHelper sqliteDBHelper = new SqliteDBHelper(SQLiteActivity.this); sqliteDBHelper.getWritableDatabase(); System.out.println("数据库创建成功"); } }复制代码 Android sqlite3数据库管理工具 Android SDK的tools目录下提供了一个sqlite3.exe工具,这是一个简单的sqlite数据库管理工具。开发者可以方便的使用其对sqlite数据库进行命令行的操作。 程序运行生成的.db文件一般位于"/data/data/项目名(包括所处包名)/databases/.db",因此要对数据库文件进行操作需要先找到数据库文件: 1、进入shell 命令 adb shell2、找到数据库文件 cd data/data ls --列出所有项目 cd project_name --进入所需项目名 cd databases ls --列出现寸的数据库文件 3、进入数据库 sqlite3 test_db --进入所需数据库 会出现类似如下字样: SQLite version 3.6.22Enter ".help" for instructionsEnter SQL statements terminated with a ";"sqlite>至此,可对数据库进行sql操作。 4、sqlite常用命令 .databases --产看当前数据库.tables --查看当前数据库中的表.help --sqlite3帮助.schema --各个表的生成语句 原文地址https://www.cnblogs.com/ITtangtang/p/3920916.html

auto_answer 2019-12-02 01:50:21 0 浏览量 回答数 0

问题

图解!24张图彻底弄懂九大常见数据结构! 7月22日 【今日算法】

游客ih62co2qqq5ww 2020-07-27 13:19:32 6 浏览量 回答数 1

问题

HBase数据模型解析和基本的表设计分析

pandacats 2019-12-20 21:05:54 0 浏览量 回答数 0

问题

图解九大数据结构 6月13日 【今日算法】

游客ih62co2qqq5ww 2020-06-17 13:17:00 29 浏览量 回答数 1

回答

微服务 (MicroServices) 架构是当前互联网业界的一个技术热点,圈里有不少同行朋友当前有计划在各自公司开展微服务化体系建设,他们都有相同的疑问:一个微服务架构有哪些技术关注点 (technical concerns)?需要哪些基础框架或组件来支持微服务架构?这些框架或组件该如何选型?笔者之前在两家大型互联网公司参与和主导过大型服务化体系和框架建设,同时在这块也投入了很多时间去学习和研究,有一些经验和学习心得,可以和大家一起分享。 服务注册、发现、负载均衡和健康检查和单块 (Monolithic) 架构不同,微服务架构是由一系列职责单一的细粒度服务构成的分布式网状结构,服务之间通过轻量机制进行通信,这时候必然引入一个服务注册发现问题,也就是说服务提供方要注册通告服务地址,服务的调用方要能发现目标服务,同时服务提供方一般以集群方式提供服务,也就引入了负载均衡和健康检查问题。根据负载均衡 LB 所在位置的不同,目前主要的服务注册、发现和负载均衡方案有三种: 第一种是集中式 LB 方案,如下图 Fig 1,在服务消费者和服务提供者之间有一个独立的 LB,LB 通常是专门的硬件设备如 F5,或者基于软件如 LVS,HAproxy 等实现。LB 上有所有服务的地址映射表,通常由运维配置注册,当服务消费方调用某个目标服务时,它向 LB 发起请求,由 LB 以某种策略(比如 Round-Robin)做负载均衡后将请求转发到目标服务。LB 一般具备健康检查能力,能自动摘除不健康的服务实例。服务消费方如何发现 LB 呢?通常的做法是通过 DNS,运维人员为服务配置一个 DNS 域名,这个域名指向 LB。 Fig 1, 集中式 LB 方案 集中式 LB 方案实现简单,在 LB 上也容易做集中式的访问控制,这一方案目前还是业界主流。集中式 LB 的主要问题是单点问题,所有服务调用流量都经过 LB,当服务数量和调用量大的时候,LB 容易成为瓶颈,且一旦 LB 发生故障对整个系统的影响是灾难性的。另外,LB 在服务消费方和服务提供方之间增加了一跳 (hop),有一定性能开销。 第二种是进程内 LB 方案,针对集中式 LB 的不足,进程内 LB 方案将 LB 的功能以库的形式集成到服务消费方进程里头,该方案也被称为软负载 (Soft Load Balancing) 或者客户端负载方案,下图 Fig 2 展示了这种方案的工作原理。这一方案需要一个服务注册表 (Service Registry) 配合支持服务自注册和自发现,服务提供方启动时,首先将服务地址注册到服务注册表(同时定期报心跳到服务注册表以表明服务的存活状态,相当于健康检查),服务消费方要访问某个服务时,它通过内置的 LB 组件向服务注册表查询(同时缓存并定期刷新)目标服务地址列表,然后以某种负载均衡策略选择一个目标服务地址,最后向目标服务发起请求。这一方案对服务注册表的可用性 (Availability) 要求很高,一般采用能满足高可用分布式一致的组件(例如 Zookeeper, Consul, Etcd 等)来实现。 Fig 2, 进程内 LB 方案 进程内 LB 方案是一种分布式方案,LB 和服务发现能力被分散到每一个服务消费者的进程内部,同时服务消费方和服务提供方之间是直接调用,没有额外开销,性能比较好。但是,该方案以客户库 (Client Library) 的方式集成到服务调用方进程里头,如果企业内有多种不同的语言栈,就要配合开发多种不同的客户端,有一定的研发和维护成本。另外,一旦客户端跟随服务调用方发布到生产环境中,后续如果要对客户库进行升级,势必要求服务调用方修改代码并重新发布,所以该方案的升级推广有不小的阻力。 进程内 LB 的案例是 Netflix 的开源服务框架,对应的组件分别是:Eureka 服务注册表,Karyon 服务端框架支持服务自注册和健康检查,Ribbon 客户端框架支持服务自发现和软路由。另外,阿里开源的服务框架 Dubbo 也是采用类似机制。 第三种是主机独立 LB 进程方案,该方案是针对第二种方案的不足而提出的一种折中方案,原理和第二种方案基本类似,不同之处是,他将 LB 和服务发现功能从进程内移出来,变成主机上的一个独立进程,主机上的一个或者多个服务要访问目标服务时,他们都通过同一主机上的独立 LB 进程做服务发现和负载均衡,见下图 Fig 3。 Fig 3 主机独立 LB 进程方案 该方案也是一种分布式方案,没有单点问题,一个 LB 进程挂了只影响该主机上的服务调用方,服务调用方和 LB 之间是进程内调用,性能好,同时,该方案还简化了服务调用方,不需要为不同语言开发客户库,LB 的升级不需要服务调用方改代码。该方案的不足是部署较复杂,环节多,出错调试排查问题不方便。 该方案的典型案例是 Airbnb 的 SmartStack 服务发现框架,对应组件分别是:Zookeeper 作为服务注册表,Nerve 独立进程负责服务注册和健康检查,Synapse/HAproxy 独立进程负责服务发现和负载均衡。Google 最新推出的基于容器的 PaaS 平台 Kubernetes,其内部服务发现采用类似的机制。 服务前端路由微服务除了内部相互之间调用和通信之外,最终要以某种方式暴露出去,才能让外界系统(例如客户的浏览器、移动设备等等)访问到,这就涉及服务的前端路由,对应的组件是服务网关 (Service Gateway),见图 Fig 4,网关是连接企业内部和外部系统的一道门,有如下关键作用: 服务反向路由,网关要负责将外部请求反向路由到内部具体的微服务,这样虽然企业内部是复杂的分布式微服务结构,但是外部系统从网关上看到的就像是一个统一的完整服务,网关屏蔽了后台服务的复杂性,同时也屏蔽了后台服务的升级和变化。安全认证和防爬虫,所有外部请求必须经过网关,网关可以集中对访问进行安全控制,比如用户认证和授权,同时还可以分析访问模式实现防爬虫功能,网关是连接企业内外系统的安全之门。限流和容错,在流量高峰期,网关可以限制流量,保护后台系统不被大流量冲垮,在内部系统出现故障时,网关可以集中做容错,保持外部良好的用户体验。监控,网关可以集中监控访问量,调用延迟,错误计数和访问模式,为后端的性能优化或者扩容提供数据支持。日志,网关可以收集所有的访问日志,进入后台系统做进一步分析。 Fig 4, 服务网关 除以上基本能力外,网关还可以实现线上引流,线上压测,线上调试 (Surgical debugging),金丝雀测试 (Canary Testing),数据中心双活 (Active-Active HA) 等高级功能。 网关通常工作在 7 层,有一定的计算逻辑,一般以集群方式部署,前置 LB 进行负载均衡。 开源的网关组件有 Netflix 的 Zuul,特点是动态可热部署的过滤器 (filter) 机制,其它如 HAproxy,Nginx 等都可以扩展作为网关使用。 在介绍过服务注册表和网关等组件之后,我们可以通过一个简化的微服务架构图 (Fig 5) 来更加直观地展示整个微服务体系内的服务注册发现和路由机制,该图假定采用进程内 LB 服务发现和负载均衡机制。在下图 Fig 5 的微服务架构中,服务简化为两层,后端通用服务(也称中间层服务 Middle Tier Service)和前端服务(也称边缘服务 Edge Service,前端服务的作用是对后端服务做必要的聚合和裁剪后暴露给外部不同的设备,如 PC,Pad 或者 Phone)。后端服务启动时会将地址信息注册到服务注册表,前端服务通过查询服务注册表就可以发现然后调用后端服务;前端服务启动时也会将地址信息注册到服务注册表,这样网关通过查询服务注册表就可以将请求路由到目标前端服务,这样整个微服务体系的服务自注册自发现和软路由就通过服务注册表和网关串联起来了。如果以面向对象设计模式的视角来看,网关类似 Proxy 代理或者 Façade 门面模式,而服务注册表和服务自注册自发现类似 IoC 依赖注入模式,微服务可以理解为基于网关代理和注册表 IoC 构建的分布式系统。 Fig 5, 简化的微服务架构图 服务容错当企业微服务化以后,服务之间会有错综复杂的依赖关系,例如,一个前端请求一般会依赖于多个后端服务,技术上称为 1 -> N 扇出 (见图 Fig 6)。在实际生产环境中,服务往往不是百分百可靠,服务可能会出错或者产生延迟,如果一个应用不能对其依赖的故障进行容错和隔离,那么该应用本身就处在被拖垮的风险中。在一个高流量的网站中,某个单一后端一旦发生延迟,可能在数秒内导致所有应用资源 (线程,队列等) 被耗尽,造成所谓的雪崩效应 (Cascading Failure,见图 Fig 7),严重时可致整个网站瘫痪。 Fig 6, 服务依赖 Fig 7, 高峰期单个服务延迟致雪崩效应 经过多年的探索和实践,业界在分布式服务容错一块探索出了一套有效的容错模式和最佳实践,主要包括: Fig 8, 弹性电路保护状态图 电路熔断器模式 (Circuit Breaker Patten), 该模式的原理类似于家里的电路熔断器,如果家里的电路发生短路,熔断器能够主动熔断电路,以避免灾难性损失。在分布式系统中应用电路熔断器模式后,当目标服务慢或者大量超时,调用方能够主动熔断,以防止服务被进一步拖垮;如果情况又好转了,电路又能自动恢复,这就是所谓的弹性容错,系统有自恢复能力。下图 Fig 8 是一个典型的具备弹性恢复能力的电路保护器状态图,正常状态下,电路处于关闭状态 (Closed),如果调用持续出错或者超时,电路被打开进入熔断状态 (Open),后续一段时间内的所有调用都会被拒绝 (Fail Fast),一段时间以后,保护器会尝试进入半熔断状态 (Half-Open),允许少量请求进来尝试,如果调用仍然失败,则回到熔断状态,如果调用成功,则回到电路闭合状态。舱壁隔离模式 (Bulkhead Isolation Pattern),顾名思义,该模式像舱壁一样对资源或失败单元进行隔离,如果一个船舱破了进水,只损失一个船舱,其它船舱可以不受影响 。线程隔离 (Thread Isolation) 就是舱壁隔离模式的一个例子,假定一个应用程序 A 调用了 Svc1/Svc2/Svc3 三个服务,且部署 A 的容器一共有 120 个工作线程,采用线程隔离机制,可以给对 Svc1/Svc2/Svc3 的调用各分配 40 个线程,当 Svc2 慢了,给 Svc2 分配的 40 个线程因慢而阻塞并最终耗尽,线程隔离可以保证给 Svc1/Svc3 分配的 80 个线程可以不受影响,如果没有这种隔离机制,当 Svc2 慢的时候,120 个工作线程会很快全部被对 Svc2 的调用吃光,整个应用程序会全部慢下来。限流 (Rate Limiting/Load Shedder),服务总有容量限制,没有限流机制的服务很容易在突发流量 (秒杀,双十一) 时被冲垮。限流通常指对服务限定并发访问量,比如单位时间只允许 100 个并发调用,对超过这个限制的请求要拒绝并回退。回退 (fallback),在熔断或者限流发生的时候,应用程序的后续处理逻辑是什么?回退是系统的弹性恢复能力,常见的处理策略有,直接抛出异常,也称快速失败 (Fail Fast),也可以返回空值或缺省值,还可以返回备份数据,如果主服务熔断了,可以从备份服务获取数据。Netflix 将上述容错模式和最佳实践集成到一个称为 Hystrix 的开源组件中,凡是需要容错的依赖点 (服务,缓存,数据库访问等),开发人员只需要将调用封装在 Hystrix Command 里头,则相关调用就自动置于 Hystrix 的弹性容错保护之下。Hystrix 组件已经在 Netflix 经过多年运维验证,是 Netflix 微服务平台稳定性和弹性的基石,正逐渐被社区接受为标准容错组件。 服务框架微服务化以后,为了让业务开发人员专注于业务逻辑实现,避免冗余和重复劳动,规范研发提升效率,必然要将一些公共关注点推到框架层面。服务框架 (Fig 9) 主要封装公共关注点逻辑,包括: Fig 9, 服务框架 服务注册、发现、负载均衡和健康检查,假定采用进程内 LB 方案,那么服务自注册一般统一做在服务器端框架中,健康检查逻辑由具体业务服务定制,框架层提供调用健康检查逻辑的机制,服务发现和负载均衡则集成在服务客户端框架中。监控日志,框架一方面要记录重要的框架层日志、metrics 和调用链数据,还要将日志、metrics 等接口暴露出来,让业务层能根据需要记录业务日志数据。在运行环境中,所有日志数据一般集中落地到企业后台日志系统,做进一步分析和处理。REST/RPC 和序列化,框架层要支持将业务逻辑以 HTTP/REST 或者 RPC 方式暴露出来,HTTP/REST 是当前主流 API 暴露方式,在性能要求高的场合则可采用 Binary/RPC 方式。针对当前多样化的设备类型 (浏览器、普通 PC、无线设备等),框架层要支持可定制的序列化机制,例如,对浏览器,框架支持输出 Ajax 友好的 JSON 消息格式,而对无线设备上的 Native App,框架支持输出性能高的 Binary 消息格式。配置,除了支持普通配置文件方式的配置,框架层还可集成动态运行时配置,能够在运行时针对不同环境动态调整服务的参数和配置。限流和容错,框架集成限流容错组件,能够在运行时自动限流和容错,保护服务,如果进一步和动态配置相结合,还可以实现动态限流和熔断。管理接口,框架集成管理接口,一方面可以在线查看框架和服务内部状态,同时还可以动态调整内部状态,对调试、监控和管理能提供快速反馈。Spring Boot 微框架的 Actuator 模块就是一个强大的管理接口。统一错误处理,对于框架层和服务的内部异常,如果框架层能够统一处理并记录日志,对服务监控和快速问题定位有很大帮助。安全,安全和访问控制逻辑可以在框架层统一进行封装,可做成插件形式,具体业务服务根据需要加载相关安全插件。文档自动生成,文档的书写和同步一直是一个痛点,框架层如果能支持文档的自动生成和同步,会给使用 API 的开发和测试人员带来极大便利。Swagger 是一种流行 Restful API 的文档方案。当前业界比较成熟的微服务框架有 Netflix 的 Karyon/Ribbon,Spring 的 Spring Boot/Cloud,阿里的 Dubbo 等。 运行期配置管理服务一般有很多依赖配置,例如访问数据库有连接字符串配置,连接池大小和连接超时配置,这些配置在不同环境 (开发 / 测试 / 生产) 一般不同,比如生产环境需要配连接池,而开发测试环境可能不配,另外有些参数配置在运行期可能还要动态调整,例如,运行时根据流量状况动态调整限流和熔断阀值。目前比较常见的做法是搭建一个运行时配置中心支持微服务的动态配置,简化架构如下图 (Fig 10): Fig 10, 服务配置中心 动态配置存放在集中的配置服务器上,用户通过管理界面配置和调整服务配置,具体服务通过定期拉 (Scheduled Pull) 的方式或者服务器推 (Server-side Push) 的方式更新动态配置,拉方式比较可靠,但会有延迟同时有无效网络开销 (假设配置不常更新),服务器推方式能及时更新配置,但是实现较复杂,一般在服务和配置服务器之间要建立长连接。配置中心还要解决配置的版本控制和审计问题,对于大规模服务化环境,配置中心还要考虑分布式和高可用问题。 配置中心比较成熟的开源方案有百度的 Disconf,360 的 QConf,Spring 的 Cloud Config 和阿里的 Diamond 等。 Netflix 的微服务框架Netflix 是一家成功实践微服务架构的互联网公司,几年前,Netflix 就把它的几乎整个微服务框架栈开源贡献给了社区,这些框架和组件包括: Eureka: 服务注册发现框架Zuul: 服务网关Karyon: 服务端框架Ribbon: 客户端框架Hystrix: 服务容错组件Archaius: 服务配置组件Servo: Metrics 组件Blitz4j: 日志组件下图 Fig 11 展示了基于这些组件构建的一个微服务框架体系,来自 recipes-rss。 Fig 11, 基于 Netflix 开源组件的微服务框架 Netflix 的开源框架组件已经在 Netflix 的大规模分布式微服务环境中经过多年的生产实战验证,正逐步被社区接受为构造微服务框架的标准组件。Pivotal 去年推出的 Spring Cloud 开源产品,主要是基于对 Netflix 开源组件的进一步封装,方便 Spring 开发人员构建微服务基础框架。对于一些打算构建微服务框架体系的公司来说,充分利用或参考借鉴 Netflix 的开源微服务组件 (或 Spring Cloud),在此基础上进行必要的企业定制,无疑是通向微服务架构的捷径。 原文地址:https://www.infoq.cn/article/basis-frameworkto-implement-micro-service#anch130564%20%EF%BC%8C

auto_answer 2019-12-02 01:55:22 0 浏览量 回答数 0

回答

遍历一个 List 有哪些不同的方式?每种方法的实现原理是什么?Java 中 List 遍历的最佳实践是什么? 遍历方式有以下几种: for 循环遍历,基于计数器。在集合外部维护一个计数器,然后依次读取每一个位置的元素,当读取到最后一个元素后停止。 迭代器遍历,Iterator。Iterator 是面向对象的一个设计模式,目的是屏蔽不同数据集合的特点,统一遍历集合的接口。Java 在 Collections 中支持了 Iterator 模式。 foreach 循环遍历。foreach 内部也是采用了 Iterator 的方式实现,使用时不需要显式声明 Iterator 或计数器。优点是代码简洁,不易出错;缺点是只能做简单的遍历,不能在遍历过程中操作数据集合,例如删除、替换。 最佳实践:Java Collections 框架中提供了一个 RandomAccess 接口,用来标记 List 实现是否支持 Random Access。 如果一个数据集合实现了该接口,就意味着它支持 Random Access,按位置读取元素的平均时间复杂度为 O(1),如ArrayList。如果没有实现该接口,表示不支持 Random Access,如LinkedList。 推荐的做法就是,支持 Random Access 的列表可用 for 循环遍历,否则建议用 Iterator 或 foreach 遍历。 说一下 ArrayList 的优缺点 ArrayList的优点如下: ArrayList 底层以数组实现,是一种随机访问模式。ArrayList 实现了 RandomAccess 接口,因此查找的时候非常快。ArrayList 在顺序添加一个元素的时候非常方便。 ArrayList 的缺点如下: 删除元素的时候,需要做一次元素复制操作。如果要复制的元素很多,那么就会比较耗费性能。插入元素的时候,也需要做一次元素复制操作,缺点同上。 ArrayList 比较适合顺序添加、随机访问的场景。 如何实现数组和 List 之间的转换? 数组转 List:使用 Arrays. asList(array) 进行转换。List 转数组:使用 List 自带的 toArray() 方法。 代码示例: ArrayList 和 LinkedList 的区别是什么? 数据结构实现:ArrayList 是动态数组的数据结构实现,而 LinkedList 是双向链表的数据结构实现。随机访问效率:ArrayList 比 LinkedList 在随机访问的时候效率要高,因为 LinkedList 是线性的数据存储方式,所以需要移动指针从前往后依次查找。增加和删除效率:在非首尾的增加和删除操作,LinkedList 要比 ArrayList 效率要高,因为 ArrayList 增删操作要影响数组内的其他数据的下标。内存空间占用:LinkedList 比 ArrayList 更占内存,因为 LinkedList 的节点除了存储数据,还存储了两个引用,一个指向前一个元素,一个指向后一个元素。线程安全:ArrayList 和 LinkedList 都是不同步的,也就是不保证线程安全; 综合来说,在需要频繁读取集合中的元素时,更推荐使用 ArrayList,而在插入和删除操作较多时,更推荐使用 LinkedList。 补充:数据结构基础之双向链表 双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱。所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。 ArrayList 和 Vector 的区别是什么? 这两个类都实现了 List 接口(List 接口继承了 Collection 接口),他们都是有序集合 线程安全:Vector 使用了 Synchronized 来实现线程同步,是线程安全的,而 ArrayList 是非线程安全的。性能:ArrayList 在性能方面要优于 Vector。扩容:ArrayList 和 Vector 都会根据实际的需要动态的调整容量,只不过在 Vector 扩容每次会增加 1 倍,而 ArrayList 只会增加 50%。 Vector类的所有方法都是同步的。可以由两个线程安全地访问一个Vector对象、但是一个线程访问Vector的话代码要在同步操作上耗费大量的时间。 Arraylist不是同步的,所以在不需要保证线程安全时时建议使用Arraylist。 插入数据时,ArrayList、LinkedList、Vector谁速度较快?阐述 ArrayList、Vector、LinkedList 的存储性能和特性? ArrayList、LinkedList、Vector 底层的实现都是使用数组方式存储数据。数组元素数大于实际存储的数据以便增加和插入元素,它们都允许直接按序号索引元素,但是插入元素要涉及数组元素移动等内存操作,所以索引数据快而插入数据慢。 Vector 中的方法由于加了 synchronized 修饰,因此 Vector 是线程安全容器,但性能上较ArrayList差。 LinkedList 使用双向链表实现存储,按序号索引数据需要进行前向或后向遍历,但插入数据时只需要记录当前项的前后项即可,所以 LinkedList 插入速度较快。 多线程场景下如何使用 ArrayList? ArrayList 不是线程安全的,如果遇到多线程场景,可以通过 Collections 的 synchronizedList 方法将其转换成线程安全的容器后再使用。例如像下面这样: 为什么 ArrayList 的 elementData 加上 transient 修饰? ArrayList 中的数组定义如下: private transient Object[] elementData; 再看一下 ArrayList 的定义: public class ArrayList extends AbstractList implements List<E>, RandomAccess, Cloneable, java.io.Serializable 可以看到 ArrayList 实现了 Serializable 接口,这意味着 ArrayList 支持序列化。transient 的作用是说不希望 elementData 数组被序列化,重写了 writeObject 实现: 每次序列化时,先调用 defaultWriteObject() 方法序列化 ArrayList 中的非 transient 元素,然后遍历 elementData,只序列化已存入的元素,这样既加快了序列化的速度,又减小了序列化之后的文件大小。 List 和 Set 的区别 List , Set 都是继承自Collection 接口 List 特点:一个有序(元素存入集合的顺序和取出的顺序一致)容器,元素可以重复,可以插入多个null元素,元素都有索引。常用的实现类有 ArrayList、LinkedList 和 Vector。 Set 特点:一个无序(存入和取出顺序有可能不一致)容器,不可以存储重复元素,只允许存入一个null元素,必须保证元素唯一性。Set 接口常用实现类是 HashSet、LinkedHashSet 以及 TreeSet。 另外 List 支持for循环,也就是通过下标来遍历,也可以用迭代器,但是set只能用迭代,因为他无序,无法用下标来取得想要的值。 Set和List对比 Set:检索元素效率低下,删除和插入效率高,插入和删除不会引起元素位置改变。 List:和数组类似,List可以动态增长,查找元素效率高,插入删除元素效率低,因为会引起其他元素位置改变 Set接口 说一下 HashSet 的实现原理? HashSet 是基于 HashMap 实现的,HashSet的值存放于HashMap的key上,HashMap的value统一为PRESENT,因此 HashSet 的实现比较简单,相关 HashSet 的操作,基本上都是直接调用底层 HashMap 的相关方法来完成,HashSet 不允许重复的值。 HashSet如何检查重复?HashSet是如何保证数据不可重复的? 向HashSet 中add ()元素时,判断元素是否存在的依据,不仅要比较hash值,同时还要结合equles 方法比较。 HashSet 中的add ()方法会使用HashMap 的put()方法。 HashMap 的 key 是唯一的,由源码可以看出 HashSet 添加进去的值就是作为HashMap 的key,并且在HashMap中如果K/V相同时,会用新的V覆盖掉旧的V,然后返回旧的V。所以不会重复( HashMap 比较key是否相等是先比较hashcode 再比较equals )。 以下是HashSet 部分源码: hashCode()与equals()的相关规定: 如果两个对象相等,则hashcode一定也是相同的 两个对象相等,对两个equals方法返回true 两个对象有相同的hashcode值,它们也不一定是相等的 综上,equals方法被覆盖过,则hashCode方法也必须被覆盖 hashCode()的默认行为是对堆上的对象产生独特值。如果没有重写hashCode(),则该class的两个对象无论如何都不会相等(即使这两个对象指向相同的数据)。 ** ==与equals的区别** ==是判断两个变量或实例是不是指向同一个内存空间 equals是判断两个变量或实例所指向的内存空间的值是不是相同 ==是指对内存地址进行比较 equals()是对字符串的内容进行比较3.==指引用是否相同 equals()指的是值是否相同 HashSet与HashMap的区别 Queue BlockingQueue是什么? Java.util.concurrent.BlockingQueue是一个队列,在进行检索或移除一个元素的时候,它会等待队列变为非空;当在添加一个元素时,它会等待队列中的可用空间。BlockingQueue接口是Java集合框架的一部分,主要用于实现生产者-消费者模式。我们不需要担心等待生产者有可用的空间,或消费者有可用的对象,因为它都在BlockingQueue的实现类中被处理了。Java提供了集中BlockingQueue的实现,比如ArrayBlockingQueue、LinkedBlockingQueue、PriorityBlockingQueue,、SynchronousQueue等。 在 Queue 中 poll()和 remove()有什么区别? 相同点:都是返回第一个元素,并在队列中删除返回的对象。 不同点:如果没有元素 poll()会返回 null,而 remove()会直接抛出 NoSuchElementException 异常。 代码示例: Queue queue = new LinkedList (); queue. offer("string"); // add System. out. println(queue. poll()); System. out. println(queue. remove()); System. out. println(queue. size()); Map接口 说一下 HashMap 的实现原理? HashMap概述: HashMap是基于哈希表的Map接口的非同步实现。此实现提供所有可选的映射操作,并允许使用null值和null键。此类不保证映射的顺序,特别是它不保证该顺序恒久不变。 HashMap的数据结构: 在Java编程语言中,最基本的结构就是两种,一个是数组,另外一个是模拟指针(引用),所有的数据结构都可以用这两个基本结构来构造的,HashMap也不例外。HashMap实际上是一个“链表散列”的数据结构,即数组和链表的结合体。 HashMap 基于 Hash 算法实现的 当我们往Hashmap中put元素时,利用key的hashCode重新hash计算出当前对象的元素在数组中的下标存储时,如果出现hash值相同的key,此时有两种情况。(1)如果key相同,则覆盖原始值;(2)如果key不同(出现冲突),则将当前的key-value放入链表中获取时,直接找到hash值对应的下标,在进一步判断key是否相同,从而找到对应值。理解了以上过程就不难明白HashMap是如何解决hash冲突的问题,核心就是使用了数组的存储方式,然后将冲突的key的对象放入链表中,一旦发现冲突就在链表中做进一步的对比。 需要注意Jdk 1.8中对HashMap的实现做了优化,当链表中的节点数据超过八个之后,该链表会转为红黑树来提高查询效率,从原来的O(n)到O(logn) HashMap在JDK1.7和JDK1.8中有哪些不同?HashMap的底层实现 在Java中,保存数据有两种比较简单的数据结构:数组和链表。数组的特点是:寻址容易,插入和删除困难;链表的特点是:寻址困难,但插入和删除容易;所以我们将数组和链表结合在一起,发挥两者各自的优势,使用一种叫做拉链法的方式可以解决哈希冲突。 JDK1.8之前 JDK1.8之前采用的是拉链法。拉链法:将链表和数组相结合。也就是说创建一个链表数组,数组中每一格就是一个链表。若遇到哈希冲突,则将冲突的值加到链表中即可。 JDK1.8之后 相比于之前的版本,jdk1.8在解决哈希冲突时有了较大的变化,当链表长度大于阈值(默认为8)时,将链表转化为红黑树,以减少搜索时间。 JDK1.7 VS JDK1.8 比较 JDK1.8主要解决或优化了一下问题: resize 扩容优化引入了红黑树,目的是避免单条链表过长而影响查询效率,红黑树算法请参考解决了多线程死循环问题,但仍是非线程安全的,多线程时可能会造成数据丢失问题。 HashMap的put方法的具体流程? 当我们put的时候,首先计算 key的hash值,这里调用了 hash方法,hash方法实际是让key.hashCode()与key.hashCode()>>>16进行异或操作,高16bit补0,一个数和0异或不变,所以 hash 函数大概的作用就是:高16bit不变,低16bit和高16bit做了一个异或,目的是减少碰撞。按照函数注释,因为bucket数组大小是2的幂,计算下标index = (table.length - 1) & hash,如果不做 hash 处理,相当于散列生效的只有几个低 bit 位,为了减少散列的碰撞,设计者综合考虑了速度、作用、质量之后,使用高16bit和低16bit异或来简单处理减少碰撞,而且JDK8中用了复杂度 O(logn)的树结构来提升碰撞下的性能。 putVal方法执行流程图 ①.判断键值对数组table[i]是否为空或为null,否则执行resize()进行扩容; ②.根据键值key计算hash值得到插入的数组索引i,如果table[i]==null,直接新建节点添加,转向⑥,如果table[i]不为空,转向③; ③.判断table[i]的首个元素是否和key一样,如果相同直接覆盖value,否则转向④,这里的相同指的是hashCode以及equals; ④.判断table[i] 是否为treeNode,即table[i] 是否是红黑树,如果是红黑树,则直接在树中插入键值对,否则转向⑤; ⑤.遍历table[i],判断链表长度是否大于8,大于8的话把链表转换为红黑树,在红黑树中执行插入操作,否则进行链表的插入操作;遍历过程中若发现key已经存在直接覆盖value即可; ⑥.插入成功后,判断实际存在的键值对数量size是否超多了最大容量threshold,如果超过,进行扩容。 HashMap的扩容操作是怎么实现的? ①.在jdk1.8中,resize方法是在hashmap中的键值对大于阀值时或者初始化时,就调用resize方法进行扩容; ②.每次扩展的时候,都是扩展2倍; ③.扩展后Node对象的位置要么在原位置,要么移动到原偏移量两倍的位置。 在putVal()中,我们看到在这个函数里面使用到了2次resize()方法,resize()方法表示的在进行第一次初始化时会对其进行扩容,或者当该数组的实际大小大于其临界值值(第一次为12),这个时候在扩容的同时也会伴随的桶上面的元素进行重新分发,这也是JDK1.8版本的一个优化的地方,在1.7中,扩容之后需要重新去计算其Hash值,根据Hash值对其进行分发,但在1.8版本中,则是根据在同一个桶的位置中进行判断(e.hash & oldCap)是否为0,重新进行hash分配后,该元素的位置要么停留在原始位置,要么移动到原始位置+增加的数组大小这个位置上 HashMap是怎么解决哈希冲突的? 答:在解决这个问题之前,我们首先需要知道什么是哈希冲突,而在了解哈希冲突之前我们还要知道什么是哈希才行; 什么是哈希? Hash,一般翻译为“散列”,也有直接音译为“哈希”的,这就是把任意长度的输入通过散列算法,变换成固定长度的输出,该输出就是散列值(哈希值);这种转换是一种压缩映射,也就是,散列值的空间通常远小于输入的空间,不同的输入可能会散列成相同的输出,所以不可能从散列值来唯一的确定输入值。简单的说就是一种将任意长度的消息压缩到某一固定长度的消息摘要的函数。 所有散列函数都有如下一个基本特性**:根据同一散列函数计算出的散列值如果不同,那么输入值肯定也不同。但是,根据同一散列函数计算出的散列值如果相同,输入值不一定相同**。 什么是哈希冲突? 当两个不同的输入值,根据同一散列函数计算出相同的散列值的现象,我们就把它叫做碰撞(哈希碰撞)。 HashMap的数据结构 在Java中,保存数据有两种比较简单的数据结构:数组和链表。数组的特点是:寻址容易,插入和删除困难;链表的特点是:寻址困难,但插入和删除容易;所以我们将数组和链表结合在一起,发挥两者各自的优势,使用一种叫做链地址法的方式可以解决哈希冲突: 这样我们就可以将拥有相同哈希值的对象组织成一个链表放在hash值所对应的bucket下,但相比于hashCode返回的int类型,我们HashMap初始的容量大小DEFAULT_INITIAL_CAPACITY = 1 << 4(即2的四次方16)要远小于int类型的范围,所以我们如果只是单纯的用hashCode取余来获取对应的bucket这将会大大增加哈希碰撞的概率,并且最坏情况下还会将HashMap变成一个单链表,所以我们还需要对hashCode作一定的优化 hash()函数 上面提到的问题,主要是因为如果使用hashCode取余,那么相当于参与运算的只有hashCode的低位,高位是没有起到任何作用的,所以我们的思路就是让hashCode取值出的高位也参与运算,进一步降低hash碰撞的概率,使得数据分布更平均,我们把这样的操作称为扰动,在JDK 1.8中的hash()函数如下: static final int hash(Object key) { int h; return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);// 与自己右移16位进行异或运算(高低位异或) } 这比在JDK 1.7中,更为简洁,相比在1.7中的4次位运算,5次异或运算(9次扰动),在1.8中,只进行了1次位运算和1次异或运算(2次扰动); JDK1.8新增红黑树 通过上面的链地址法(使用散列表)和扰动函数我们成功让我们的数据分布更平均,哈希碰撞减少,但是当我们的HashMap中存在大量数据时,加入我们某个bucket下对应的链表有n个元素,那么遍历时间复杂度就为O(n),为了针对这个问题,JDK1.8在HashMap中新增了红黑树的数据结构,进一步使得遍历复杂度降低至O(logn); 总结 简单总结一下HashMap是使用了哪些方法来有效解决哈希冲突的: 使用链地址法(使用散列表)来链接拥有相同hash值的数据;使用2次扰动函数(hash函数)来降低哈希冲突的概率,使得数据分布更平均;引入红黑树进一步降低遍历的时间复杂度,使得遍历更快; **能否使用任何类作为 Map 的 key? **可以使用任何类作为 Map 的 key,然而在使用之前,需要考虑以下几点: 如果类重写了 equals() 方法,也应该重写 hashCode() 方法。 类的所有实例需要遵循与 equals() 和 hashCode() 相关的规则。 如果一个类没有使用 equals(),不应该在 hashCode() 中使用它。 用户自定义 Key 类最佳实践是使之为不可变的,这样 hashCode() 值可以被缓存起来,拥有更好的性能。不可变的类也可以确保 hashCode() 和 equals() 在未来不会改变,这样就会解决与可变相关的问题了。 为什么HashMap中String、Integer这样的包装类适合作为K? 答:String、Integer等包装类的特性能够保证Hash值的不可更改性和计算准确性,能够有效的减少Hash碰撞的几率 都是final类型,即不可变性,保证key的不可更改性,不会存在获取hash值不同的情况 内部已重写了equals()、hashCode()等方法,遵守了HashMap内部的规范(不清楚可以去上面看看putValue的过程),不容易出现Hash值计算错误的情况; 如果使用Object作为HashMap的Key,应该怎么办呢? 答:重写hashCode()和equals()方法 重写hashCode()是因为需要计算存储数据的存储位置,需要注意不要试图从散列码计算中排除掉一个对象的关键部分来提高性能,这样虽然能更快但可能会导致更多的Hash碰撞; 重写equals()方法,需要遵守自反性、对称性、传递性、一致性以及对于任何非null的引用值x,x.equals(null)必须返回false的这几个特性,目的是为了保证key在哈希表中的唯一性; HashMap为什么不直接使用hashCode()处理后的哈希值直接作为table的下标 答:hashCode()方法返回的是int整数类型,其范围为-(2 ^ 31)~(2 ^ 31 - 1),约有40亿个映射空间,而HashMap的容量范围是在16(初始化默认值)~2 ^ 30,HashMap通常情况下是取不到最大值的,并且设备上也难以提供这么多的存储空间,从而导致通过hashCode()计算出的哈希值可能不在数组大小范围内,进而无法匹配存储位置; 那怎么解决呢? HashMap自己实现了自己的hash()方法,通过两次扰动使得它自己的哈希值高低位自行进行异或运算,降低哈希碰撞概率也使得数据分布更平均; 在保证数组长度为2的幂次方的时候,使用hash()运算之后的值与运算(&)(数组长度 - 1)来获取数组下标的方式进行存储,这样一来是比取余操作更加有效率,二来也是因为只有当数组长度为2的幂次方时,h&(length-1)才等价于h%length,三来解决了“哈希值与数组大小范围不匹配”的问题; HashMap 的长度为什么是2的幂次方 为了能让 HashMap 存取高效,尽量较少碰撞,也就是要尽量把数据分配均匀,每个链表/红黑树长度大致相同。这个实现就是把数据存到哪个链表/红黑树中的算法。 这个算法应该如何设计呢? 我们首先可能会想到采用%取余的操作来实现。但是,重点来了:“取余(%)操作中如果除数是2的幂次则等价于与其除数减一的与(&)操作(也就是说 hash%length==hash&(length-1)的前提是 length 是2的 n 次方;)。” 并且 采用二进制位操作 &,相对于%能够提高运算效率,这就解释了 HashMap 的长度为什么是2的幂次方。 那为什么是两次扰动呢? 答:这样就是加大哈希值低位的随机性,使得分布更均匀,从而提高对应数组存储下标位置的随机性&均匀性,最终减少Hash冲突,两次就够了,已经达到了高位低位同时参与运算的目的; HashMap 与 HashTable 有什么区别? 线程安全: HashMap 是非线程安全的,HashTable 是线程安全的;HashTable 内部的方法基本都经过 synchronized 修饰。(如果你要保证线程安全的话就使用 ConcurrentHashMap 吧!); 效率: 因为线程安全的问题,HashMap 要比 HashTable 效率高一点。另外,HashTable 基本被淘汰,不要在代码中使用它; 对Null key 和Null value的支持: HashMap 中,null 可以作为键,这样的键只有一个,可以有一个或多个键所对应的值为 null。但是在 HashTable 中 put 进的键值只要有一个 null,直接抛NullPointerException。 **初始容量大小和每次扩充容量大小的不同 **: ①创建时如果不指定容量初始值,Hashtable 默认的初始大小为11,之后每次扩充,容量变为原来的2n+1。HashMap 默认的初始化大小为16。之后每次扩充,容量变为原来的2倍。②创建时如果给定了容量初始值,那么 Hashtable 会直接使用你给定的大小,而 HashMap 会将其扩充为2的幂次方大小。也就是说 HashMap 总是使用2的幂作为哈希表的大小,后面会介绍到为什么是2的幂次方。 底层数据结构: JDK1.8 以后的 HashMap 在解决哈希冲突时有了较大的变化,当链表长度大于阈值(默认为8)时,将链表转化为红黑树,以减少搜索时间。Hashtable 没有这样的机制。 推荐使用:在 Hashtable 的类注释可以看到,Hashtable 是保留类不建议使用,推荐在单线程环境下使用 HashMap 替代,如果需要多线程使用则用 ConcurrentHashMap 替代。 如何决定使用 HashMap 还是 TreeMap? 对于在Map中插入、删除和定位元素这类操作,HashMap是最好的选择。然而,假如你需要对一个有序的key集合进行遍历,TreeMap是更好的选择。基于你的collection的大小,也许向HashMap中添加元素会更快,将map换为TreeMap进行有序key的遍历。 HashMap 和 ConcurrentHashMap 的区别 ConcurrentHashMap对整个桶数组进行了分割分段(Segment),然后在每一个分段上都用lock锁进行保护,相对于HashTable的synchronized锁的粒度更精细了一些,并发性能更好,而HashMap没有锁机制,不是线程安全的。(JDK1.8之后ConcurrentHashMap启用了一种全新的方式实现,利用CAS算法。) HashMap的键值对允许有null,但是ConCurrentHashMap都不允许。 ConcurrentHashMap 和 Hashtable 的区别? ConcurrentHashMap 和 Hashtable 的区别主要体现在实现线程安全的方式上不同。 底层数据结构: JDK1.7的 ConcurrentHashMap 底层采用 分段的数组+链表 实现,JDK1.8 采用的数据结构跟HashMap1.8的结构一样,数组+链表/红黑二叉树。Hashtable 和 JDK1.8 之前的 HashMap 的底层数据结构类似都是采用 数组+链表 的形式,数组是 HashMap 的主体,链表则是主要为了解决哈希冲突而存在的; 实现线程安全的方式(重要): ① 在JDK1.7的时候,ConcurrentHashMap(分段锁) 对整个桶数组进行了分割分段(Segment),每一把锁只锁容器其中一部分数据,多线程访问容器里不同数据段的数据,就不会存在锁竞争,提高并发访问率。(默认分配16个Segment,比Hashtable效率提高16倍。) 到了 JDK1.8 的时候已经摒弃了Segment的概念,而是直接用 Node 数组+链表+红黑树的数据结构来实现,并发控制使用 synchronized 和 CAS 来操作。(JDK1.6以后 对 synchronized锁做了很多优化) 整个看起来就像是优化过且线程安全的 HashMap,虽然在JDK1.8中还能看到 Segment 的数据结构,但是已经简化了属性,只是为了兼容旧版本;② Hashtable(同一把锁) :使用 synchronized 来保证线程安全,效率非常低下。当一个线程访问同步方法时,其他线程也访问同步方法,可能会进入阻塞或轮询状态,如使用 put 添加元素,另一个线程不能使用 put 添加元素,也不能使用 get,竞争会越来越激烈效率越低。 两者的对比图: HashTable: JDK1.7的ConcurrentHashMap: JDK1.8的ConcurrentHashMap(TreeBin: 红黑二叉树节点 Node: 链表节点): 答:ConcurrentHashMap 结合了 HashMap 和 HashTable 二者的优势。HashMap 没有考虑同步,HashTable 考虑了同步的问题。但是 HashTable 在每次同步执行时都要锁住整个结构。 ConcurrentHashMap 锁的方式是稍微细粒度的。 ConcurrentHashMap 底层具体实现知道吗?实现原理是什么? JDK1.7 首先将数据分为一段一段的存储,然后给每一段数据配一把锁,当一个线程占用锁访问其中一个段数据时,其他段的数据也能被其他线程访问。 在JDK1.7中,ConcurrentHashMap采用Segment + HashEntry的方式进行实现,结构如下: 一个 ConcurrentHashMap 里包含一个 Segment 数组。Segment 的结构和HashMap类似,是一种数组和链表结构,一个 Segment 包含一个 HashEntry 数组,每个 HashEntry 是一个链表结构的元素,每个 Segment 守护着一个HashEntry数组里的元素,当对 HashEntry 数组的数据进行修改时,必须首先获得对应的 Segment的锁。 该类包含两个静态内部类 HashEntry 和 Segment ;前者用来封装映射表的键值对,后者用来充当锁的角色;Segment 是一种可重入的锁 ReentrantLock,每个 Segment 守护一个HashEntry 数组里得元素,当对 HashEntry 数组的数据进行修改时,必须首先获得对应的 Segment 锁。 JDK1.8 在JDK1.8中,放弃了Segment臃肿的设计,取而代之的是采用Node + CAS + Synchronized来保证并发安全进行实现,synchronized只锁定当前链表或红黑二叉树的首节点,这样只要hash不冲突,就不会产生并发,效率又提升N倍。 结构如下: 如果该节点是TreeBin类型的节点,说明是红黑树结构,则通过putTreeVal方法往红黑树中插入节点;如果binCount不为0,说明put操作对数据产生了影响,如果当前链表的个数达到8个,则通过treeifyBin方法转化为红黑树,如果oldVal不为空,说明是一次更新操作,没有对元素个数产生影响,则直接返回旧值;如果插入的是一个新节点,则执行addCount()方法尝试更新元素个数baseCount; 辅助工具类 Array 和 ArrayList 有何区别? Array 可以存储基本数据类型和对象,ArrayList 只能存储对象。Array 是指定固定大小的,而 ArrayList 大小是自动扩展的。Array 内置方法没有 ArrayList 多,比如 addAll、removeAll、iteration 等方法只有 ArrayList 有。 对于基本类型数据,集合使用自动装箱来减少编码工作量。但是,当处理固定大小的基本数据类型的时候,这种方式相对比较慢。 如何实现 Array 和 List 之间的转换? Array 转 List: Arrays. asList(array) ;List 转 Array:List 的 toArray() 方法。 comparable 和 comparator的区别? comparable接口实际上是出自java.lang包,它有一个 compareTo(Object obj)方法用来排序comparator接口实际上是出自 java.util 包,它有一个compare(Object obj1, Object obj2)方法用来排序 一般我们需要对一个集合使用自定义排序时,我们就要重写compareTo方法或compare方法,当我们需要对某一个集合实现两种排序方式,比如一个song对象中的歌名和歌手名分别采用一种排序方法的话,我们可以重写compareTo方法和使用自制的Comparator方法或者以两个Comparator来实现歌名排序和歌星名排序,第二种代表我们只能使用两个参数版的Collections.sort(). 方法如何比较元素? TreeSet 要求存放的对象所属的类必须实现 Comparable 接口,该接口提供了比较元素的 compareTo()方法,当插入元素时会回调该方法比较元素的大小。TreeMap 要求存放的键值对映射的键必须实现 Comparable 接口从而根据键对元素进 行排 序。 Collections 工具类的 sort 方法有两种重载的形式, 第一种要求传入的待排序容器中存放的对象比较实现 Comparable 接口以实现元素的比较; 第二种不强制性的要求容器中的元素必须可比较,但是要求传入第二个参数,参数是Comparator 接口的子类型(需要重写 compare 方法实现元素的比较),相当于一个临时定义的排序规则,其实就是通过接口注入比较元素大小的算法,也是对回调模式的应用(Java 中对函数式编程的支持)。

剑曼红尘 2020-03-24 14:41:57 0 浏览量 回答数 0

回答

估计得请百度的数据,你去百度客服问问看 ------------------------- 究竟怎样做才能不影响网站在谷歌搜索结果中的表现呢?  您希望这种迁移对于用户来说是毫无察觉地发生的,同时希望谷歌知道新页面应该与原网站页面得到相同的质量认可。当您迁移网站时,那些讨厌的404错误提示(无法找到文件) 不仅会伤害用户体验,还会给您的网站在谷歌搜索结果中的表现带来负面影响。  本文将介绍如何稳妥地将您的网站搬到一个新域名(例如从www.example.com变为www.example.org)。这与将网站搬到一个新的IP地址是不同的,如果想了解这方面的内容请阅读此文。  网站迁移的主要步骤如下:  *首先通过移动一个目录或子域名的内容来测试整个网站的迁移过程。然后使用301重定向功能将原有网站网页重定向到您的新网站上。通过此方法可告知谷歌和其它搜索引擎:您的网站已经永久性地迁移了。  *上述操作完成后,查看一下您新网站里的网页能否出现在谷歌的搜索结果里。如果您对这次小范围的迁移感到满意,就可以迁移整个网站了。请不要将旧网站中所有网页的流量都重定向到您的新主页上,这种一刀切式的重定向虽然会避免404错误,但它并不能为用户提供良好的体验。尽管页对页的重定向(旧网站中每一网页都重新定向到新网站的相应网页上)会带来更大的工作量,但这也会给您的用户带来更连贯和明晰的体验。如果在新旧网站中不是一对一的页面匹配,那么一定要努力确保旧网站中每一个网页至少要重定向到具有类似内容的新网页上。  *如果网站因为要重新命名或重新设计而需变更域名,您可以分两个阶段进行:第一阶段,移动您的网站;第二阶段,开始重新设计。这样做,不仅可以掌控用户在每一阶段中感受到的变化幅度,而且可以使整个过程变得更顺利。把变化控制在最低限度可以使您更容易发现和解决各种意外情况。   *检查您网站网页的内、外部链接。理想的情况是您应该联络每个链接到您网站上的其他网站的管理员,让他们把链接指向您新域名的相应网页。如果这难以实现,您要确保原网站中所有含有其他网站链接指向的网页都被重定向到您的新网站上。您也应该检查并更新所有旧网站里的内部链接,使它们指向新域名。当您的网站内容已经在新服务器上准备就绪后,您可以使用一个诸如Xenu的链接检查工具来确认在您的新站点上没有遗留的故障链接。这一点特别重要,如果您的原始内容包含绝对链接(如www.example.com/cooking/recipes/chocolatecake.html )而不是相对链接(如 …/recipes/chocolatecake.html)的话。  *为防止混淆和混乱,您最好继续持有对原网站域名的控制权限至少180天。  *将您的新网站添加到网站管理员工具帐户中,并验证您对该网站的所有权。创建并提交一个Sitemap以显示出新网站的所有URL,这样谷歌就会知道您新网站里的内容现在已经可用,可以对其进行抓取了。 ------------------------- 笔者这里建议网站改版更换域名最好在百度更新之后,一般在周六的时候进行,然后开始记录接下来四天的变化。四天中,老数据仍然存在于百度数据库中,新站的数据还没有被收录。  3天后。  原先的网站收录没有变,新站开始被收录首页。  4天后。  原网站收录仍然不变,排名依旧,新站多收录了2条内页。因为做了301的缘故,原网站的PR值从2变成了0,新站PR还没有到2。  接下来的几天:  百度更新数据库。  原网站收录量从1000降到10,新站从2升到10,可见百度更新了数据库,原网站的大部分收录都被清楚了。  谷歌恢复关键词排名  原网站目标关键词在更换域名之后消失,现在又关键词又以新站的域名排在了谷歌首页的第十位。  百度收录新首页并恢复关键词排名  一直到现在,百度终于更新了新站的快照,并且恢复了网站的大部分目标词的排名,不过收录方面还是做新站处理,依然只有5条,不过相比于一般的新站,301还是起到了比较关键的作用。对于网站更换什么域名好,新域名还是老域名,详情请关注域名到期查询 ------------------------- 还是专家清楚 引用第4楼元芳于2014-11-05 21:05发表的  : 在百度站长平台 把A域名301到B域名~

小哈哈乖乖 2019-12-02 00:53:14 0 浏览量 回答数 0

回答

简介 ES是一个基于RESTful web接口并且构建在Apache Lucene之上的开源分布式搜索引擎。 同时ES还是一个分布式文档数据库,其中每个字段均可被索引,而且每个字段的数据均可被搜索,能够横向扩展至数以百计的服务器存储以及处理PB级的数据。 可以在极短的时间内存储、搜索和分析大量的数据。通常作为具有复杂搜索场景情况下的核心发动机。 ES就是为高可用和可扩展而生的。一方面可以通过升级硬件来完成系统扩展,称为垂直或向上扩展(Vertical Scale/Scaling Up)。 另一方面,增加更多的服务器来完成系统扩展,称为水平扩展或者向外扩展(Horizontal Scale/Scaling Out)。尽管ES能够利用更强劲的硬件,但是垂直扩展毕竟还是有它的极限。真正的可扩展性来自于水平扩展,通过向集群中添加更多的节点来分担负载,增加可靠性。ES天生就是分布式的,它知道如何管理多个节点来完成扩展和实现高可用性。意味应用不需要做任何的改动。 Gateway,代表ES索引的持久化存储方式。在Gateway中,ES默认先把索引存储在内存中,然后当内存满的时候,再持久化到Gateway里。当ES集群关闭或重启的时候,它就会从Gateway里去读取索引数据。比如LocalFileSystem和HDFS、AS3等。 DistributedLucene Directory,它是Lucene里的一些列索引文件组成的目录。它负责管理这些索引文件。包括数据的读取、写入,以及索引的添加和合并等。 River,代表是数据源。是以插件的形式存在于ES中。  Mapping,映射的意思,非常类似于静态语言中的数据类型。比如我们声明一个int类型的变量,那以后这个变量只能存储int类型的数据。比如我们声明一个double类型的mapping字段,则只能存储double类型的数据。 Mapping不仅是告诉ES,哪个字段是哪种类型。还能告诉ES如何来索引数据,以及数据是否被索引到等。 Search Moudle,搜索模块,支持搜索的一些常用操作 Index Moudle,索引模块,支持索引的一些常用操作 Disvcovery,主要是负责集群的master节点发现。比如某个节点突然离开或进来的情况,进行一个分片重新分片等。这里有个发现机制。 发现机制默认的实现方式是单播和多播的形式,即Zen,同时也支持点对点的实现。另外一种是以插件的形式,即EC2。 Scripting,即脚本语言。包括很多,这里不多赘述。如mvel、js、python等。    Transport,代表ES内部节点,代表跟集群的客户端交互。包括 Thrift、Memcached、Http等协议 RESTful Style API,通过RESTful方式来实现API编程。 3rd plugins,代表第三方插件。 Java(Netty),是开发框架。 JMX,是监控。 使用案例 1、将ES作为网站的主要后端系统 比如现在搭建一个博客系统,对于博客帖子的数据可以直接在ES上存储,并且使用ES来进行检索,统计。ES提供了持久化的存储、统计和很多其他数据存储的特性。 注意:但是像其他的NOSQL数据存储一样,ES是不支持事务的,如果要事务机制,还是考虑使用其他的数据库做真实库。 2、将ES添加到现有系统 有些时候不需要ES提供所有数据的存储功能,只是想在一个数据存储的基础之上使用ES。比如已经有一个复杂的系统在运行,但是现在想加一个搜索的功能,就可以使用该方案。 3、将ES作为现有解决方案的后端部分 因为ES是开源的系统,提供了直接的HTTP接口,并且现在有一个大型的生态系统在支持他。比如现在我们想部署大规模的日志框架、用于存储、搜索和分析海量的事件,考虑到现有的工具可以写入和读取ES,可以不需要进行任何开发,配置这些工具就可以去运作。 设计结构 1、逻辑设计 文档 文档是可以被索引的信息的基本单位,它包含几个重要的属性: 是自我包含的。一篇文档同时包含字段和他们的取值。 是层次型的。文档中还可以包含新的文档,一个字段的取值可以是简单的,例如location字段的取值可以是字符串,还可以包含其他字段和取值,比如可以同时包含城市和街道地址。 拥有灵活的结构。文档不依赖于预先定义的模式。也就是说并非所有的文档都需要拥有相同的字段,并不受限于同一个模式 {   "name":"meeting",   "location":"office",   "organizer":"yanping" } {   "name":"meeting",   "location":{     "name":"sheshouzuo",        "date":"2019-6-28"   },   "memebers":["leio","shiyi"] } 类型 类型是文档的逻辑容器,类似于表格是行的容器。在不同的类型中,最好放入不同的结构的文档。 字段 ES中,每个文档,其实是以json形式存储的。而一个文档可以被视为多个字段的集合。 映射 每个类型中字段的定义称为映射。例如,name字段映射为String。 索引 索引是映射类型的容器一个ES的索引非常像关系型世界中的数据库,是独立的大量文档集合。   关系型数据库与ES的结构上的对比 2、物理设计 节点 一个节点是一个ES的实例,在服务器上启动ES之后,就拥有了一个节点,如果在另一个服务器上启动ES,这就是另一个节点。甚至可以在一台服务器上启动多个ES进程,在一台服务器上拥有多个节点。多个节点可以加入同一个集群。 当ElasticSearch的节点启动后,它会利用多播(multicast)(或者单播,如果用户更改了配置)寻找集群中的其它节点,并与之建立连接。这个过程如下图所示: 节点主要有3种类型,第一种类型是client_node,主要是起到请求分发的作用,类似路由。第二种类型是master_node,是主的节点,所有的新增,删除,数据分片都是由主节点操作(elasticsearch底层是没有更新数据操作的,上层对外提供的更新实际上是删除了再新增),当然也能承担搜索操作。第三种类型是date_node,该类型的节点只能做搜索操作,具体会分配到哪个date_node,就是由client_node决定,而data_node的数据都是从master_node同步过来的 分片 一个索引可以存储超出单个结点硬件限制的大量数据。比如,一个具有10亿文档的索引占据1TB的磁盘空间,而任一节点都没有这样大的磁盘空间;或者单个节点处理搜索请求,响应太慢。   为了解决这个问题,ES提供了将索引划分成多份的能力,这些份就叫做分片。当你创建一个索引的时候,你可以指定你想要的分片的数量。每个分片本身也是一个功能完善并且独立的“索引”,这个“索引”可以被放置到集群中的任何节点上。 分片之所以重要,主要有两方面的原因:   1、允许你水平分割/扩展你的内容容量 允许你在分片(潜在地,位于多个节点上)之上进行分布式的、并行的操作,进而提高性能/吞吐量 至于一个分片怎样分布,它的文档怎样聚合回搜索请求,是完全由ES管理的,对于作为用户的你来说,这些都是透明的。   2、在一个网络/云的环境里,失败随时都可能发生,在某个分片/节点不知怎么的就处于离线状态,或者由于任何原因消失了。这种情况下,有一个故障转移机制是非常有用并且是强烈推荐的。为此目的,ES允许你创建分片的一份或多份拷贝,这些拷贝叫做复制分片,或者直接叫复制。 复制之所以重要,主要有两方面的原因: (1)在分片/节点失败的情况下,提供了高可用性。因为这个原因,注意到复制分片从不与原/主要(original/primary)分片置于同一节点上是非常重要的。 (2)扩展你的搜索量/吞吐量,因为搜索可以在所有的复制上并行运行 总之,每个索引可以被分成多个分片。一个索引也可以被复制0次(意思是没有复制)或多次。一旦复制了,每个索引就有了主分片(作为复制源的原来的分片)和复制分片(主分片的拷贝)之别。分片和复制的数量可以在索引创建的时候指定。在索引创建之后,你可以在任何时候动态地改变复制数量,但是不能改变分片的数量。   默认情况下,ES中的每个索引被分片5个主分片和1个复制,这意味着,如果你的集群中至少有两个节点,你的索引将会有5个主分片和另外5个复制分片(1个完全拷贝),这样的话每个索引总共就有10个分片。一个索引的多个分片可以存放在集群中的一台主机上,也可以存放在多台主机上,这取决于你的集群机器数量。主分片和复制分片的具体位置是由ES内在的策略所决定的。 3、插件HEAD elasticsearch-head是一个界面化的集群操作和管理工具 ● node:即一个 Elasticsearch 的运行实例,使用多播或单播方式发现 cluster 并加入。 ● cluster:包含一个或多个拥有相同集群名称的 node,其中包含一个master node。 ● index:类比关系型数据库里的DB,是一个逻辑命名空间。 ● alias:可以给 index 添加零个或多个alias,通过 alias 使用index 和根据index name 访问index一样,但是,alias给我们提供了一种切换index的能力,比如重建了index,取名● customer_online_v2,这时,有了alias,我要访问新 index,只需要把 alias 添加到新 index 即可,并把alias从旧的 index 删除。不用修改代码。 ● type:类比关系数据库里的Table。其中,一个index可以定义多个type,但一般使用习惯仅配一个type。 ● mapping:类比关系型数据库中的 schema 概念,mapping 定义了 index 中的 type。mapping 可以显示的定义,也可以在 document 被索引时自动生成,如果有新的 field,Elasticsearch 会自动推测出 field 的type并加到mapping中。 ● document:类比关系数据库里的一行记录(record),document 是 Elasticsearch 里的一个 JSON 对象,包括零个或多个field。 ● field:类比关系数据库里的field,每个field 都有自己的字段类型。 ● shard:是一个Lucene 实例。Elasticsearch 基于 Lucene,shard 是一个 Lucene 实例,被 Elasticsearch 自动管理。之前提到,index 是一个逻辑命名空间,shard 是具体的物理概念,建索引、查询等都是具体的shard在工作。shard 包括primary shard 和 replica shard,写数据时,先写到primary shard,然后,同步到replica shard,查询时,primary 和 replica 充当相同的作用。replica shard 可以有多份,也可以没有,replica shard的存在有两个作用,一是容灾,如果primary shard 挂了,数据也不会丢失,集群仍然能正常工作;二是提高性能,因为replica 和 primary shard 都能处理查询。另外,如上图右侧红框所示,shard数和replica数都可以设置,但是,shard 数只能在建立index 时设置,后期不能更改,但是,replica 数可以随时更改。但是,由于 Elasticsearch 很友好的封装了这部分,在使用Elasticsearch 的过程中,我们一般仅需要关注 index 即可,不需关注shard。   shard、node、cluster 在物理上构成了 Elasticsearch 集群,field、type、index 在逻辑上构成一个index的基本概念,在使用 Elasticsearch 过程中,我们一般关注到逻辑概念就好,就像我们在使用MySQL 时,我们一般就关注DB Name、Table和schema即可,而不会关注DBA维护了几个MySQL实例、master 和 slave 等怎么部署的一样。 ES中的索引原理 (1)传统的关系型数据库 二叉树查找效率是logN,同时插入新的节点不必移动全部节点,所以用树型结构存储索引,能同时兼顾插入和查询的性能。因此在这个基础上,再结合磁盘的读取特性(顺序读/随机读),传统关系型数据库采用了B-Tree/B+Tree这样的数据结构做索引 (2)ES 采用倒排索引 那么,倒排索引是个什么样子呢? 首先,来搞清楚几个概念,为此,举个例子: 假设有个user索引,它有四个字段:分别是name,gender,age,address。画出来的话,大概是下面这个样子,跟关系型数据库一样 Term(单词):一段文本经过分析器分析以后就会输出一串单词,这一个一个的就叫做Term Term Dictionary(单词字典):顾名思义,它里面维护的是Term,可以理解为Term的集合 Term Index(单词索引):为了更快的找到某个单词,我们为单词建立索引 Posting List(倒排列表):倒排列表记录了出现过某个单词的所有文档的文档列表及单词在该文档中出现的位置信息,每条记录称为一个倒排项(Posting)。根据倒排列表,即可获知哪些文档包含某个单词。(PS:实际的倒排列表中并不只是存了文档ID这么简单,还有一些其它的信息,比如:词频(Term出现的次数)、偏移量(offset)等,可以想象成是Python中的元组,或者Java中的对象) (PS:如果类比现代汉语词典的话,那么Term就相当于词语,Term Dictionary相当于汉语词典本身,Term Index相当于词典的目录索引) 我们知道,每个文档都有一个ID,如果插入的时候没有指定的话,Elasticsearch会自动生成一个,因此ID字段就不多说了 上面的例子,Elasticsearch建立的索引大致如下: name字段: age字段: gender字段: address字段: Elasticsearch分别为每个字段都建立了一个倒排索引。比如,在上面“张三”、“北京市”、22 这些都是Term,而[1,3]就是Posting List。Posting list就是一个数组,存储了所有符合某个Term的文档ID。 只要知道文档ID,就能快速找到文档。可是,要怎样通过我们给定的关键词快速找到这个Term呢? 当然是建索引了,为Terms建立索引,最好的就是B-Tree索引(MySQL就是B树索引最好的例子)。 我们查找Term的过程跟在MyISAM中记录ID的过程大致是一样的 MyISAM中,索引和数据是分开,通过索引可以找到记录的地址,进而可以找到这条记录 在倒排索引中,通过Term索引可以找到Term在Term Dictionary中的位置,进而找到Posting List,有了倒排列表就可以根据ID找到文档了 (PS:可以这样理解,类比MyISAM的话,Term Index相当于索引文件,Term Dictionary相当于数据文件) (PS:其实,前面我们分了三步,我们可以把Term Index和Term Dictionary看成一步,就是找Term。因此,可以这样理解倒排索引:通过单词找到对应的倒排列表,根据倒排列表中的倒排项进而可以找到文档记录) 为了更进一步理解,用两张图来具现化这一过程: (至于里面涉及的更加高深的数据压缩技巧,以及多个field联合查询利用跳表的数据结构快速做运算来查询,这些大家有兴趣可以自己去了解)

问问小秘 2020-04-29 15:40:48 0 浏览量 回答数 0

回答

134题 其实就是水平扩容了,Zookeeper在这方面不太好。两种方式:全部重启:关闭所有Zookeeper服务,修改配置之后启动。不影响之前客户端的会话。逐个重启:这是比较常用的方式。 133题 集群最低3(2N+1)台,保证奇数,主要是为了选举算法。一个由 3 台机器构成的 ZooKeeper 集群,能够在挂掉 1 台机器后依然正常工作,而对于一个由 5 台服务器构成的 ZooKeeper 集群,能够对 2 台机器挂掉的情况进行容灾。注意,如果是一个由6台服务器构成的 ZooKeeper 集群,同样只能够挂掉 2 台机器,因为如果挂掉 3 台,剩下的机器就无法实现过半了。 132题 基于“过半”设计原则,ZooKeeper 在运行期间,集群中至少有过半的机器保存了最新的数据。因此,只要集群中超过半数的机器还能够正常工作,整个集群就能够对外提供服务。 131题 不是。官方声明:一个Watch事件是一个一次性的触发器,当被设置了Watch的数据发生了改变的时候,则服务器将这个改变发送给设置了Watch的客户端,以便通知它们。为什么不是永久的,举个例子,如果服务端变动频繁,而监听的客户端很多情况下,每次变动都要通知到所有的客户端,这太消耗性能了。一般是客户端执行getData(“/节点A”,true),如果节点A发生了变更或删除,客户端会得到它的watch事件,但是在之后节点A又发生了变更,而客户端又没有设置watch事件,就不再给客户端发送。在实际应用中,很多情况下,我们的客户端不需要知道服务端的每一次变动,我只要最新的数据即可。 130题 数据发布/订阅,负载均衡,命名服务,分布式协调/通知,集群管理,Master 选举,分布式锁,分布式队列 129题 客户端 SendThread 线程接收事件通知, 交由 EventThread 线程回调 Watcher。客户端的 Watcher 机制同样是一次性的, 一旦被触发后, 该 Watcher 就失效了。 128题 1、服务端接收 Watcher 并存储; 2、Watcher 触发; 2.1 封装 WatchedEvent; 2.2 查询 Watcher; 2.3 没找到;说明没有客户端在该数据节点上注册过 Watcher; 2.4 找到;提取并从 WatchTable 和 Watch2Paths 中删除对应 Watcher; 3、调用 process 方法来触发 Watcher。 127题 1.调用 getData()/getChildren()/exist()三个 API,传入 Watcher 对象 2.标记请求 request,封装 Watcher 到 WatchRegistration 3.封装成 Packet 对象,发服务端发送 request 4.收到服务端响应后,将 Watcher 注册到 ZKWatcherManager 中进行管理 5.请求返回,完成注册。 126题 Zookeeper 允许客户端向服务端的某个 Znode 注册一个 Watcher 监听,当服务端的一些指定事件触发了这个 Watcher,服务端会向指定客户端发送一个事件通知来实现分布式的通知功能,然后客户端根据 Watcher 通知状态和事件类型做出业务上的改变。工作机制:(1)客户端注册 watcher(2)服务端处理 watcher(3)客户端回调 watcher 125题 服务器具有四种状态,分别是 LOOKING、FOLLOWING、LEADING、OBSERVING。 LOOKING:寻 找 Leader 状态。当服务器处于该状态时,它会认为当前集群中没有 Leader,因此需要进入 Leader 选举状态。 FOLLOWING:跟随者状态。表明当前服务器角色是 Follower。 LEADING:领导者状态。表明当前服务器角色是 Leader。 OBSERVING:观察者状态。表明当前服务器角色是 Observer。 124题 Zookeeper 有三种部署模式:单机部署:一台集群上运行;集群部署:多台集群运行;伪集群部署:一台集群启动多个 Zookeeper 实例运行。 123题 Paxos算法是分布式选举算法,Zookeeper使用的 ZAB协议(Zookeeper原子广播),二者有相同的地方,比如都有一个Leader,用来协调N个Follower的运行;Leader要等待超半数的Follower做出正确反馈之后才进行提案;二者都有一个值来代表Leader的周期。不同的地方在于:ZAB用来构建高可用的分布式数据主备系统(Zookeeper),Paxos是用来构建分布式一致性状态机系统。Paxos算法、ZAB协议要想讲清楚可不是一时半会的事儿,自1990年莱斯利·兰伯特提出Paxos算法以来,因为晦涩难懂并没有受到重视。后续几年,兰伯特通过好几篇论文对其进行更进一步地解释,也直到06年谷歌发表了三篇论文,选择Paxos作为chubby cell的一致性算法,Paxos才真正流行起来。对于普通开发者来说,尤其是学习使用Zookeeper的开发者明确一点就好:分布式Zookeeper选举Leader服务器的算法与Paxos有很深的关系。 122题 ZAB协议是为分布式协调服务Zookeeper专门设计的一种支持崩溃恢复的原子广播协议(paxos算法的一种实现)。ZAB协议包括两种基本的模式:崩溃恢复和消息广播。当整个zookeeper集群刚刚启动或者Leader服务器宕机、重启或者网络故障导致不存在过半的服务器与Leader服务器保持正常通信时,所有进程(服务器)进入崩溃恢复模式,首先选举产生新的Leader服务器,然后集群中Follower服务器开始与新的Leader服务器进行数据同步,当集群中超过半数机器与该Leader服务器完成数据同步之后,退出恢复模式进入消息广播模式,Leader服务器开始接收客户端的事务请求生成事物提案来进行事务请求处理。 121题 Zookeeper本身也是集群,推荐配置不少于3个服务器。Zookeeper自身也要保证当一个节点宕机时,其他节点会继续提供服务。如果是一个Follower宕机,还有2台服务器提供访问,因为Zookeeper上的数据是有多个副本的,数据并不会丢失;如果是一个Leader宕机,Zookeeper会选举出新的Leader。ZK集群的机制是只要超过半数的节点正常,集群就能正常提供服务。只有在ZK节点挂得太多,只剩一半或不到一半节点能工作,集群才失效。所以,3个节点的cluster可以挂掉1个节点(leader可以得到2票>1.5),2个节点的cluster就不能挂掉任何1个节点了(leader可以得到1票<=1)。 120题 选完Leader以后,zk就进入状态同步过程。1、Leader等待server连接;2、Follower连接leader,将最大的zxid发送给leader;3、Leader根据follower的zxid确定同步点;4、完成同步后通知follower 已经成为uptodate状态;5、Follower收到uptodate消息后,又可以重新接受client的请求进行服务了。 119题 在zookeeper集群中也是一样,每个节点都会投票,如果某个节点获得超过半数以上的节点的投票,则该节点就是leader节点了。zookeeper中有三种选举算法,分别是LeaderElection,FastLeaderElection,AuthLeaderElection, FastLeaderElection此算法和LeaderElection不同的是它不会像后者那样在每轮投票中要搜集到所有结果后才统计投票结果,而是不断的统计结果,一旦没有新的影响leader结果的notification出现就返回投票结果。这样的效率更高。 118题 zk的负载均衡是可以调控,nginx只是能调权重,其他需要可控的都需要自己写插件;但是nginx的吞吐量比zk大很多,应该说按业务选择用哪种方式。 117题 Zookeeper 的核心是原子广播,这个机制保证了各个Server之间的同步。实现这个机制的协议叫做Zab协议。Zab协议有两种模式,它们分别是恢复模式(选主)和广播模式(同步)。当服务启动或者在领导者崩溃后,Zab就进入了恢复模式,当领导者被选举出来,且大多数Server完成了和 leader的状态同步以后,恢复模式就结束了。状态同步保证了leader和Server具有相同的系统状态。 116题 有临时节点和永久节点,分再细一点有临时有序/无序节点,有永久有序/无序节点。当创建临时节点的程序结束后,临时节点会自动消失,临时节点上的数据也会一起消失。 115题 在分布式环境中,有些业务逻辑只需要集群中的某一台机器进行执行,其他的机器可以共享这个结果,这样可以大大减少重复计算,提高性能,这就是主节点存在的意义。 114题 ZooKeeper 实现分布式事务,类似于两阶段提交,总共分为以下 4 步:客户端先给 ZooKeeper 节点发送写请求;ZooKeeper 节点将写请求转发给 Leader 节点,Leader 广播给集群要求投票,等待确认;Leader 收到确认,统计投票,票数过半则提交事务;事务提交成功后,ZooKeeper 节点告知客户端。 113题 ZooKeeper 实现分布式锁的步骤如下:客户端连接 ZooKeeper,并在 /lock 下创建临时的且有序的子节点,第一个客户端对应的子节点为 /lock/lock-10000000001,第二个为 /lock/lock-10000000002,以此类推。客户端获取 /lock 下的子节点列表,判断自己创建的子节点是否为当前子节点列表中序号最小的子节点,如果是则认为获得锁,否则监听刚好在自己之前一位的子节点删除消息,获得子节点变更通知后重复此步骤直至获得锁;执行业务代码;完成业务流程后,删除对应的子节点释放锁。 112题 ZooKeeper 特性如下:顺序一致性(Sequential Consistency):来自相同客户端提交的事务,ZooKeeper 将严格按照其提交顺序依次执行;原子性(Atomicity):于 ZooKeeper 集群中提交事务,事务将“全部完成”或“全部未完成”,不存在“部分完成”;单一系统镜像(Single System Image):客户端连接到 ZooKeeper 集群的任意节点,其获得的数据视图都是相同的;可靠性(Reliability):事务一旦完成,其产生的状态变化将永久保留,直到其他事务进行覆盖;实时性(Timeliness):事务一旦完成,客户端将于限定的时间段内,获得最新的数据。 111题 ZooKeeper 通常有三种搭建模式:单机模式:zoo.cfg 中只配置一个 server.id 就是单机模式了,此模式一般用在测试环境,如果当前主机宕机,那么所有依赖于当前 ZooKeeper 服务工作的其他服务器都不能进行正常工作;伪分布式模式:在一台机器启动不同端口的 ZooKeeper,配置到 zoo.cfg 中,和单机模式相同,此模式一般用在测试环境;分布式模式:多台机器各自配置 zoo.cfg 文件,将各自互相加入服务器列表,上面搭建的集群就是这种完全分布式。 110题 ZooKeeper 主要提供以下功能:分布式服务注册与订阅:在分布式环境中,为了保证高可用性,通常同一个应用或同一个服务的提供方都会部署多份,达到对等服务。而消费者就须要在这些对等的服务器中选择一个来执行相关的业务逻辑,比较典型的服务注册与订阅,如 Dubbo。分布式配置中心:发布与订阅模型,即所谓的配置中心,顾名思义就是发布者将数据发布到 ZooKeeper 节点上,供订阅者获取数据,实现配置信息的集中式管理和动态更新。命名服务:在分布式系统中,通过命名服务客户端应用能够根据指定名字来获取资源、服务地址和提供者等信息。分布式锁:这个主要得益于 ZooKeeper 为我们保证了数据的强一致性。 109题 Dubbo是 SOA 时代的产物,它的关注点主要在于服务的调用,流量分发、流量监控和熔断。而 Spring Cloud诞生于微服务架构时代,考虑的是微服务治理的方方面面,另外由于依托了 Spirng、Spirng Boot的优势之上,两个框架在开始目标就不一致,Dubbo 定位服务治理、Spirng Cloud 是一个生态。 108题 Dubbo通过Token令牌防止用户绕过注册中心直连,然后在注册中心上管理授权。Dubbo还提供服务黑白名单,来控制服务所允许的调用方。 107题 Dubbo超时时间设置有两种方式: 服务提供者端设置超时时间,在Dubbo的用户文档中,推荐如果能在服务端多配置就尽量多配置,因为服务提供者比消费者更清楚自己提供的服务特性。 服务消费者端设置超时时间,如果在消费者端设置了超时时间,以消费者端为主,即优先级更高。因为服务调用方设置超时时间控制性更灵活。如果消费方超时,服务端线程不会定制,会产生警告。 106题 Random LoadBalance: 随机选取提供者策略,有利于动态调整提供者权重。截面碰撞率高,调用次数越多,分布越均匀; RoundRobin LoadBalance: 轮循选取提供者策略,平均分布,但是存在请求累积的问题; LeastActive LoadBalance: 最少活跃调用策略,解决慢提供者接收更少的请求; ConstantHash LoadBalance: 一致性Hash策略,使相同参数请求总是发到同一提供者,一台机器宕机,可以基于虚拟节点,分摊至其他提供者,避免引起提供者的剧烈变动; 缺省时为Random随机调用。 105题 Consumer(消费者),连接注册中心 ,并发送应用信息、所求服务信息至注册中心。 注册中心根据 消费 者所求服务信息匹配对应的提供者列表发送至Consumer 应用缓存。 Consumer 在发起远程调用时基于缓存的消费者列表择其一发起调用。 Provider 状态变更会实时通知注册中心、在由注册中心实时推送至Consumer。 104题 Provider:暴露服务的服务提供方。 Consumer:调用远程服务的服务消费方。 Registry:服务注册与发现的注册中心。 Monitor:统计服务的调用次调和调用时间的监控中心。 Container:服务运行容器。 103题 主要就是如下3个核心功能: Remoting:网络通信框架,提供对多种NIO框架抽象封装,包括“同步转异步”和“请求-响应”模式的信息交换方式。 Cluster:服务框架,提供基于接口方法的透明远程过程调用,包括多协议支持,以及软负载均衡,失败容错,地址路由,动态配置等集群支持。 Registry:服务注册,基于注册中心目录服务,使服务消费方能动态的查找服务提供方,使地址透明,使服务提供方可以平滑增加或减少机器。 102题 透明化的远程方法调用,就像调用本地方法一样调用远程方法,只需简单配置,没有任何API侵入。软负载均衡及容错机制,可在内网替代F5等硬件负载均衡器,降低成本,减少单点。服务自动注册与发现,不再需要写死服务提供方地址,注册中心基于接口名查询服务提供者的IP地址,并且能够平滑添加或删除服务提供者。 101题 垂直分表定义:将一个表按照字段分成多表,每个表存储其中一部分字段。水平分表是在同一个数据库内,把同一个表的数据按一定规则拆到多个表中。 100题 垂直分库是指按照业务将表进行分类,分布到不同的数据库上面,每个库可以放在不同的服务器上,它的核心理念是专库专用。水平分库是把同一个表的数据按一定规则拆到不同的数据库中,每个库可以放在不同的服务器上。 99题 QPS:每秒查询数。TPS:每秒处理事务数。Uptime:服务器已经运行的时间,单位秒。Questions:已经发送给数据库查询数。Com_select:查询次数,实际操作数据库的。Com_insert:插入次数。Com_delete:删除次数。Com_update:更新次数。Com_commit:事务次数。Com_rollback:回滚次数。 98题 如果需要跨主机进行JOIN,跨应用进行JOIN,或者数据库不能获得较好的执行计划,都可以自己通过程序来实现JOIN。 例如:SELECT a.,b. FROM a,b WHERE a.col1=b.col1 AND a.col2> 10 ORDER BY a.col2; 可以利用程序实现,先SELECT * FROM a WHERE a.col2>10 ORDER BY a.col2;–(1) 利用(1)的结果集,做循环,SELECT * FROM b WHERE b.col1=a.col1; 这样可以避免排序,可以在程序里控制执行的速度,有效降低数据库压力,也可以实现跨主机的JOIN。 97题 搭建复制的必备条件:复制的机器之间网络通畅,Master打开了binlog。 搭建复制步骤:建立用户并设置权限,修改配置文件,查看master状态,配置slave,启动从服务,查看slave状态,主从测试。 96题 Heartbeat方案:利用Heartbeat管理VIP,利用crm管理MySQL,MySQL进行双M复制。(Linux系统下没有分库的标准方案)。 LVS+Keepalived方案:利用Keepalived管理LVS和VIP,LVS分发请求到MySQL,MySQL进行双M复制。(Linux系统下无分库无事务的方案)。 Cobar方案:利用Cobar进行HA和分库,应用程序请求Cobar,Cobar转发请求道数据库。(有分库的标准方案,Unix下唯一方案)。 95题 聚集(clustered)索引,也叫聚簇索引,数据行的物理顺序与列值(一般是主键的那一列)的逻辑顺序相同,一个表中只能拥有一个聚集索引。但是,覆盖索引可以模拟多个聚集索引。存储引擎负责实现索引,因此不是所有的存储索引都支持聚集索引。当前,SolidDB和InnoDB是唯一支持聚集索引的存储引擎。 优点:可以把相关数据保存在一起。数据访问快。 缺点:聚集能最大限度地提升I/O密集负载的性能。聚集能最大限度地提升I/O密集负载的性能。建立在聚集索引上的表在插入新行,或者在行的主键被更新,该行必须被移动的时候会进行分页。聚集表可会比全表扫描慢,尤其在表存储得比较稀疏或因为分页而没有顺序存储的时候。第二(非聚集)索引可能会比预想的大,因为它们的叶子节点包含了被引用行的主键列。 94题 以下原因是导致mysql 表毁坏的常见原因: 服务器突然断电导致数据文件损坏; 强制关机,没有先关闭mysql 服务; mysqld 进程在写表时被杀掉; 使用myisamchk 的同时,mysqld 也在操作表; 磁盘故障;服务器死机;mysql 本身的bug 。 93题 1.定位慢查询 首先先打开慢查询日志设置慢查询时间; 2.分析慢查询(使用explain工具分析sql语句); 3.优化慢查询 。

游客ih62co2qqq5ww 2020-06-15 13:55:41 0 浏览量 回答数 0

问题

SDK及DEMO下载

nicenelly 2019-12-01 20:57:56 1162 浏览量 回答数 0

回答

在这个信息时代高速发展的情况下,很多人会对自己该往哪个方向发展感到迷茫,下面我就浅显的给大家介绍一下五大流行区域的发展前景。大数据的发展前景:当前大数据行业真的是人才稀缺吗?学了几年后,大数据行业会不会产能过剩?大数据行业最终需要什么样的人才?接下来就带你们看看分析结果:当前大数据行业真的是人才稀缺吗?对!未来人才缺口150万,数据分析人才最稀缺。先看大数据人才缺口有多大?根据LinkedIn(领英)发布的《2016年中国互联网最热职位人才报告》显示,研发工程师、产品经理、人力资源、市场营销、运营和数据分析是当下中国互联网行业需求最旺盛的六类人才职位。其中数据分析人才最为稀缺、供给指数最低。同时,数据分析人才跳槽速度也最快,平均跳槽速度为19.8个月。而清华大学计算机系教授武永卫去年透露了一组数据:未来3-5年,中国需要180万数据人才,但目前只有约30万人。大数据行业未来会产能过剩吗?提供大数据技术与应用服务的第三方公司面临调整,未来发展会趋集中关于“大数据概念是否被过度炒作”的讨论,其实2013年的夏季达沃斯就有过。彼时支持“炒作”观点的现场观众达54.5%。对此,持反对意见的北京大学光华管理学院副教授苏萌提出了三个理由:不同机构间的数据还未真正流动起来,目前还只是数据“孤岛”;完整的生态产业链还未形成,尽管通过行为数据分析已能够分辨出一个消费者的喜好,但从供应到购买的链条还没建成;数据分析人才仍然极度匮乏。4年之后,舆论热点已经逐渐从大数据转向人工智能,大数据行业也历经整合。近一年间,一些大数据公司相继出现裁员、业务大调整等情况,部分公司出现亏损。那都是什么公司面临危机呢?基于数据归属,涉及大数据业务的公司其实有两类:一类是自身拥有数据的甲方公司,如亚马逊、阿里巴巴等;另一类是整合数据资源,提供大数据技术与应用服务的第三方公司。目前行业整合出现盈利问题的公司多集中在第三方服务商。对此,LinkedIn(领英)中国技术副总裁王迪表示,第三方服务商提供的更多的是技术或平台,大数据更多还是让甲方公司获益。在王迪看来,大数据业务要产生规模效益,至少要具备三点:算法、计算平台以及数据本身。“第三方大数据创业公司在算法上有一技之长,而计算能力实际上已经匀化了,传统企业如果用好了,和大数据创业公司没有区别,甚至计算能力更强,而数据获取方面,很多数据在传统行业内部并没有共享出来,第三方大数据公司获取这些数据是比较困难的,最后可能谁有数据,谁产生的价值更高。”说白了,数据为王。在2013年,拿到千万级A轮融资的大数据企业不足10家,到2015年,拿到千万级以上A轮融资的企业已经超过30家。直到2016年互联网资本寒冬,大数据行业投资热度有所减退,大数据行业是否也存在产能过剩?王迪认为,目前的行业整合属于正常现象,“经过市场的优胜劣汰,第三方服务领域会出现一些做得比较好的公司,其他公司可能被淘汰或转型做一些垂直行业应用。从社会来看,总的需求量一定是增加的,而对于供给侧,经过行业自然的洗牌,最终会集中在几家优秀的行业公司。”需要什么样的大数据人才?今年3月份,教育部公布了第二批获准开设“数据科学与大数据技术”的高校名单,加上第一批获批的北京大学、对外经济贸易大学、中南大学,一共35所高校获批该专业。今年开始,部分院校将招收第一届大数据专业本科生。大数据人才培养涉及到两方面问题:交叉性学科的人才培养方案是否与市场需求相匹配;学科建设的周期与行业快速更新之间的差距怎样弥合。对于第一个问题,“电商热”时期开设的电子商务专业是一个可吸取经验的样本。2000年,教育部高教司批准了第一批高校开设电子商务本科专业。作为一个复合型专业,电子商务的本科教学涵盖了管理、技术、营销三方面的课程。电子商务领域人才需求量大,但企业却无法从电子商务专业中找到合适的人才,原因何在?职业规划专家姜萌认为,并不是某一个专业对应一个行业热点,而是一个专业集群对应一个行业热点。“比如电子商务专业,我们到电子商务公司里会发现,不是学电子商务的人在做这些工作,而是每个专业各司其职,比如计算机、设计、物流管理、营销、广告、金融等等。现在行业的复合型工作都是由一个专业集群来完成的,而不是一个人来复合一堆专业特点。”大数据专业的人才培养也同样走复合型路线,复旦大学大数据学院的招生简章显示,学院本科人才培养以统计学、计算机科学和数学为三大基础支撑性学科,以生物学、医学、环境科学、经济学、社会学、管理学等为应用拓展性学科,具备典型的交叉学科特征。LinkedIn(领英)中国技术副总裁王迪指出,“从企业应用的角度来看,大数据行业里从事相关职能的同学背景是各异的,大数据作为一个人才培养方向还在探索中,在这个阶段,高校尝试开设硕士课程是很好的实践,但开设一类的本科专业还为时过早。”另一方面,专业人才培养的周期较长,而行业热点不断更新轮替,中间产生的时间差使得新兴专业的志愿填报具备了一定风险。王迪认为,“从今天的产业实践上看,大数据领域依然是从现有专业中挑选人才,教育和市场发展总是有一定差距的,学生本科四年,加上硕士阶段已经是七年之后的事情了,产业已经演进了很多,而教学大纲并不会跟进得那么快。”因此,尽管大数据的应用前景毋庸置疑,但在人才培养层面,复合型人才培养方案会不会重走电子商务专业的老路?学校教育如何赶上行业发展速度?这些都是值得进一步商榷的问题。面对热门专业,志愿填报需要注意啥?了解了大数据行业、公司和大数据专业后,姜萌对于考生填报像大数据相关的热门专业,提出了几条建议:报考热的专业和就业热的专业并不一定是重合的,比如软件、计算机、金融,这些专业的就业率实际并没有那么高,地质勘探、石油、遥感等专业,虽然报考上是冷门,但行业需求大,就业率更高。选择热门专业,更需要考虑就业质量。专业就业好,是统计学意义,指的是平均收入水平高,比如金融专业的收入,比其他纯文科专业的平均收入较高,但落实到个体层面,就业情况就不一样了,尤其像金融专业是典型的名校高学历好就业,但对于考试成绩较低的同学来说,如果去一些普通院校、专科院校学习金融,最后就业情况可能还不如会计专业。志愿填报,除了专业,城市因素也很重要:如果想从事金融、互联网的工作,更适合去一线城市,如果是去三、四线城市的学生可以考虑应用面比较广的专业,就是各行各业都能用到的专业,比如会计专业,专科层次的会计和985层次的会计都有就业渠道。如果先选择报考城市,也可以针对所在城市的行业特点选择专业,比如沿海城市外贸相对发达,选择国际贸易、外语类专业就业情况更好,比如武汉有光谷,选择光电类专业更好就业。最终家长和考生更需要考虑个人与专业匹配的问题,金融、计算机等热门专业不是所有人都适合学,好专业不见得对所有个体都是好的。java的发展前景:由于Java的诸多优点,Java的发展前景十分广泛。比如,在我们中国的市场,Java无论在企业级应用,还是在面向大众的服务方面都取得了不少进展,在中国的电信、金融等关键性业务中发挥着举足轻重的作用。由于SUN、TBM、Oracle等国际厂商相继推出各种基于Java技术的应用服务器以及各种应用软件,推动了Java在金融、电信、制造等领域日益广泛的应用,如清华大学计算机系利用Java、XML和Web技术研制开发了多个软件平台,东方科技的TongWeb、中创的Inforweb等J2EE应用服务器。由此可见,在巨大市场需求下,企业对于Java人才的渴求已经是不争的事实。你问我火了这么多年的Java语言的发展前景怎么样?那来看看吧Java在WEB、移动设备以及云计算方面前景广阔,随着云计算以及移动领域的扩张,更多的企业在考虑将其应用部署在Java平台上。无论是本地主机,公共云,Java都是目前最适合的选择。;另外在Oracle的技术投资担保下,Java也是企业在云应用方面回避微软平台、在移动应用方面回避苹果公司的一个最佳选择。Java可以参与制作大部分网络应用程序系统,而且与如今流行的WWW浏览器结合很好,这一优点将促进Java的更大范围的推广。因为在未来的社会,信息将会传送的更加快速,这将推动程序向WEB程序方向发展,由于Java具有编写WEB程序的能力,并且Java与浏览器结合良好,这将使得Java前景充满光明的发展。Python的发展前景:Python程序员的发展前景是怎样的?随着Python的技术的流行, Python在为人们带来工作与生活上的便捷后,关注者们开始慢慢关心Python的发展前景与方向。从自身特性看Python发展Python自身强大的优势决定其不可限量的发展前景。Python作为一种通用语言,几乎可以用在任何领域和场合,角色几乎是无限的。Python具有简单、易学、免费、开源、可移植、可扩展、可嵌入、面向对象等优点,它的面向对象甚至比java和C#、.net更彻底。它是一种很灵活的语言,能帮你轻松完成编程工作。强大的类库支持,使编写文件处理、正则表达式,网络连接等程序变得相当容易。能运行在多种计算机平台和操作系统中,如各位unix,windows,MacOS,OS/2等等,并可作为一种原型开发语言,加快大型程序的开发速度。从企业应用来看Python发展Python被广泛的用在Web开发、运维自动化、测试自动化、数据挖掘等多个行业和领域。一项专业调查显示,75%的受访者将Python视为他们的主要开发语言,反之,其他25%受访者则将其视为辅助开发语言。将Python作为主要开发语言的开发者数量逐年递增,这表明Python正在成为越来越多开发者的开发语言选择。目前,国内不少大企业都已经使用Python如豆瓣、搜狐、金山、腾讯、盛大、网易、百度、阿里、淘宝、热酷、土豆、新浪、果壳等;国外的谷歌、NASA、YouTube、Facebook、工业光魔、红帽等都在应用Python完成各种各样的任务。从市场需求与薪资看Python发展Python得到越来越多公司的青睐,使得Python人才需求逐年增加,从市场整体需求来看,Python在招聘市场上的流行程度也是在逐步上升的,工资水平也是水涨船高。据统计Python平均薪资水平在12K,随着经验的提升,薪资也是逐年增长。学习Python的程序员,除去Python开发工程师、Python高级工程师、Python自动化测试外,也能够朝着Python游戏开发工程师、SEO工程师、Linux运维工程师等方向发展,发展方向较为多元化。随着Python的流行,带动的是它的普及以及市场需求量,所以现在学习Python是个不错的时机。区块链的发展前景:区块链开发 ? 155---0116---2665 ?可是区块链技术到底是什么,大多数人都是模糊没有概念。通俗来讲,如果我们把数据库假设成一本账本,读写数据库就可以看做一种记账的行为,区块链技术的原理就是在一段时间内找出记账最快最好的人,由这个人来记账,然后将账本的这一页信息发给整个系统里的其他所有人。区块链技术也称分布式账本(或账簿)技术,属于互联网数据库技术,由参与者共同完成数据库记录,特点是去中心化和公开透明。此外,在每个区块的信息写入并获得认可后,整个区块链数据库完整保存在互联网的节点中,难以被修改,因此数据库的安全性极高。人们普遍认为,区块链技术是实现数字产品(如货币和知识产权)快速、安全和透明地对等(P2P)转账或转让的重要手段。在以色列Zen Protocol公司,区块链应用软件开发专家阿希尔·曼宁介绍说,他们公司正在开发Zen区块链平台,其将用于支持金融产品在无中介的环境下自动和自由交易。通常,人们将钱存放在银行,依靠银行管理自己的资金。但是,在支配资金时往往会受到银行规定的限制,或在汇款时存在耗时长、费用高等问题。区块链技术平台将让人们首次拥有自己管理和支配钱财的能力,他相信去中心化金融管理体系具有广阔的市场,有望极大地改变传统的金融市场。2018年伊始这一轮区块链的热潮,主要起源于虚拟货币的炒作热情。站在风口,区块链技术被认为是继蒸汽机、电力、互联网之后,下一代颠覆性的核心技术。很多人不禁要问“区块链又和比特币又是什么关系?”记者查询了大量资料发现,比特币2009年被一位名叫中本聪的人提出,之后比特币这套去中心化的机制一直稳定运行,这引起很多人对这套历史上并不存在的运行机制强烈关注。于是人们把从比特币技术抽象提取出来的技术运用于其他领域,称之为区块链。这过程就好像人们先发明了面条,然后人们发现其背后面粉不仅可以做面条还可以做馒头、面包。比特币是面条,区块链是面粉。也就是说,区块链和比特币的关系即比特币算是区块链技术的一种应用,或者说一种使用了区块链技术的产品形态。而说到区块链不得不说的就是ICO,它是一种公开发行的初始数字货币。对于投资人来说,出于对市场信号的敏感和长期关注价值投资项目,目前炙手可热的区块链也成为诸多投资人关注的新兴项目之一。“区块链对于我们来说就是省去了中间环节,节约了交易成本,节省了交易时间,但是目前来看各方面环境还不够成熟,有待观望。”一位投资人这样说道。记者发现,在春节期间,不少互金圈的朋友熬夜到凌晨进入某个探讨区块链的微信群热聊,此群还吸引了不少知名人士,诸如明星加入,同时还有大咖在群里解读区块链的投资方式和未来发展等等。一时间,关于区块链的讨论群接二连三出现,也引发了各个行业对区块链的关注。出于对于区块链技术懵懂的状态,记者追问了身边的一些互金圈的朋友,为何如此痴迷区块链?多数朋友认为“区块链能赚钱,抱着试试看的心态,或许能像之前比特币一样从中获取收益。”显然,区块链技术具有广阔的应用潜力,但是在其逐步进入社会改善民众生活的过程中,也面临许多的问题,需要积极去寻求相应的对策,最终让其发挥出潜力。只有这样,10年或20年后人们才能真正享受区块链技术创造的美好环境。人工智能的发展前景:人工智能产业是智能产业发展的核心,是其他智能科技产品发展的基础,国内外的高科技公司以及风险投资机构纷纷布局人工智能产业链。科技部部长万钢3月10日表示,加快实施新一代人工智能科学基础的关键技术系统集成研发,使那些研发成果尽快能够进入到开放平台,在开放使用中再一次把它增强完善。万钢称,马上就要发布人工智能项目指南和细则,来突破基础前沿理论关键部分的技术。人工智能发展趋势据前瞻产业研究院《人工智能行业市场前瞻与投资战略规划分析报告》指出,2017年中国人工智能核心产业规模超过700亿元,随着国家规划的出台,各地人工智能相关建设将逐步启动,预计到2020年,中国人工智能核心产业规模将超过1600亿元,增长率达到26.2%。报告认为,从产业投资回报率分析,智能安防、智能驾驶等领域的快速发展都将刺激计算机视觉分析类产品的需求,使得计算机视觉领域具备投资价值;而随着中国软件集成水平和人们生活水平的提高,提供教育、医疗、娱乐等专业化服务的服务机器人和智能无人设备具备投资价值。人工智能现状当前,人工智能受到的关注度持续提升,大量的社会资本和智力、数据资源的汇集驱动人工智能技术研究不断向前推进。从发展层次来看,人工智能技术可分为计算智能、感知智能和认知智能。当前,计算智能和感知智能的关键技术已经取得较大突破,弱人工智能应用条件基本成熟。但是,认知智能的算法尚未突破,前景仍不明朗。今年,随着智力资源的不断汇集,人工智能核心技术的研究重点可能将从深度学习转为认知计算,即推动弱人工智能向强人工智能不断迈进。一方面,在人工智能核心技术方面,在百度等大型科技公司和北京大学、清华大学等重点院校的共同推动下,以实现强人工智能为目标的类脑智能有望率先突破。另一方面,在人工智能支撑技术方面,量子计算、类脑芯片等核心技术正处在从科学实验向产业化应用的转变期,以数据资源汇集为主要方向的物联网技术将更加成熟,这些技术的突破都将有力推动人工智能核心技术的不断演进。工业大数据2022 年我国工业大数据有望突破 1200 亿元, 复合增速 42%。 工业大数据是提升制造智能化水平,推动中国制造业转型升级的关键动力,具体包括企业信息化数据、工业物联网数据,以及外部跨界数据。其中,企业信息化和工业物联网中机器产生的海量时序数据是工业数据的主要来源。工业大数据不仅可以优化现有业务,实现提质增效,而且还有望推动企业业务定位和盈利模式发生重大改变,向个性化定制、智能化生产、网络化协同、服务化延伸等智能化场景转型。预计到 2022 年,中国工业大数据市场规模有望突破 1200亿元,年复合增速 42%。IT的未来是人工智能这是一个指数级增长的时代。过去几十年,信息技术的进步相当程度上归功于芯片上晶体管数目的指数级增加,及由此带来的计算力的极大提升。这就是所谓的摩尔定律。在互联网时代,互联的终端数也是超线性的增长,而网络的效力大致与联网终端数的平方成正比。今天,大数据时代产生的数据正在呈指数级增加。在指数级增长的时代,我们可能会高估技术的短期效应,而低估技术的长期效应。历史的经验告诉我们,技术的影响力可能会远远的超过我们的想象。未来的计算能力人工智能需要强大的计算能力。计算机的性能过去30年提高了一百万倍。随着摩尔定律逐渐趋于物理极限,未来几年,我们期待一些新的技术突破。先谈一下类脑计算。传统计算机系统,长于逻辑运算,不擅长模式识别与形象思维。构建模仿人脑的类脑计算机芯片,我们今天可以以极低的功耗,模拟100万个神经元,2亿5千万个神经突触。未来几年,我们会看到类脑计算机的进一步的发展与应用随着互联网的普及、传感器的泛在、大数据的涌现、电子商务的发展、信息社区的兴起,数据和知识在人类社会、物理空间和信息空间之间交叉融合、相互作用,人工智能发展所处信息环境和数据基础发展了巨大的变化。伴随着科学基础和实现载体取得新的突破,类脑计算、深度学习、强化学习等一系列的技术萌芽预示着内在动力的成长,人工智能的发展已进入一个新的阶段。发展发展前景好,代表你现在学习会比后来者起步快,占有更大的优势,当然,你也要明白兴趣是最好的老师,选择自己感兴趣的相信你学的会更加而牢固。记住,最重要的一点:方向最重要!!!希望大家多多关注. ,加微信zhanglindashuju 可以获取更多资料哦作者:失色的瞳孔链接:https://juejin.im/post/5b1a6531e51d45067e6fc24a来源:掘金著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

孟志昂 2019-12-02 01:45:13 0 浏览量 回答数 0

问题

企业运营对DevOps的「傲慢与偏见」

忆远0711 2019-12-01 21:32:29 9823 浏览量 回答数 0
阿里云大学 云服务器ECS com域名 网站域名whois查询 开发者平台 小程序定制 小程序开发 国内短信套餐包 开发者技术与产品 云数据库 图像识别 开发者问答 阿里云建站 阿里云备案 云市场 万网 阿里云帮助文档 免费套餐 开发者工具 SSL证书 小程序开发制作 视频内容分析 企业网站制作 视频集锦 代理记账服务 2020阿里巴巴研发效能峰会 企业建站模板 云效成长地图 高端建站 2020中国云原生 阿里云云栖号