IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 大数据 -> Elasticsearch原理与实现(二) -> 正文阅读

[大数据]Elasticsearch原理与实现(二)

概述

字段数据类型

通过映射类型的properties字段,可以定义映射类型包含的字段及其数据类型。
Elasticsearch支持的数据类型包括字符串、数值、日期、布尔、二进制、范围等核心数据类型,还支持数组、对象等衍生类型,也支持嵌套、关联、地理信息等特殊类型。由于衍生类型和特殊类型基本都是从核心类型派生而来,所以下面先介绍一下核心数据类型。

核心类型

核心数据类型是字段数据类型的基础,它们涵盖了大多数文档字段的应用场景。核心类型可以分为字符串、数值、日期、布尔等几种大的类型,每种大的类型下可能会包含一些更具体的数据类型。

字符串类型

字符串类型包括text和keyword两种类型,两者的区别在于text类型在存储前会做词项分析,而keyword类型则不会。所以text类型的字段可以通过analyzer参数设置改字段的分词器,而keyword类型字段则没有这个参数。由于词项分析,text类型字段在编入索引后可通过词项做检索,但不能通过字段整体值做检索;而keyword类型字段则刚好相反,只能通过字段整体值来做检索而不能用词项做检索。所以text类型的字段一般用于存储全文数据,比如日志信息、文章正文、邮件内容等;而keyword类型则用于存储结构化的文本数据,如邮编、地址、电话等。
由于text类型存储的是全文数据,所以它编入索引的信息包括文档ID、词频、词序等信息,而keyword类型则只编入文档ID。当然,这可以通过index_option参数修改。在存储方面,keyword类型默认就支持通过文档机制保存字段原始值,可通过doc_values参数关闭这个机制。text类型则不支持文档值机制,所以text类型不能参与文档排序、过滤、聚集等操作,除非打开它的fielddata机制。

数值类型

数值类型对应一个具体的数字值,例如1024、3.14等。Elasticsearch支持包括整型、浮点类型在内的8种数值类型,它们的主要区别体现的数值精确度上,具体见表2-4。
在这里插入图片描述
在这些类型中比较特殊的一类是scaled_float,它虽然是浮点数据类型,但在存储上却是使用long类型来表示。其基本思想是通过一个换算系数将浮点数放大为整型再保存,例如设置3.14的换算系数为100,则换算结果为3.14×100=314,最终保存的值就是314。由于使用整型保存浮点数不仅不会损失精度还能提升运算效率,所以非常适合小数位数固定的数值,比如货币金额通常就只有两个小数位。设置scaled_float的换算系数时可使用scaling_factor,例如
在这里插入图片描述
对应整型数据类型来说,应该在满足需求的前提下选择尽可能小的数据类型,这对于提升索引和搜索性能都有帮助。如果不清楚最终数值的范围,可以不显示设置他们的类型而由Elasticsearch自主判断,以防止实际数值范围溢出。

日期类型

Elasticsearch有两种日期类型,分别是date核date_nanos。由于JSON并没有日期类型,所以这两种类型在文档中表现处理的仍然是带有日期格式的字符串。但在Elasticsearch内部存储它们时,会将他们转换为该日期与计算机纪元(1970年1月1日0点)的时间差值。其中,date类型会按毫秒计算差值,而date_nanos则会按纳秒计算差值。由于Elasticsearch在实现上使用long类型保存这个差值,这使得date_nanos类型能够保存的时间最多只能到2262年。所以在使用date_nanos类型时,要注意时间范围是否超标。
不管是哪一种日期类型,它们都必须满足一定的格式要求。如果没有指定格式默认会使用ISO 8601定义的标准时间格式,类似于“yyyy-MM-ddTHH:mm:ss”的形式。当然,这种格式有比较严格的定义,可以在相关文档中找到它们的规范。除此之外,默认格式也支持使用毫秒数直接表示日期。通过format参数还可以自定义日期格式,支持使用类似“yyyy-MM-ddTHH:mm:ss”的JODA格式来描述。相信有一定Java开发经验的读者应该不难理解,这里不再赘述。除此之外,Elasticsearch还内置了一组常用日期格式,可直接使用这些日期格式的名称来定义日期。这些日期格式非常多,详细请参考:https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-date-format.html。

布尔类型

布尔类型的类型关键字是boolean,它只有两个值,即true和false。但也接收以字符串描述的true和false,即使用 "true" 和 "false" 也是合法的。

字节类型

字节类型接收以Base64编码后表示的二进制字节流,所以尽管它的类型是字节类型,但在文档中它表现处理的仍然是字符串。字节类型的字段在默认情况下不会被存储,也不会被检索到。

范围类型

范围类型要求字段的值描述的是一个数值、日期或IP地址的范围,添加文档时可以使用gte、gt、lt、lte分别表示大于等于、大于、小于、小于等于。数值范围类型包括integer_range、float_range、long_range、double_range,日期范围类型和IP范围类型分别为date_range和ip_range。例如在示例2-9中先定义了age_range字段的类型为integer_range,然后又添加了一个age_range范围为[7, 23)的文档。所以在检索age_range为10时就会返回添加的新文档。
在这里插入图片描述
在使用date_range和ip_range时需要注意它们的格式,对于日期可以使用format定义日期格式,而IP地址除了可以使用上述方式表示以外,还可以使用CIDR表示法描述一个网段。

衍生类型

衍生类型从核心类型衍生而来,包括数组和对象两种。严格来说,它们并不是独立的数据类型,因为它们并不像核心数据类型那样有专门的类型名称,而是通过特定的JSON格式确认它们的类型。

数组

如果要定义一个字段为数组类型,不需要使用类似array这样的名称声明它的类型,而是通过在添加文档时使用“[]”来确认该字段为数组。Elasticsearch也没有定义array这种数据类型,数组是在核心数据类型基础上的一种扩展。只要字段声明为某种核心数据类型,那么它就可以接收以“[]”表示的数组。惟一的限制就是数组中的元素必须是同一种类型,或者它们至少可以转换为同一种类型。如果在索引定义中声明了属性的数据类型,则数组元素的类型必须要与这种类型一致,或者可以转换为这种类型。例如:
在这里插入图片描述
在示例2-10中,["12","2"]虽然为字符串的数组,但由于它们可以转换为整型,所以可以赋值给整型字段。

对象

与数组类似,Elasticsearch中也没有定义object这种数据类型,它是在添加文档时使用“{}”的格式来确认字段类型为对象。例如:
在这里插入图片描述
在示例2-11中,address就是一个对象,包含了country和city两个字段。与数组类型不同的是,对象类型在定义索引的映射关系时可以声明。具体方式是使用嵌套的properties属性,例如在示例2-11中的colleges索引可以这样定义:
在这里插入图片描述

多数据类型

有些文档字段可能经常会以不同的方式检索,如果文档字段只以一种方式编入索引,检索性能就会受到影响。比如文章的标题,在多数情况下可能是通过文章标题中的词项做检索,但在标题比较短并且知道整个标题内容时也是有可能使用整个标题做检索的。如果将标题字段的类型设置为text,那么标题在编入索引时就会被提取词项而不能使用整个标题做检索,而如果设置为keyword则不能使用词项做检索。事实上更为重要的是text类型并不支持文档值机制,所以通过text类型做排序或聚集就必须开启fielddata机制,而这种机制对于内
存的消耗又非常大。
所以针对字符串类型text和keyword,Elasticsearch专门提供了一个用于配置字段多数据类型的参数fields,它能让一个字段同时具备两种数据类型的特征。示例2-13就是将articles索引的title字段设置为两种数据类型:
在这里插入图片描述
在上图中,title字段的类型被设置为text,同时通过fields参数又为该字段添加了两个子字段。其中一个子字段名称为raw,它的类型被设置为keyword类型;另一个子字段名称为length,它的类型则为token_count。使用fields设置的子字段,在添加文档时不需要单独设置值,它们与title共享相同的字段值,只是会以不同方式处理字段值。同样,在检索时,它们也不会单独显示在结果中。所以它们一般只是在检索中以查询条件的形式出现,以减少检索时的性能开销。例如对于title.raw来说,title字段在编入索引时会将字段值做分析并提取词项,而title.raw则按keyword类型将整个值编入索引。所以如果需要根据词项做检索时应使用title字段,而如果需要使用整个值做检索或是在排序和聚集时则可以使用title.raw字段。在默认情况下,如果没有明确定义字符串类型时,添加到索引中的字符串都会以示例2-13的形式设置为多类型。
再来看另外一个字段title.length,它被设置为一种新的数据类型token_count。这种数据类型保存的值为整型,但实际接收的内容却是title字段的字符串。它会将字符串做分析并提取词项,然后将词项的数量保存下来,所以token_count类型字段必须要通过analyzer参数设置提取词项使用的分析器。由于title.length字段也是通过fields参数添加进来的,所以它在检索结果中也不会出现。需要注意的是,即使token_count类型不是通过fields参数添加进来的字段,它在检索结果的_source字段中仍然是原始的字符串,因为_source字段保存的是源文档而不是字段实际编入索引的值。如果一定要查看token_count类型字段保存的实际值,可以使用第4章第4.4.3节介绍的docvalue_fields查询方式。

分片与复制

全文检索面对的文档数量往往十分惊人,因为这些文档一般都来自访问流量巨大的互联网应用。比如,搜索引擎要处理的网页数据,在线交易系统每天产生的订单等。即便是在业务数据并不多的普通应用中,它们产生的日志文档容量往往也十分庞大。如果这些文档都存储在Elasticsearch中,Elasticsearch就必须要解决海量文档存储的问题。这不仅是要解决文档能够存的下的问题,还要保证它们不会因为故障而丢失,同时还要保证文档的检索速度尽可能不受文档数量增加的影响。

分片与集群

解决大数据存储的通用方案称为分片(Shard),它的核心思想是将数据分解成大小合适的片段,然后再将它们存储到集群中不同的节点上。这样一来,数据存储的容量从理论上来说就没有上线了。因为在数据量增加时,只需要像集群中添加新的节点就可以增加整体容量了。数据分片带来的收益不仅体系在数据存储上,对于数据处理来说也可以大幅提升性能和吞吐量。这是因为在现有磁盘技术条件下,磁盘读写速度与CPU处理能力不在一个数量级上,所以硬盘玩玩是数据处理最大瓶颈。所以,即使多个CPU或多个线程并发处理数据,只要处理的数据在同一个磁盘上,数据处理的速度也不会得到显著提升。在使用数据分片技术后,数据会被散列到不同机器的磁盘上,数据的读写也就被分散到不同的磁盘上,这会显著提升数据处理的速度。大数据处理开源框架Hadoop中的HDFS和MapReduce正是基于这种思想,实现了在短时间内处理大量数据的功能。Elasticsearch作为一种全文检索引擎,显然也有必要考虑大数据的问题,所以Elasticsearch在设计之初就支持文档分片。因为Elasticsearch支持分片,所以它存储文档的容量在理论上没有上限。也正是从这个意义上,它才被很多文献归类为一种数据库,一种基于文档的NoSQL数据库。
分片的基础是要创建集群,Elasticsearch创建集群非常简单,只要集群中的节点在相互连接的网络中,并且具有相同的集群名称即可。Elasticsearch集群名称在配置文件中指定,在安装路径的config目录下找到elasticsearch.yml文件,其中的cluster.name就是配置集群名称的参数,默认名称为elasticsearch。所以在一个局域网内部创建Elasticsearch集群非常简单,只要在不同的机器上直接运行elasticsearch命令即可,甚至不需要修改配置文件。但在学习Elasticsearch时,如果想要在单台机器上创建一个集群,则需要在elasticsearch.yml文件中添加配置:“node.max_local_storage_nodes:2”。这将允许在单台机器启动多个Elasticsearch实例,否则在单机启动多个Elasticsearch实例时会报错。当启动好多个实例后,可通过_nodes接口查看节点情况。在Kibana控制台中执行“GET _nodes”命令,可在返回结果中看到如下信息:
在这里插入图片描述
创建了Elasticsearch集群后,就需要确定索引分片的数量。分片一般会均匀地分散到集群的不同节点上,这就将存储和检索负载分散到集群的不同节点上。索引分片数量是在创建索引时通过number_of_shards参数设置的,例如在示例2-15中创建的test索引,分片数量为10:
在这里插入图片描述
在索引定义好分片数量后,当有新的节点加入集群时,Elasticsearch会将分片均衡地散列到新的节点。例如,索引分片数量为2,当集群中只有一个节点A时,这些分片将全部位于节点A上;而当有节点B加入到集群中时,Elasticsearch会动态地将其中一个分片复制到节点B上。这也意味着如果索引的分片数量为1,那么这个索引未来将无法扩容。

路由

分片解决了海量文档存储的问题,但也引入了一个新的问题,那就是如何确定文档应该存储到哪个分片。在Elasticsearch中,确定文档存储在哪一个分片中的机制被称为路由(Routing)。计算文档路由的具体运算公司如下:

shard_num = hash(_routing)% num_primary_shards  (2-1)

上面公司中,shard_num为分片序号,hash为散列函数,_routing为路由参数,而num_primary_shards则是一个索引的主分片数量。这里之所以使用主分片主要是为了区分副本分片,即在运算是并不包含副本分片数量。决定一份文档最终存储在哪一个分片上,最关键的参数就是_routing。在默认情况下,文档的_routing参数是文档ID,也就是前面介绍的元字段_id。如果想要修改路由参数,可以通过在添加或检索文档时设置routing参数。从负载均衡的角度来看,routing参数的值越分散,文档分散的越均匀。所以选择合适的routing无论对文档添加还是对文档检索,都会有非常显著的性能提升。下面是设置routing自定义规则的例子。
在这里插入图片描述
为了提升检索效率,Elasticsearch在检索文档时,并不会将所有分片整合到一起做检索,而是先根据路由规则路由到具体分片,然后再在分片上根据检索条件查找文档。所以如果文档添加时的路由规则与文档检索时的路由规则不相同,在检索文档时就有可能被路由到错误的分片上,从而导致检索失败。一种比较常见的错误情况就是在文档添加时使用了自定义的路由规则,而在文档检索时忘记使用路由规则。为了避免这种情况的发生,可以在创建索引时将文档路由参数设置为强制要求,例如示例2-17中test索引的路由参数设置为强制:
在这里插入图片描述
在路由参数设置为强制之后,对文档CRUD操作都必须要指定routing参数,否则在执行请求时将报错误。
由于路由选择对于索引性能的影响很大,往往选择的routing参数看似分散但却会路由到相同的分片。为了解决这个问题,Elasticsearch又引入了另一个分区参数来平衡路由运算,这就是routing_partition_size。引入这个参数后,路由运算公式变为
在这里插入图片描述
在添加了分区参数以后,分片编号同时由路由参数_routing和索引_id字段共同决定,这也就加大分片均衡的可能性。routing_partition_size参数必须大于1并且小于主分片数量,它的默认值1代表不会使用式(2-2)计算分片编号。当使用式(2-2)计算分片编号时,需要按示例2-17的方式将索引路由参数设置为强制,同时也不能再使用join类型字段构建父子关系。

容量规划

文档所在分片除了由routing参数决定以为,索引分片数量也是其中一个重要的决定因素。按照公式(2-1)所示,在索引分片数量发生变化时,即使routing参数不变,最终的分片位置也会发送变化。如果在运行时索引分片数量发生变化,为了保证文档存储和检索都能路由到正确的分片,已经存储到分片中的文档就必须按公式(2-1)做分片的重新路由。这个过程在Elasticsearch中叫重新索引(Reindex),显然当分片中已经存储了大量文档时,这将是一个非常耗费资源的过程。
为了避免重新索引导致的性能开销,Elasticsearch对索引分片数量做了一个严格的限制,这就是索引分片数量一旦在创建索引时确定后就不能在修改。这虽然解决了重新索引问题,但索引的存储容量也被分片数量、节点存储容量限制死了。节点存储容量决定了分片容量的上限,而索引总容量这是单个分片容量与分片数量的乘积。从性能角度考虑,分片太大显然会降低检索速度,所以单个分片的容量也不能过大,需要根据用户对检索性能的要求估算单个分片的容量上限。尽管最好的办法是将分片平均分片到不同的节点上,但如果节点存储容量大于单分片容量上限时,也可以考虑在一个节点上存储多个分片。尽管如此,还是意味着索引存储容量存在上限,所以在创建索引时有必要对容量预先做好规划。如果用户在容量规划时低估了文档容量,那么索引将无法通过扩容来支持更多的文档。
索引容量规划主要是根据一些已知条件规划分片数量,这些已知条件主要包括文档存储整体容量和检索性能要求两个方面。通过检索性能要求可以估算出每个分片的最大容量,再使用整体容量除以分片大小就可以估算出分片数量。文档整体容量有时可能无法估算,比如说日志文件每天都在产生,数量只可能越来越多,不可能估算出上限来。这种情况下可以取一个固定的时间段,比如一天或是一个月,每隔这样一段时间就创建一个新的索引出来。由于固定时间段内的文档数量可估算,所以分片数量也就可以预先估算。本书第3章3.1.1节介绍的_rollover接口,以滚动别名的方式给出解决这种问题的一个备选方案。
事实上,无论容量规划得多科学依然不能完全避免文档实际存储量与索引容量不相符的情况。在这种情况下,惟一可行的办法就是创建新的索引,再将原索引中的文档存储到新的索引中。Elasticsearch针对这种情况提供了三个接口,即_split接口、_shrink接口和_reindex接口。这三个接口都没有修改原索引容量的能力,而是通过创建新索引的方法间接改变索引容量,但它们在性能上比手工创建索引和复制文档还是要好一些。

副本

分片在解决了Elasticsearch文档存储容量问题的同时,也提升了文档处理的性能和吞吐量,但并不能解决容灾容错等高可用性问题。也就是说当集群存储分片的节点发生故障,分片技术并不能保证文档存储、检索等服务依然可用,更不能保证分片中的数据不丢失。为了解决这个问题,Elasticsearch在存储上又引入了另一项称为副本(Replica)的技术。
副本是主分片的复制品,它与主分片的数据完全一致,能够在主分片故障时迅速恢复数据。所以主分片与副本分片永远不会在同一节点上,因为这样对于数据恢复没有任何意义。在默认情况下,Elasticsearch为每个索引都设置了1个副本分片,这意味着集群中应该至少有两个节点。如果集群中只有一个节点,副本分片就永远不会被创建,这时Elasticsearch就会将集群健康状态设置为黄色。索引的副本分片数量可以通过number_of_replicas参数设置,例如:
在这里插入图片描述
在创建了示例2-18中的索引后,可使用“GET _cat/shards”命令查看集群中的分片情况。test索引的主分片为10个,每个主分片有2个副本分片,所以总共是30个分片。除了使用number_of_replicas设置固定的副本分片以外,还可以根据节点数量使用auto_expend_replicas参数设置动态扩展副本分片。这个参数的格式为“-”,如“1-10”代表副本分片数量是1~10个,而“0-all”中all代表所有节点数量。与主分片不同的,副本分片的数量在索引创建之后可以随时动态更改。

客户端API概览

Elasticsearch提供了丰富的客户端API操作和访问文档,支持Java、JavaScript、Groovy、.NET、PHP、Perl、Python、Ruby等多种语言。但Elasticsearch最基本的访问方式还是通过REST接口,以HTTP协议的形式操作文档数据。除此之外,Elasticsearch还内置一种称为Painless的脚本语言,可以在API中使用。本节将从总体上介绍REST接口和Painless脚本语言,同时也会简要介绍一下基于Java语言的API。

REST接口

REST可以理解为一种架构风格,它核心的思想是认为一切都是资源,而应用程序则是通过更改资源的状态实现具体功能。REST中的资源可以理解为数据,并且以URI为惟一标识。所以构建REST风格的URI,一个重要原则就是它们应该都是名词。
Elasticsearch的主要资源就是索引、映射类型和文档,它们在Elasticsearch定义的URI中是有次序的。例如在“/users/doc/1”这个URI中,users为索引名,doc为类型名,而1则是文档的ID。在版本7中,映射类型已经被提升为一种内置资源,用户不能再自定义映射类型名称。内置资源要么以下划线“”开头,要么以“.”开头,一般都是一些具有特别用途的资源。除了映射类型_doc以外,Elasticsearch提供的所有接口也都是以下划线""开头的,例如_search、_cat、_cluster等。
在REST中对资源的操作是通过HTTP的七种请求方法完成的,即POST、PUT、GET、DELETE、HEAD、OPTIONS、TRACE。但常用的请求方法一般只有4种,即POST、PUT、GET、DELETE。简单来说,POST可以理解为新增资源,PUT为新增或修改资源,GET为查询资源,DELETE为删除资源。具体到Elasticsearch中,创建一个索引可以使用PUT请求,如PUT test代表创建一个名为test的索引,“PUT test/_doc/1”则代表在test索引的_doc类型下增加ID为1的文档。除此之外,Elasticsearch还支持HEAD请求,用于做存在性查询,即查看一个资源是否存在。
这里要特别说明一下POST和PUT的区别。PUT新增资源是直接通过URI标明资源是哪一个,所以对同一个URI多次PUT请求时,只有第一个请求时执行新增操作;之后所有的PUT请求都可以理解为对资源的更新。所以一般说PUT请求时幂等的,即对同一资源请求多次的结果是一样的。而POST请求则不同,它的URI一般要操作资源的父资源,所以对同一URI请求多次会一直新增资源。举例来说,多次请求“PUT test/_doc_1”相当于一直在更新ID为1的文档,文档的_id字段值为1。而使用POST请求时应该为“POST test/_doc/”,多次请求时会不断向test索引中添加新文档,而每次文档的_id字段都由Elasticsearch自动产生。在Elasticsearch中可以同时使用POST和PUT请求添加一份文档,但通过映射类型添加文档则只能使用POST请求。

多索引

REST接口的URI一般都对应一个资源,但Elasticsearch在操作索引时可以在URI中指定多个,也可以使用通配符匹配多个索引。具体来说,多个索引使用逗号分隔开出现在URI中,可以在索引名称中使用星号匹配任意字符,还可以在URI中使用_all代表所有索引,如下图:
在这里插入图片描述
需要注意的是,并不是所有Elaticsearch接口都支持多索引,在不支持多索引的接口中使用上述格式的URI将会报错。

通用参数

有一些参数对于所有Elasticsearch接口都是有效的,它们一般用于定义接口返回结果的内容和格式定义。比如在接口请求中添加“?pretty=true”,可以让返回的JSON结果以更易读的格式展示出来;添加“?format=yaml”则可以让返回结果以YAML格式展示出来;而添加“?human=true”则会让返回结果字段以更易于人类理解的方式展示。
除了以上参数,还有一个比较有用的参数filter_path。这个参数用于过滤返回结果中的字段,参数值是希望在返回结果中展示的字段路径。例如,如果只想查看返回结果中的_source字段值,那么就可以使用“hits.hits._source”。这是因为在使用_search接口检索文档时,_source字段是在返回结果的hits.hits字段。在讲解聚集查询时,在所有示例中都会使用filter_path参数以过滤聚集结果。

小结

Elasticsearch原理与实现非常重要。索引、映射、文档是Elasticsearch中非常重要的概念,正确理解它们对于学习后面的知识很有帮助。
索引可以理解为文档的容器,文档以索引体现其存在性。未编入索引的文档将不能被检索到,即使它们实际已经存储在Elasticsearch中。映射是文档如何编入索引的映射关系,但并不需要预先定义,可以由Elasticsearch自动生成。文档则是实际存储在Elasticsearch中的数据,是一种半结构化的JSON文档。文档中的全文数据会预先分析并提取词项,词项则会编入索引以提高检索文档的效率。映射类型在Elasticsearch 7中已经被废止,这是改版本中最为重要的一个变化,它引起了许多REST接口发生变化。

  大数据 最新文章
实现Kafka至少消费一次
亚马逊云科技:还在苦于ETL?Zero ETL的时代
初探MapReduce
【SpringBoot框架篇】32.基于注解+redis实现
Elasticsearch:如何减少 Elasticsearch 集
Go redis操作
Redis面试题
专题五 Redis高并发场景
基于GBase8s和Calcite的多数据源查询
Redis——底层数据结构原理
上一篇文章      下一篇文章      查看所有文章
加:2022-04-26 11:47:11  更:2022-04-26 11:51:50 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 2:45:39-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码