NoSQL 数据库
                 MongoDB和Redis


 
目 录
1NoSQL简述... 4
2MongoDB简介... 4
3术语介绍... 5
4MongoDB资源消耗... 6
5交互式shell6
6一般功能... 7
6.1插入... 7
6.2查询... 7
6.3删除... 7
6.4索引... 8
6.5map/reduce. 8
7模式设计... 8
8嵌入与引用... 9
9GridFS. 11
9.1GridFS表示的对象信息... 11
9.2GridFS管理... 12
10Replication(复制)... 13
10.1master-slave模式... 13
10.2replica pairs模式... 13
10.3受限的master-master复制... 14
11Sharding(分片)... 14
11.1sharding介绍... 14
11.2sharding的配置和管理... 15
12Java API简介... 16
13MongoDB实例分析... 17
13.1图片保存在文件系统中... 17
13.2图片保存在数据库中... 19
14MongoDB常用API总结... 23
15Redis简介... 27
15.1Redis特性... 27
16Redis数据类型... 28
16.1String类型... 28
16.2List类型... 28
16.3Set类型... 29
16.4ZSet类型... 29
16.5Hash类型... 29
17All data in memory, but saved on disk. 29
18RedisMaster-Slave模式... 30
19Redis虚拟内存管理... 31
20Redis实例分析... 31
21Redis命令总结... 32
21.1连接操作相关的命令... 32
21.2value操作的命令... 32
21.3String操作的命令... 33
21.4List操作的命令... 33
21.5Set操作的命令... 34
21.6zsetsorted set)操作的命令... 35
21.7Hash操作的命令... 35
21.8持久化... 36
21.9远程服务控制... 36
 


NoSQL 数据库
MongoDB和Redis
1NoSQL简述
CAP(Consistency,Availabiity,Partition tolerance)理论告诉我们,一个分布式系统不可能满足一致性,可用性和分区容错性这三个需求,最多只能同时满足两个。关系型数据库通过把更新操作写到事务型日志里实现了部分耐用性,但带来的是写性能的下降。MongoDB等NoSQL数据库背后蕴涵的哲学是不同的平台应该使用不同类型的数据库,MongoDB通过降低一些特性来达到性能的提高,这在很多大型站点中是可行的。因为MongoDB是非原子性的,所以如果如果应用需要事务,还是需要选择MySQL等关系数据库。
NoSQL数据库,顾名思义就是打破了传统关系型数据库的范式约束。很多NoSQL数据库从数据存储的角度看也不是关系型数据库,而是key-value数据格式的hash数据库。由于放弃了关系数据库强大的SQL查询语言和事务一致性以及范式约束,NoSQL数据库在很大程度上解决了传统关系型数据库面临的诸多挑战。
在社区中,NoSQL是指“not only sql”,其特点是非关系型,分布式,开源,可水平扩展,模式自由,支持replication,简单的API,最终一致性(相对于即时一致性,最终一致性允许有一个“不一致性窗口”,但能保证最终的客户都能看到最新的值)。
2MongoDB简介
mongo取自“humongous”(海量的),是开源的文档数据库──nosql数据库的一种。
MongoDB是一种面向集合(collection)的,模式自由的文档(document)数据库。
面向集合是说数据被分成集合的形式,每个集合在数据库中有惟一的名称,集合可以包含不限数目的文档。除了模式不是预先定义好的,集合与RDBMS中的表概念类似,虽然二者并不是完全对等。数据库和集合的创建是“lazy”的,即只有在第一个document被插入时集合和数据库才真正创建——这时在磁盘的文件系统里才能看见。
模式自由是说数据库不需要知道存放在集合中的文档的结构,完全可以在同一个集合中存放不同结构的文档,支持嵌入子文档。
文档类似于RDBMS中的记录,以BSON的格式保存。BSON是Binary JSON的简称,是对JSON-like文档的二进制编码序列化。像JSON(JavaScript Object Notation)一样,BSON支持在对象和数组内嵌入其它的对象和数组。有些数据类型在JSON里不能表示,但可以在BSON里表示,如Date类型和BinData(二进制数据),Python原生的类型都可以表示。与Protocal Buffers(Google开发的用以处理对索引服务器请求/应答的协议)相比,BSON模式更自由,所以更灵活,但这样也使得每个文档都要保存字段名,所以空间压缩上不如Protocol Buffers。
BSON第一眼看上去像BLOB,但MongoDB理解BSON的内部机制,所以MongoDB可以深入BSON对象的内部,即使是嵌套的对象,这样MongoDB就可以在顶层和嵌套的BSON对象上建立索引来应对各种查询了。
MongoDB可运行在Linux、Windows和OS X平台,支持32位和64位应用,默认端口为27017。推荐运行在64位平台,因为MongoDB为了提高性能使用了内存映射文件进行数据管理,而在32位模式运行时支持的最大文件为2GB。
MongoDB查询速度比MySQL要快,因为它cache了尽可能多的数据到RAM中,即使是non-cached数据也非常快。当前MongoDB官方支持的客户端API语言就多达8种(C|C++|Java|Javascript|Perl|PHP|Python|Ruby),社区开发的客户端API还有Erlang、Go、Haskell......
3术语介绍
数据库、集合、文档
每个MongoDB服务器可以有多个数据库,每个数据库都有可选的安全认证。数据库包括一个或多个集合,集合以命名空间的形式组织在一起,用“.”隔开(类似于JAVA/Python里面的包),比如集合blog.posts和blog.authors都处于"blog"下,不会与bbs.authors有名称上的冲突。集合里的数据由多个BSON格式的文档对象组成,document的命名有一些限定,如字段名不能以"$"开头,不能有".",名称"_id"被保留为主键。
如果插入的文档没有提供“_id”字段,数据库会为文档自动生成一个ObjectId对象作为“_id”的值插入到集合中。字段“_id”的值可以是任意类型,只要能够保证惟一性。BSON ObjectID是一个12字节的值,包括4字节的时间戳,3字节的机器号,2字节的进程id以及3字节的自增计数。建议用户还是使用有意义的“_id”值。
MongoDb相比于传统的SQL关系型数据库,最大的不同在于它们的模式设计(Schema Design)上的差别,正是由于这一层次的差别衍生出其它各方面的不同。
如果将关系数据库简单理解为由数据库、表(table)、记录(record)三个层次概念组成,而在构建一个关系型数据库的时候,工作重点和难点都在数据库表的划分与组织上。一般而言,为了平衡提高存取效率与减少数据冗余之间的矛盾,设计的数据库表都会尽量满足所谓的第三范式。相应的,可以认为MongoDb由数据库、集合(collection)、文档对象(Document-oriented、BSON)三个层次组成。MongoDb里的collection可以理解为关系型数据库里的表,虽然二者并不完全对等。当然,不要期望collection会满足所谓的第三范式,因为它们根本就不在同一个概念讨论范围之内。类似于表由多条记录组成,集合也包含多个文档对象,虽然说一般情况下,同一个集合内的文档对象具有相同的格式定义,但这并不是必须的,即MongoDb的数据模式是自由的(schema-free、模式自由、无模式),collection中可以包含具有不同schema的文档记录,支持嵌入子文档。
4MongoDB资源消耗
考虑到性能的原因,mongo做了很多预分配,包括提前在文件系统中为每个数据库分配逐渐增长大小的文件集。这样可以有效地避免潜在的文件系统碎片,使数据库操作更高效。
一个数据库的文件集从序号0开始分配,0,1...,大小依次是64M,128M,256M,512M,1G,2G,然后就是一直2G的创建下去(32位系统最大到512M)。所以如果上一个文件是1G,而数据量刚好超过1G,则下一个文件(大小为2G)则可能有超过90%都是空的。
如果想使磁盘利用更有效率,下面是一些解决方法:
1. 只建立一个数据库,这样最多只会浪费2G。
2. 每个文档使用自建的“_id”值而不要使用默认的ObjectId对象。
3. 由于每个document的每个字段名都会存放,所以如果字段名越长,document的数据占用就会越大,因此把字段名缩短会大大降低数据的占用量。如把“timeAdded”改为“tA”。
Mongo使用内存映射文件来访问数据,在执行插入等操作时,观察mongod进程的内存占用时会发现量很大,当使用内存映射文件时是正常的。并且映射数据的大小只出现在虚拟内存那一列,常驻内存量才反应出有多少数据cached在内存中。
【按照mongodb官方的说法,mongodb完全由系统内核进行内存管理,会尽可能的占用系统空闲内存,用free可以看到,大部分内存都是作为io cache被占用的,而这部分内存是可以释放出来给应用使用的。】
5交互式shell
mongo类似于MySQL中的mysql进程,但功能远比mysql强大,它可以使用JavaScript语法的命令从交互式shell中直接操作数据库。如查看数据库中的内容,使用游标循环查看查询结果,创建索引,更改及删除数据等数据库管理功能。下面是一个在mongo中使用游标的例子:
> for(var cur = db.posts.find(); cur.hasNext();) {   
... print(tojson(cur.next()));
... }
输出:
{
        "_id" : ObjectId("4bb311164a4a1b0d84000000"),
        "date" : "Wed Mar 31 17:05:23 2010",
        "content" : "blablablabla",
        "author" : "navygong",
        "title" : "the first blog"
}
 
...其它的documents。
6一般功能
6.1插入
客户端把数据序列化为BSON格式传给DB后被存储在磁盘上,在读取时数据库几乎不做什么改动直接把对象返回给客户端,由client完成unserialized。如:
> doc = {'author': 'joe', 'created': new Date('2010, 6, 21'), 'title':'Yet another blog post', 'text': 'Here is the text...', 'tags': ['example', 'joe'], 'comments': [{'author': 'jim', 'comment': 'I disgree'}, {'author': 'navy', 'comment': 'Good post'}], '_id': 'test_id'}
> db.posts.insert(doc)
6.2查询
基本上你能想到的查询种类MongoDB都支持,如等值匹配,<,<=,>, >=,$ne,$in,$mod,$all,$size [1],$exists,$type [2],正则表达式匹配,全文搜索,......。还有distinct(),sort(),count(),skip() [3],group() [4],......。这里列表的查询中很多用法都和一般的RDBMS不同。
[1] 匹配一个有size个元素的数组。如db.things.find({a: {$size: 1}})能够匹配文档{a: ["foo"]}。
[2] 根据类型匹配。db.things.find({a : {$type : 16}})能够匹配所有a为int类型的文档。BSON协议中规定了各种类型对应的枚举值。
[3] 指定跳过多少个文档后开始返回结果,可以用在分页中。如:db.students.find().skip((pageNumber-1)*nPerPage).limit(nPerPage).forEach( function(student) { print(student.name + "

"); } )。

[4] 在sharded MongoDB配置环境中应该应该使用map/reduce来代替group()。
6.3删除
可以像查询一样指定条件来删除特定的文档。
6.4索引
可以像在一般的RDBMS中一样使用索引。提供了建立(一般、惟一、组合)索引、删除索引、重建索引等各种方法。索引信息保存在集合“system.indexes”中。
6.5map/reduce
MongoDB提供了map/reduce方法来进行数据的批处理及聚集操作。和Hadoop的使用类似,从集合中接收输入,结果输出到另一个集合。如果你需要使用group,map/reduce会是个不错的选择。但MongoDB中的索引和标准查询不是使用map/reduce,而是与MySQL相似。
7模式设计
Mongo式的模式设计
使用Mongo有很多种方式,你本能上可能会像使用关系型数据库一样去使用。当然这样也可以工作得很好,但却没能发挥出Mongo的真正威力。Monog是专门设计为富对象模型(rich object model)使用的。
例如:如果你建立了一个简单的在线商店并且把产品信息存储在关系型数据库中,那你可能会有两个像这样的表:
item

title
price
sku

 
item_features

sku
feature_name
feature_value

你进行了范式处理因为不同的物品有不同的特征,这样你不用建立一个包含所有特征的表了。在Mongo中你也可以像上面那样建立两个集合,但像下面这样存储每种物品会更有效。
item : {
       "title" : ,</span> </div> <div> <span>       "price" : <price> ,</span> </div> <div> <span>       "sku" : <sku> ,</span> </div> <div> <span>       "features" : {</span> </div> <div> <span>          "optical zoom" : <value> ,</span> </div> <div> <span>          ...</span> </div> <div> <span>       }</span> </div> <div> } </div> <div> 因为只要查询一个集合就能取得一件物品的所有信息,而这些信息都保存在磁盘上同一个地方,因此大大提高了查询的速度。如果你想插入或更新一种特征,如db.items.update( { sku : 123 } , { "$set" : { "features.zoom" : "5" } } ),也不必在磁盘上移动整个对象,因为Mongo为每个对象在磁盘上预留了空间来适应对象的增长。 </div> <div> <b><font size="6">8<span>嵌入与引用</span></font></b> </div> <div> 以一实例来说,假设需要设计一个小型数据库来存储“学生、地址、科目、成绩”这些信息,那么关系型数据库的设计如图1所示,而key-value型数据库的设计则可能如图2所示。 </div> <div> 图1 关系型的数据库设计 </div> <div> 图2 key-value型的数据库设计 </div> <div> 对比图1和图2,在关系型的数据库设计里划分出了4个表,而在key-value型的数据库设计里却只有两个集合。如果说集合与表一一对应的话,那么图2中应该也有4个集合才对,把本应该是集合的address和scores直接合入了集合students中,原因在于在key-value型的数据库里,数据模式是自由的。 </div> <div> 以scores来说,在关系型的数据库设计中将其单独成一个表是因为student与score是一对多的关系,如果将score合入student表,那么就必须预留最多可能的字段,这会存在浪费,并且当以后新增一门课程时扩展困难,因此一般都会将score表单独出来。而对于key-value型的数据库就不同了,其scores字段就是一个BSON,该BSON可以只有一个for_course,也可以有任意多个for_course,其固有的模式自由特性使得它可以将score包含在内而无需另建一个score集合。 </div> <div> 对于与student为一对一关系的address表也可以直接合入student,无需担心address的扩展性,当以后需要给address新增一个province字段,直接在数据插入时加上这个值即可。 </div> <div> 当然,对于与student成多对多关系course表,为了减少数据冗余,可以将course建立为一个集合,同关系型的数据库设计中类似。 </div> <div> students文档中嵌入了address文档和scores文档,scores文档的“for_course”字段的值是指向courses集合的文档的引用。如果是关系型数据库,需要把“scores”作为一个单独的表,然后在students表中建立一个指向“scores”的外键。所以Mongo模式设计中的一个关键问题就是“是值得为这个对象新建一个集合呢,还是把这个对象嵌入到其它的集合中”。在关系型数据库中为了范式的要求,每个子项都要建一个单独的表,但在Mongo中使用嵌入式对象更有效,所以你应该给出不使用嵌入式对象而单独建一个集合的理由。 </div> <div> 为什么说引用要慢些呢,以上面的students集合为例,比如执行: </div> <div> print( student.scores[0].for_course.name ); </div> <div> 如果这是第一次访问scores[0],那些客户端必须执行: </div> <div> student.scores[0].for_course = db.courses.findOne({_id:_course_id_to_find_}); //伪代码 </div> <div> 所以每一次遍历引用都要对数据库进行一次这样的查询,即使所有的数据都在内存中。再考虑到从客户端到服务器端的种种延迟,这个时间也不会低。 </div> <div> 有一些规则可以决定该用嵌入还是引用: </div> <div> 1. 第一个类对象,也就是处于顶层的,往往应该有自己的集合。 </div> <div> 2. 排列项详情对象应该用嵌入。 </div> <div> 3. 处于被包含关系的应该用嵌入。 </div> <div> 4. 多对多的关系通常应该用引用。 </div> <div> 5. 数据量小的集合可以放心地做成一个单独的集合,因为整个集合可以很快地cached。 </div> <div> 6. 要想获得嵌入式对象的系统级视图会更困难一些。如上面的“Scores”如果不做成嵌入式对象可以更容易地查询出分数排名前100的学生。 </div> <div> 7. 如果嵌入的是大对象,需要留意到BSON对象的4M大小限定(后面会讲到)。 </div> <div> 8. 如果性能是关键就用嵌入。 </div> <div> 下面是一些示例: </div> <div> 1. Customer/Order/Order Line-Item </div> <div> cutomers和orders应该做成一个集合,line-items应该以数组的形式嵌入在order中。 </div> <div> 2. 博客系统 </div> <div> posts应该是一个集合;author可以是一个单独的集合,如果只需记录作者的email地址也可以以字段的方式存在于posts中;comments应该做成嵌入的对象。 </div> <div> <b><font size="6">9GridFS</font></b> </div> <div> <span>    GridFS</span>是MongoDB中用来存储大文件而定义的一种文件系统。MongoDB默认是用BSON格式来对数据进行存储和网络传输。但由于BSON文档对象在MongoDB中最大为4MB,无法存储大的对象。即使没有大小限制,BSON也无法满足对大数据集的快速范围查询,所以MongoDB引进了GridFS。 </div> <div> <b><font size="5">9.1GridFS<span>表示的对象信息</span></font></b> </div> <div> <b>1. </b> <b>文件对象(类</b>GridFSFile <b> </b> <b>的对象</b> <b>)的元数据信息。</b>结构如下 </div> <div> { </div> <div>  "_id" : <unspecified>, <span>                 // unique ID for this file</span> </div> <div>  "filename" : data_string, <span>               // human name for the file</span> </div> <div>  "contentType" : data_string, <span>            // valid mime type for the object</span> </div> <div>  "length" : data_number, <span>               // size of the file in bytes</span> </div> <div>  "chunkSize" : data_number, <span>            // size of each of the chunks. Default is 256k</span> </div> <div>  "uploadDate" : data_date, <span>              // date when object first stored</span> </div> <div>  "aliases" : data_array of data_string, <span>     // optional array of alias strings</span> </div> <div>  "metadata" : data_object, <span>              // anything the user wants to store</span> </div> <div>  "md5" : data_string <span>    //result of running "filemd5" command on the file's chunks</span> </div> <div> } </div> <div> 如下是put进去的一个文件例子: </div> <div> { </div> <div> _id: ObjId(4bbdf6200459d967be9d8e98), </div> <div> filename: "/home/hjgong/source_file/wnwb.svg", </div> <div> length: 7429, </div> <div> chunkSize: 262144, </div> <div> uploadDate: new Date(1270740513127), </div> <div> md5: "ccd93f05e5b9912c26e68e9955bbf8b9" </div> <div> } </div> <div> <b>2. </b> <b>数据的二进制块以及一些统计信息。</b>结构如下: </div> <div> { </div> <div>  "_id": <unspecified>, <span>       // object id of the chunk in the _chunks collection</span> </div> <div>  "files_id": <unspecified>, <span>    // _id value of the owning `files` collection entry</span> </div> <div>  "n": data_number, <span>          // "chunk number" - starting with 0</span> </div> <div>  "data": data_binary (type 0x02), <span>       // binary data for chunk</span> </div> <div> } </div> <div> 因此使用GridFS可以储存富媒体文件,同时存入任意的附加信息,因为这些信息实际上也是一个普通的collection。以前,如果要存储一个附件,通常的做法是,在主数据库中存放文件的属性同时记录文件的path,当查询某个文件时,需要首先查询数据库,获得该文件的path,然后从存储系统中获得相应的文件。在使用GridFS时则非常简单,可以直接将这些信息直接存储到文件中。比如下面的Java代码,将文件file(file可以是图片、音频、视频等文件)储存到db中: </div> <div> 其中该方法的第一个参数的类型还可以是InputStream,byte[],从而实现多个重载的方法。 </div> <div> <b><font size="5">9.2GridFS<span>管理</span></font></b> </div> <div> <span>   MongoDB</span>提供的工具mongofiles可以从命令行操作GridFS。如: </div> <div> <span>     ./mongofiles -host localhost:1727 -u navygong -p 111 put ~/source_file/wnwb.svg</span> </div> <div> <span>   </span>每种语言提供的MongoDB客户端API都提供了一套方法,可以像操作普通文件一样对GridFS文件进行操作,包括read(),write(),tell(),seek()等。 </div> <div> <b><font size="6">10Replication<span>(复制)</span></font></b> </div> <div> <span>    Mongo</span>提供了两种方式的复制:简单的master-slave配置及replica pair的概念。 </div> <div> <span>    </span>如果安全认证被enable,不管哪种replicate方式,都要在master/slave中创建一个能为各个database识别的用户名/密码。认证步骤如下: </div> <div> <span>    slave</span>先在local.system.users里查找一个名为"repl"的用户,找到后用它去认证master。如果"repl"用户没有找到,则使用local.system.users中的第一个用户去认证。local数据库和admin数据库一样,local中的用户可以访问整个db server。 </div> <div> <b><font size="5">10.1master-slave<span>模式</span></font></b> </div> <div> 一个server可以同时为master和slave。一个slave可以有多个master,这种方式并不推荐,因为可能会产生不可预期的结果。 </div> <div> 在该模式中,一般是在两个不同的机器上各部署一个MongDB实例,一个为master,另一作为slave。将MongoDB作为master启动,只需要在命令行输入: </div> <p> </p> <table border="1"> <tbody> <tr> <td valign="top" width="568"> <div> ./mongod --master </div> </td> </tr> </tbody> </table> <p></p> <div> 然后主服务进程将会在数据库中创建一个集合local.oplog.$main,该collection主要记录了事务日志,即需要在slave执行的操作。 </div> <div> 而将MongoDB作为slave启动,只需要在命令行输入: </div> <p> </p> <table border="1"> <tbody> <tr> <td valign="top" width="568"> <div> ./mongod --slave --source <masterhostname>[:<port>] </div> </td> </tr> </tbody> </table> <p></p> <div> port不指定时即使用默认端口,masterhostname是master的IP或master机器的FQDN。 </div> <div> 其他配置选项: </div> <div> --autoresync:自动sync,但在10分钟内最多只会进行一次。 </div> <div> --oplogSize:指定master上用于存放更改的数据量,如果不指定,在32位机上最少为50M,在64位机上最少为 1G,最大为磁盘空间的5%。 </div> <div> <b><font size="5">10.2replica pairs<span>模式</span></font></b> </div> <div> 以这种方式启动后,数据库会自动协商谁是master谁是slave。一旦一个数据库服务器断电,另一个会自动接管,并从那一刻起起为master。万一另一个将来也出错了,那么master状态将会转回给第一个服务器。以这种复制方式启动本地MongoDB的命令如下: </div> <p> </p> <table border="1"> <tbody> <tr> <td valign="top" width="568"> <div> ./mongod --pairwith <remoteserver>  --arbiter <arbiterserver> </div> </td> </tr> </tbody> </table> <p></p> <div> 其中remoteserver是pair里的另一个server,arbiterserver是一个起仲裁作用的Mongo数据库服务器,用来协商pair中哪一个是master。arbiter运行在第三个机器上,利用“平分决胜制”决定在pair中的两台机器不能联系上对方时让哪一个做master,一般是能同arbiter通话的那台机器做master。如果不加--arbiter选项,出现网络问题时两台机器都作为master。命令db.$cmd.findOne({ismaster:1})可以检查当前哪一个database是master。 </div> <div> pair中的两台机器只能满足最终一致性。当replica pair中的一台机器完全挂掉时,需要用一台新的来代替。如(n1, n2)中的n2挂掉,这时用n3来代替n2。步骤如下: </div> <div> 1. 告诉n1用n3来代替n2:db.$cmd.findOne({replacepeer:1}); </div> <div> 2. 重启n1让它同n3对话:./mongod --pairwith n3 --arbiter <arbiterserver> </div> <div> 3. 启动n3:./mongod --pairwith n1 --arbiter <arbiterserver>。 </div> <div> 在n3的数据没有同步到n1前n3还不能做master,这个过程长短由数据量的多少决定。 </div> <div> <b><font size="5">10.3<span>受限的master-master</span><span>复制</span></font></b> </div> <div> Mongo不支持完全的master-master复制,通常情况下不推荐使用master-master模式,但在一些特定的情况下master-master也可用。master-master也只支持最终一致性。配置master-master只需运行mongod时同时加上--master选项和--slave选项。如下: </div> <p> </p> <table border="1"> <tbody> <tr> <td valign="top" width="568"> <div> $ nohup mongod --dbpath /data1/db --port 27017 --master --slave --source localhost:27018 > /tmp/dblog1 & </div> <div> $ nohup mongod --dbpath /data2/db --port 27018 --master --slave --source localhost:27017 > /tmp/dblog2 & </div> </td> </tr> </tbody> </table> <p></p> <div> 这种模式对插入、查询及根据_id进行的删除操作都是安全的。但对同一对象的并发更新无法进行。 </div> <div> <b><font size="6">11Sharding<span>(分片)</span></font></b> </div> <div> <b><font size="5">11.1sharding<span>介绍</span></font></b> </div> <div> MongoDB包括一个自动分片的的模块(“mongos”),从而可以构建一个大的水平可扩展的数据库集群,可以动态地添加和移走机器。如下是一个数据库集群的示意图: </div> <div> mongod:数据库服务器进程,类似于mysqld。 </div> <div> shards:每个shard有一个或多个mongod,通常是一个master,多个slave组成replication。数据由集合按一个预定的顺序划分,某一个范围的数据被放到一个特定的shard中,这样可以通过shard的key进行有效的范围查询。 </div> <div> shard keys:用于划分集合,格式类似于索引的定义,也是把一个或多个字段作为key,以key来分布数据。如:{ name : 1 (1代表升序,-1代表降序)}、{ _id : 1 }、{ lastname : 1, firstname : 1 }、{ tag : 1, timestamp : -1 }。如果有100万人同名,可能还需要划分,因为放到一个块里太大了,这时定义的shar key不能只有一个name字段了。划分能够保证相邻的数据存储在一个server(当然也在相同的块上)。 </div> <div> chunks:是一个集合里某一范围的数据,(collection, minkey, maxkey)描述了一个chunk。块的大小有限定,当块里的数据超过最大值,块会一分为二。如果一个shard里的数据过多(添加shard时,可以指定这个shard上可以存放的最大数据量maxSize),就会有块迁移到其它的shard。同样,当添加新的server时,为了平衡各个server的负载,也会迁移chunk过去。 </div> <div> config server(配置服务器):存储了集群的元信息,包括每一个shard、一个shard里的server、以及每一个chunk的基本信息。其中主要是chunk的信息,每个config server中都有一份所有chunk信息的完全拷贝。使用两阶段提交协议来保证配置信息在config server间的一致。mongos:可以认为是一个“数据库路由器”,用以协调集群的各个部分,使它们看起来像一个系统。mongos没有固定的状态,可以在 server需要的时候运行。mongos启动后会从config server里取出元信息,然后接收客户请求,把请求路由到合适的server,得到结果后送回客户。一个系统可以有多个mongos例程,每个例程都需要内存来存储元信息。例程间不需协同工作,每个mongos只需要协同shard servers和config servers工作即可。当然shard servers间也会彼此对话,也会同config servers对话。 </div> <div> <b><font size="5">11.2sharding<span>的配置和管理</span></font></b> </div> <div> mongod的启动选项中也包含了与sharding相关的参数,如--shardsvr(声明这是一个shard db),--configsvr(声明这是一个config db)。mongos的启动选项--configdb指定config server的位置。下面的链接地址是一个简单的sharding配置例子:http://www.mongodb.org/display/DOCS/A+Sample+Configuration+Session。 </div> <div> <span>    </span>像安全和认证一样,如果要sharding,先要允许一个数据库sharding,然后要指定数据库里集合的分片方式,这些都有相应的命令可以完成。 </div> <div> <b><font size="6">12Java API<span>简介</span></font></b> </div> <div> 要使用Java操作MongoDB,在官网上下载jar包,目前最新的版本是:mongo-2.0.jar。首先介绍一下比较常用的几个类: </div> <div> Mongo:连接服务器,执行一些数据库操作的选项,如新建立一个数据库等; </div> <div> DB:对应一个数据库,可以用来建立集合等操作; </div> <div> DBCollection:对应一个集合(类似表),可能是我们用得最多的,可以添加删除记录等; </div> <div> DBObject接口和BasicDBObject对象:表示一个具体的记录,BasicDBObject实现了DBObject,因为是key-value的数据结构,所以用起来其实和HashMap是基本一致的; </div> <div> DBCursor:用来遍历取得的数据,实现了Iterable和Iterator。 </div> <div> 下面以一段简单的例子说明: </div> <div>   </div> <div> <b><font size="6">13MongoDB<span>实例分析</span></font></b> </div> <div> 下面通过一个实例说明如何用MongoDB作为数据库。该实例中有一个user实体,包含一个name属性,每个user对应一到多个图片p_w_picpath。按照关系型数据库设计,可以设计一个user表和一个p_w_picpath表,其中p_w_picpath表中有一个关联到user表的外键。如果将这两个表对应为两个collection,即p_w_picpath对应的collection中的每一个document都有一个key,其value是该p_w_picpath关联的user。但为了体现MongoDB的效率,即MongoDB是schema-free的,而且支持嵌入子文档,因此在实现时,将一个user发布的p_w_picpath作为该user的子文档嵌入其中,这样只需要定义一个collection,即userCollection。如下图所示: </div> <div> <span>       </span>对于图片等文件,可以存储在文件系统中,也可以存储在数据库中。因此下面分两种情况实现。 </div> <div> <b><font size="5">13.1<span>图片保存在文件系统中</span></font></b> </div> <div> 这种情况下,图片实体中需要记录图片的路径uri,因此Image类的定义如下: </div> <div> 因为在MongoDB中,当保存的对象没有设置ID时,mongoDB会默认给该条记录设置一个ID("_id"),因此在类中没有定义id属性(下同)。 </div> <div> 因为一个user对应多个p_w_picpath,所以在user实体中需要记录对应的p_w_picpath。如下: </div> <div> 在main函数中实现如下功能:首先定义一个user(假设id为1),其对应3张图片,然后将该user插入userCollection中。然后,通过查询查找到该user(根据id),再发布第4张图片,更新该user,然后打印出其信息。部分代码如下: </div> <div> 程序运行后,在控制台打印出的信息如下: </div> <div> 从该结果容易看出,用户user有两个属性“_id”和“Name”,而且ImageList作为其子文档(数组)嵌入其中,该数组中是3个图片,每个图片仍然是bson格式。 </div> <div> <b><font size="5">13.2<span>图片保存在数据库中</span></font></b> </div> <div> 这种情况下,图片实体只需要存储文件名即可,因此Image2类的定义如下: </div> <div>   </div> <div>   </div> <div>   </div> <div>   </div> <div>   </div> <div> User2类和上面类似,如下所示: </div> <div> 实现了类MongoTest2,其功能仍然是一个user对应3个图片,存入数据库中后,通过查询得到该user后,再插入第4幅图片,然后打印出信息。同时为了演示文件的查询,对存入MongoDB中的图片进行了查询并打印出其部分元数据信息。部分代码如下所示: </div> <div>   </div> <div>   </div> <div>   </div> <div> 运行程序,控制台打印出的结果如下: </div> <div>   </div> <div> <b><font size="6">14MongoDB<span>常用API</span><span>总结</span></font></b> </div> <div> <span>Ø </span> <b>类转换</b> </div> <div> 当把一个类对象存到mongoDB后,从mongoDB取出来时使用setObjectClass()将其转换回原来的类。 </div> <div> public class Tweet implements DBObject { </div> <div> <span>    /* ... */ </span> </div> <div> } </div> <div> Tweet myTweet = new Tweet(); </div> <div> myTweet.put("user", "bruce"); </div> <div> myTweet.put("message", "fun"); </div> <div> myTweet.put("date", new Date()); </div> <div> collection.insert(myTweet); </div> <div> //转换 </div> <div> collection.setObjectClass(Tweet.class); </div> <div> Tweet myTweet = (Tweet)collection.findOne(); </div> <div>   </div> <div> <span>Ø </span> <b>默认</b> <b>ID </b> </div> <div> 当保存的对象没有设置ID时,mongoDB会默认给该条记录设置一个ID("_id")。 </div> <div> 当然你也可以设置自己指定的ID,如:(在mongoDB中执行用db.users.save({_id:1,name:'bruce'});) </div> <div> BasicDBObject bo = new BasicDBObject(); </div> <div> bo.put('_id', 1); </div> <div> bo.put('name', 'bruce'); </div> <div> collection.insert(bo); </div> <div>   </div> <div> <span>Ø </span> <b>权限</b> </div> <div> 判断是否有mongoDB的访问权限,有就返回true,否则返回false。 </div> <div> boolean auth = db.authenticate(myUserName, myPassword); </div> <div>   </div> <div> <span>Ø </span> <b>查看</b> <b>mongoDB</b> <b>数据库列表</b> </div> <div> Mongo m = new Mongo(); </div> <div> for (String s : m.getDatabaseNames()) { </div> <div> System.out.println(s); </div> <div> } </div> <div>   </div> <div> <span>Ø </span> <b>查看当前库下所有的表名,等于在</b> <b>mongoDB</b> <b>中执行</b> <b>show tables; </b> </div> <div> Set<String> colls = db.getCollectionNames(); </div> <div> for (String s : colls) { </div> <div> System.out.println(s); </div> <div> } </div> <div>   </div> <div> <span>Ø </span> <b>查看一个表的索引</b> </div> <div> List<DBObject> list = coll.getIndexInfo(); </div> <div> for (DBObject o : list) { </div> <div> System.out.println(o); </div> <div> } </div> <div>   </div> <div> <span>Ø </span> <b>删除一个数据库</b> </div> <div> Mongo m = new Mongo(); </div> <div> m.dropDatabase("myDatabaseName"); </div> <div>   </div> <div> <span>Ø </span> <b>建立</b> <b>mongoDB</b> <b>的链接</b> </div> <div> Mongo m = new Mongo("localhost", 27017); //有多个重载方法,可根据需要选择 </div> <div> DB db = m.getDB("myDatabaseName"); //相当于库名 </div> <div> DBCollection coll = db.getCollection("myUsersTable");//相当于表名 </div> <div>   </div> <div>   </div> <div>   </div> <div> <b>查询数据</b> </div> <div> <span>Ø </span> <b>查询第一条记录</b> </div> <div> DBObject firstDoc = coll.findOne(); </div> <div> findOne()返回一个记录,而find()返回的是DBCursor游标对象。 </div> <div>   </div> <div> <span>Ø </span> <b>查询全部数据</b> </div> <div> DBCursor cur = coll.find(); </div> <div> while(cur.hasNext()) { </div> <div> System.out.println(cur.next()); </div> <div> } </div> <div>   </div> <div> <span>Ø </span> <b>查询记录数量</b> </div> <div> coll.find().count(); </div> <div> coll.find(new BasicDBObject("age", 26)).count(); </div> <div>   </div> <div> <span>Ø </span> <b>条件查询</b> </div> <div> BasicDBObject condition = new BasicDBObject(); </div> <div> condition.put("name", "bruce"); </div> <div> condition.put("age", 26); </div> <div> coll.find(condition); </div> <div>   </div> <div> <span>Ø </span> <b>查询部分数据块</b> </div> <div> DBCursor cursor = coll.find().skip(0).limit(10); </div> <div> while(cursor.hasNext()) { </div> <div> System.out.println(cursor.next()); </div> <div> } </div> <div>   </div> <div> <span>Ø </span> <b>比较查询</b> <b>(age > 50) </b> </div> <div> BasicDBObject condition = new BasicDBObject(); </div> <div> condition.put("age", new BasicDBObject("$gt", 50)); </div> <div> coll.find(condition); </div> <div> <b>比较符</b> </div> <div> "$gt": 大于 </div> <div> "$gte":大于等于 </div> <div> "$lt": 小于 </div> <div> "$lte":小于等于 </div> <div> "$in": 包含 </div> <div> //以下条件查询20<age<=30 </div> <div> condition.put("age", new BasicDBObject("$gt", 20).append("$lte", 30)); </div> <div>   </div> <div> <b>插入数据</b> </div> <div> <span>Ø </span> <b>批量插入</b> </div> <div> List datas = new ArrayList(); </div> <div> for (int i=0; i < 100; i++) { </div> <div> BasicDBObject bo = new BasicDBObject(); </div> <div> bo.put("name", "bruce"); </div> <div> bo.append("age", i); </div> <div> datas.add(bo); </div> <div> } </div> <div> coll.insert(datas); </div> <div> 又如: </div> <div> DBCollection coll = db.getCollection("testCollection"); <span>   </span> </div> <div> for(int i=1; i<=100; i++) {//插入100条记录 <span>   </span> </div> <div> <span>    User user = new User();   </span> </div> <div> <span>    user.setName("user_"+i);   </span> </div> <div> <span>    user.setPoint(i);   </span> </div> <div> <span>    coll.insert(user);</span> </div> <div> } <span>   </span> </div> <div> <span>Ø </span> <b>正则表达式</b> </div> <div> 查询所有名字匹配 /joh?n/i 的记录 </div> <div> Pattern pattern = Pattern.compile("joh?n", CASE_INSENSITIVE); </div> <div> BasicDBObject query = new BasicDBObject("name", pattern); </div> <div> DBCursor cursor = coll.find(query); </div> <div>   </div> <div>   </div> <div>   </div> <div> <b><font size="6">15Redis<span>简介</span></font></b> </div> <div> Redis是一个key-value类型的内存数据库,每一个key都与一个value关联,使得Redis与其他key-value数据库不同是因为在Redis中的每一个value都有一个类型(type),目前在Redis中支持5中数据类型:String、List、Set、ZSet和Hash。每一种类型决定了可以赋予其上的操作(这些操作成为命令command)。比如你可以使用LPUSH或RPUSH命令在O(1)时间对一个list添加一个元素,然后你可以使用LRANGE命令得到list中的一部分元素或使用LTRIM对该list进行trim操作。集合set操作也是很灵活的,你可以从set(无序的String的集合)中add或remove元素,还可以进行交集、合集和差集运算。每一个command都是服务端自动的操作。 </div> <div> Redis性能上和memcached一样快但提供了更多的特性。和memcached一样,Redis支持对key设置失效时间,因此当设定的时间过后会被自动删除。 </div> <div> <b><font size="5">15.1Redis<span>特性</span></font></b> </div> <div> <span>Ø </span>速度快 </div> <div> Redis使用标准C编写实现,而且将所有数据加载到内存中,所以速度非常快。官方提供的数据表明,在一个普通的Linux机器上,Redis读写速度分别达到81000/s和110000/s。 </div> <div> <span>Ø </span>持久化 </div> <div> 由于所有数据保持在内存中(2.0版本开始可以只将部分数据的value放在内存,见“虚拟内存”),所以对数据的更新将异步地保存到磁盘上,Redis提供了一些策略来保存数据,比如根据时间或更新次数。 </div> <div> <span>Ø </span>数据结构 </div> <div> 可以将Redis看做“数据结构服务器”。目前,Redis支持5种数据结构。 </div> <div> <span>Ø </span>自动操作 </div> <div> Redis对不同数据类型的操作是自动的,因此设置或增加key值,从一个集合中增加或删除一个元素都能安全的操作。 </div> <div> <span>Ø </span>支持多种语言 </div> <div> Redis支持多种语言,诸如Ruby, Python, Twisted Python, PHP, Erlang, Tcl, Perl, Lua, Java, Scala, Clojure等。对Java的支持,包括两个。一是JDBC-Redis,是使用JDBC连接Redis数据库的驱动。这个项目的目标并不是完全实现JDBC规范,因为Redis不是关系型数据库,但给Java开发人员提供了一个像操作关系数据库一样操作Redis数据库的接口。 </div> <div> 另一个是JRedis,是使用Redis作为数据库开发Java程序的开发包,主要提供了对数据结构的操作。 </div> <div> <span>Ø </span>主-从复制 </div> <div> Redis支持简单而快速的主-从复制。官方提供了一个数据,Slave在21秒即完成了对Amazon网站10G key set的复制。 </div> <div> <span>Ø </span>Sharding </div> <div> 很容易将数据分布到多个Redis实例中,但这主要看该语言是否支持。目前支持Sharding功能的语言只有PHP、Ruby和Scala。 </div> <div> <b><font size="6">16Redis<span>数据类型</span></font></b> </div> <div> 官方文档上,将Redis成为一个“数据结构服务器”(data structures server)是有一定道理的。Redis的所有功能就是以其固有的几种数据结构保存,并提供用户操作这几种结构的接口。可以对比在其他语言中那些固有数据类型及其操作。 </div> <div> Redis目前提供四种数据类型:string、list、set和zset(sorted set)。 </div> <div> <b><font size="5">16.1String<span>类型</span></font></b> </div> <div> String是最简单的类型,一个key对应一个value。Redis String是安全的,String类型的数据最大1G。String类型的值可以被视作integer,从而可以让“INCR”命令族操作,这种情况下,该integer的值限制在64位有符号数。 </div> <div> 在list、set和zset中包含的独立的元素类型都是Redis String类型。 </div> <div> 在Redis中,String类型由sds.c库定义,它被封装成Redis对象。和Java中的对象一样,Redis对象也是使用“引用”,因此当一个Redis String被多次使用时,Redis会尽量使用同一个String对象而不是多次分配。 </div> <div> 从Redis 1.1版开始,String对象可以编码成数字,因此这样可以节省内存空间。 </div> <div> <b><font size="5">16.2List<span>类型</span></font></b> </div> <div> 链表类型,主要功能是push、pop、获取一个范围的所有值等。其中的key可以理解为链表的名字。在Redis中,list就是Redis String的列表,按照插入顺序排序。比如使用LPUSH命令在list头插入一个元素,使用RPUSH命令在list的尾插入一个元素。当这两个命令之一作用于一个空的key时,一个新的list就创建出来了。比如: </div> <div> 最终在mylist中存储的元素为:”b”,”a”,”c”。 </div> <div> List的最大长度是2^32-1个元素。 </div> <div> <b><font size="5">16.3Set<span>类型</span></font></b> </div> <div> 集合,和数学中的集合概念相似。操作中的key理解为集合的名字。在Redis中,set就是Redis String的无序集合,不允许有重复元素。对set操作的command一般都有返回值标识所操作的元素是否已经存在。比如SADD命令是往set中插入一个元素,如果set中已存在该元素,则命令返回0,否则返回1。 </div> <div> Set的最大元素数是2^32-1。 </div> <div> Redis中对set的操作还有交集、并集、差集等。 </div> <div> <b><font size="5">16.4ZSet<span>类型</span></font></b> </div> <div> Zset是set的一个升级版本,在set的基础上增加了一个顺序属性,这一属性在添加修改元素时可以指定,每次指定后zset会自动安装指定值重新调整顺序。可以理解为一张表,一列存value,一列存顺序。操作中的key理解为zset的名字。 </div> <div> 比如ZADD命令是向zset中添加一个新元素,对该元素要指定一个score。如果对已经在zset中存在的元素施加ZADD命令同时指定了不同的score,则该元素的score将更新同时该元素将被移动到合适的位置以使集合保持有序。 </div> <div> 使用ZRANGE命令可以得到zset的一部分元素,当然也可以使用命令ZRANGEBYSCORE,根据score得到或删除一部分元素。 </div> <div> Zset的最大元素数是2^32-1。 </div> <div> 对于已经有序的zset,仍然可以使用SORT命令,通过指定ASC|DESC参数对其进行排序。 </div> <div> <b><font size="5">16.5Hash<span>类型</span></font></b> </div> <div> Redis Hash类型对数据域和值提供了映射,这一结构很方便表示对象。此外,在Hash中可以只保存有限的几个“域”,而不是将所有的“域”作为key,这可以节省内存。这一特性的体现可以参考下文的“虚拟内存”部分。 </div> <div> <b><font size="6">17All data in memory, but saved on disk</font></b> </div> <div> Redis在内存中加载并维护整个数据集,但这些数据是持久化的,因为它们在同一时间被保持在磁盘上,所以当Redis服务重启时,这些数据能够重新被加载到内存中。 </div> <div> Redis支持两种数据持久化的方法。一种称为snapsshotting,在这种模式下,Redis异步地将数据dump到磁盘上。Redis还可以通过配置,根据更新操作次数或间隔时间,将数据dump到磁盘。比如你可以设定发生1000个更新操作时,或距上次转储最多60s就要将数据dump到磁盘。 </div> <div> <span>       </span>因为数据是异步dump的,所以当系统崩溃时,就会出现错误。因为,Redis提供了另外一种模式,更安全的持久化模式,称为Append Only File,当出现修改数据命令的地方,这些命令就要写到“append only file”—ASAP。当服务重启时,这些命令会重新执行(replay)从而在内存中重新构建数据。 </div> <div> Redis的存储可以分为:内存存储、磁盘存储和log文件三部分,配置文件(redis.conf)中有三个参数对其进行配置。 </div> <div> <b>save <seconds> <changes></b> <b>:</b>save配置,指出在多长时间,有多少次更新操作,就将数据同步到数据文件。在默认的配置文件中设置就设置了三个条件。 </div> <div> <b>appendonly yes/no</b> <b>:</b>appendonly配置,指出是否在每次更新操作后进行日志记录,如果不开启,可能会在断电时导致一段时间内的数据丢失。因为redis本身同步数据文件是按上面的save条件来同步的,所以有的数据会在一段时间内只存在于内存中。 </div> <div> <b>appendfsync no/always/everysec</b> <b>:</b>appendfsync配置,no表示等操作系统进行数据缓存同步到磁盘,always表示每次更新操作后手动调用fsync()将数据写到磁盘,everysec表示每秒同步一次。 </div> <div> <b><font size="6">18Redis<span>的Master-Slave</span><span>模式</span></font></b> </div> <div> Redis中配置Master-Slave模式很简单,二者会自动同步。配置方法是在从机的配置文件中指定slaveof参数为主机的ip和port即可,比如: <b>slaveof 192.168.2.201 6379</b>。从原理上来说,是从机请求主机的方式,按照tokyotyrant的做法,是可以实现主-主,主-从等灵活形式的,而redis只能支持主-从,不能支持主-主。Redis中的复制具有以下特点: </div> <div> <span>Ø </span>一个master可以有多个slave。 </div> <div> <span>Ø </span>一个slave可以接收其他slave的链接,即不仅仅能连接一个master所属的slaves,而且能连接到slave的slave,从而形成了“图”结构。 </div> <div> <span>Ø </span>在复制进行时,master是“非阻塞”的。即一个或多个slave对master进行第一次同步时,master仍然可以提供查询服务,而对于slave,当复制进行时则是“阻塞”的,期间slave不能响应查询。 </div> <div> <span>Ø </span>复制可以用于提高数据的扩展性(比如多个slave用于只读查询),或者仅用于数据备份。 </div> <div> <span>Ø </span>使用复制可以避免在master存储数据,通过修改redis.conf文件(将“save”的al注释),这样数据存储只在slave端进行。 </div> <div> slave连接master并发出SYNC命令开始复制或当连接关闭时与master同步数据。master在“后台”进行存储操作,同时会监听所有对数据的更新操作。当存储操作完成后,master开始向slave传送数据并将数据保存到磁盘,加载到内存。这一过程中,master将会向slave发送所有对数据有更新操作的命令。通过telnet可以实验这一过程。通过连接到Redis端口并且发出SYNC命令,在telnet的session中,可以看到数据包的传送,以及发送给master的命令都将重新发送给slave。 </div> <div> 当master-slave连接断掉时,slave能自动重新建立连接。当一个master并发地收到多个slave数据同步请求时,master也能自动处理。 </div> <div> <b><font size="6">19Redis<span>虚拟内存管理</span></font></b> </div> <div> 在Redis2.0开始(目前最新版本)第一次提出了Virtual Memory(VM)的特性。Redis是内存数据库,因此通常情况下Redis会将所有的key和value都放在内存中,但有时这并不是最好的选择,为了查询速度,可以将所有的key放在内存中,而values可以放在磁盘上,当用到时再交换到内存。 </div> <div> 比如你的数据有100000个key都放在了内存中,而只有其中10%的key被经常访问,那么可进行VM配置的Redis会尝试将不经常访问的key关联的value放到磁盘上,当这些value被请求时才会交换到内存中。 </div> <div> 什么时候使用VM配置是需要考虑的问题。因为Redis是以磁盘为后备的内存数据库,在大多数情况下,只有RAM足够大时才使用Redis。但实际情况是,总会出现内存不够的情况: </div> <div> <span>Ÿ<span>   </span></span>有“倾向”的数据访问。只有很小比例的key被经常访问(比如一个网站的在线用户),但同时在内存中却有所有的数据。 </div> <div> <span>Ÿ<span>   </span></span>不考虑访问情况以及大的value,内存不能加载所有数据。这种情况下,Redis可以视作on-disk DB,即所有的key在内存中,而访问value时要访问慢速的磁盘。 </div> <div> 需要注意的一点是,Redis不能交换key。即如果是因为数据的key太大,value太小而造成内存不够,VM是不能解决这种情况的。当出现这种情况时,有时可以使用Hash结构,将“many keys with small values”的问题转换成“less keys but with very values”的问题(对key进行hash,从而对数据进行“分组”)。 </div> <div> 启用VM功能,只需要在redis.conf文件中使vm-enabled的值为yes。 </div> <div> <b><font size="6">20Redis<span>实例分析</span></font></b> </div> <div> 仍然以用户和图片的例子进行说明。假设将图片存储在文件系统中,即类Image中只保存图片的uri。类Image和类User的代码参见MongoDB部分的例子。下面给出测试类的关键代码: </div> <div> 在实现中,将类User的对象实例存放在一个set中,所以利用了SADD命令,在Java中即调用JRedis对象的sadd方法。smembers方法将返回指定key(这里是userSet)的集合中的所有value,这样就可以对每一个元素进行操作。 </div> <div> <b><font size="6">21Redis<span>命令总结</span></font></b> </div> <div> Redis提供了丰富的命令(command)对数据库和各种数据类型进行操作,这些command可以在Linux终端使用。在编程时,比如使用Redis 的Java语言包,这些命令都有对应的方法,比如上面例子中使用的sadd方法,就是对集合操作中的SADD命令。下面将Redis提供的命令做一总结。 </div> <div> <b><font size="5">21.1<span>连接操作相关的命令</span></font></b> </div> <div> <span>Ÿ<span>   </span></span> <b>quit</b>:关闭连接(connection) </div> <div> <span>Ÿ<span>   </span></span> <b>auth</b>:简单密码认证 </div> <div> <b><font size="5">21.2<span>对value</span><span>操作的命令</span></font></b> </div> <div> <span>Ÿ<span>   </span></span> <b>exists(<i>key</i>)</b>:确认一个key是否存在 </div> <div> <span>Ÿ<span>   </span></span> <b>del(<i>key</i>)</b>:删除一个key </div> <div> <span>Ÿ<span>   </span></span> <b>type(<i>key</i>)</b>:返回值的类型 </div> <div> <span>Ÿ<span>   </span></span> <b>keys(<i>pattern</i>)</b>:返回满足给定pattern的所有key </div> <div> <span>Ÿ<span>   </span></span> <b>randomkey</b>:随机返回key空间的一个key </div> <div> <span>Ÿ<span>   </span></span> <b>rename(<i>oldname</i>, <i>newname</i>)</b>:将key由oldname重命名为newname,若newname存在则删除newname表示的key </div> <div> <span>Ÿ<span>   </span></span> <b>dbsize</b>:返回当前数据库中key的数目 </div> <div> <span>Ÿ<span>   </span></span> <b>expire</b>:设定一个key的活动时间(s) </div> <div> <span>Ÿ<span>   </span></span> <b>ttl</b>:获得一个key的活动时间 </div> <div> <span>Ÿ<span>   </span></span> <b>select(<i>index</i>)</b>:按索引查询 </div> <div> <span>Ÿ<span>   </span></span> <b>move(<i>key</i>, <i>dbindex</i>)</b>:将当前数据库中的key转移到有dbindex索引的数据库 </div> <div> <span>Ÿ<span>   </span></span> <b>flushdb</b>:删除当前选择数据库中的所有key </div> <div> <span>Ÿ<span>   </span></span> <b>flushall</b>:删除所有数据库中的所有key </div> <div> <b><font size="5">21.3<span>对String</span><span>操作的命令</span></font></b> </div> <div> <span>Ÿ<span>   </span></span> <b>set(<i>key, value</i>)</b>:给数据库中名称为key的string赋予值value </div> <div> <span>Ÿ<span>   </span></span> <b>get(<i>key</i>)</b>:返回数据库中名称为key的string的value </div> <div> <span>Ÿ<span>   </span></span> <b>getset(<i>key, value</i>)</b>:给名称为key的string赋予上一次的value </div> <div> <span>Ÿ<span>   </span></span> <b>mget(<i>key1, key2,…, key N</i>)</b>:返回库中多个string(它们的名称为key1,key2…)的value </div> <div> <span>Ÿ<span>   </span></span> <b>setnx(<i>key, value</i>)</b>:如果不存在名称为key的string,则向库中添加string,名称为key,值为value </div> <div> <span>Ÿ<span>   </span></span> <b>setex(<i>key</i>, <i>time</i>, <i>value</i>)</b>:向库中添加string(名称为key,值为value)同时,设定过期时间time </div> <div> <span>Ÿ<span>   </span></span> <b>mset(<i>key1, value1, key2, value2,…key N, value N</i>)</b>:同时给多个string赋值,名称为key <b><i>i</i></b>的string赋值value <b><i>i</i></b> </div> <div> <span>Ÿ<span>   </span></span> <b>msetnx(<i>key1, value1, key2, value2,…key N, value N</i>)</b>:如果所有名称为key <b><i>i</i></b>的string都不存在,则向库中添加string,名称key <b><i>i</i></b>赋值为value <b><i>i</i></b> </div> <div> <span>Ÿ<span>   </span></span> <b>incr(<i>key</i>)</b>:名称为key的string增1操作 </div> <div> <span>Ÿ<span>   </span></span> <b>incrby(<i>key, integer</i>)</b>:名称为key的string增加integer </div> <div> <span>Ÿ<span>   </span></span> <b>decr(<i>key</i>)</b>:名称为key的string减1操作 </div> <div> <span>Ÿ<span>   </span></span> <b>decrby(<i>key, integer</i>)</b>:名称为key的string减少integer </div> <div> <span>Ÿ<span>   </span></span> <b>append(<i>key, value</i>)</b>:名称为key的string的值附加value </div> <div> <span>Ÿ<span>   </span></span> <b>substr(<i>key, start, end</i>)</b>:返回名称为key的string的value的子串 </div> <div> <b><font size="5">21.4<span>对List</span><span>操作的命令</span></font></b> </div> <div> <span>Ÿ<span>   </span></span> <b>rpush(<i>key, value</i>)</b>:在名称为key的list尾添加一个值为value的元素 </div> <div> <span>Ÿ<span>   </span></span> <b>lpush(<i>key, value</i>)</b>:在名称为key的list头添加一个值为value的 元素 </div> <div> <span>Ÿ<span>   </span></span> <b>llen(<i>key</i>)</b>:返回名称为key的list的长度 </div> <div> <span>Ÿ<span>   </span></span> <b>lrange(<i>key, start, end</i>)</b>:返回名称为key的list中start至end之间的元素(下标从0开始,下同) </div> <div> <span>Ÿ<span>   </span></span> <b>ltrim(<i>key, start, end</i>)</b>:截取名称为key的list,保留start至end之间的元素 </div> <div> <span>Ÿ<span>   </span></span> <b>lindex(<i>key, index</i>)</b>:返回名称为key的list中index位置的元素 </div> <div> <span>Ÿ<span>   </span></span> <b>lset(<i>key, index, value</i>)</b>:给名称为key的list中index位置的元素赋值为value </div> <div> <span>Ÿ<span>   </span></span> <b>lrem(<i>key, count, value</i>)</b>:删除count个名称为key的list中值为value的元素。count为0,删除所有值为value的元素,count>0从头至尾删除count个值为value的元素,count<0从尾到头删除|count|个值为value的元素。 </div> <div> <span>Ÿ<span>   </span></span> <b>lpop(<i>key</i>)</b>:返回并删除名称为key的list中的首元素 </div> <div> <span>Ÿ<span>   </span></span> <b>rpop(<i>key</i>)</b>:返回并删除名称为key的list中的尾元素 </div> <div> <span>Ÿ<span>   </span></span> <b>blpop(<i>key1, key2,… key N, timeout</i>)</b>:lpop命令的block版本。即当timeout为0时,若遇到名称为key <b><i>i</i></b>的list不存在或该list为空,则命令结束。如果timeout>0,则遇到上述情况时,等待timeout秒,如果问题没有解决,则对key <b><i>i+1</i></b>开始的list执行pop操作。 </div> <div> <span>Ÿ<span>   </span></span> <b>brpop(<i>key1, key2,… key N, timeout</i>)</b>:rpop的block版本。参考上一命令。 </div> <div> <span>Ÿ<span>   </span></span> <b>rpoplpush(<i>srckey, dstkey</i>)</b>:返回并删除名称为srckey的list的尾元素,并将该元素添加到名称为dstkey的list的头部 </div> <div> <b><font size="5">21.5<span>对Set</span><span>操作的命令</span></font></b> </div> <div> <span>Ÿ<span>   </span></span> <b>sadd(<i>key, member</i>)</b>:向名称为key的set中添加元素member </div> <div> <span>Ÿ<span>   </span></span> <b>srem(<i>key, member</i>) </b>:删除名称为key的set中的元素member </div> <div> <span>Ÿ<span>   </span></span> <b>spop(<i>key</i>) </b>:随机返回并删除名称为key的set中一个元素 </div> <div> <span>Ÿ<span>   </span></span> <b>smove(<i>srckey, dstkey, member</i>)</b> :将member元素从名称为srckey的集合移到名称为dstkey的集合 </div> <div> <span>Ÿ<span>   </span></span> <b>scard(<i>key</i>) </b>:返回名称为key的set的基数 </div> <div> <span>Ÿ<span>   </span></span> <b>sismember(<i>key, member</i>)</b> :测试member是否是名称为key的set的元素 </div> <div> <span>Ÿ<span>   </span></span> <b>sinter(<i>key1, key2,…key N</i>) </b>:求交集 </div> <div> <span>Ÿ<span>   </span></span> <b>sinterstore(<i>dstkey, key1, key2,…key N</i>) </b>:求交集并将交集保存到dstkey的集合 </div> <div> <span>Ÿ<span>   </span></span> <b>sunion(<i>key1, key2,…key N</i>) </b>:求并集 </div> <div> <span>Ÿ<span>   </span></span> <b>sunionstore(<i>dstkey, key1, key2,…key N</i>)</b> :求并集并将并集保存到dstkey的集合 </div> <div> <span>Ÿ<span>   </span></span> <b>sdiff(<i>key1, key2,…key N</i>) </b>:求差集 </div> <div> <span>Ÿ<span>   </span></span> <b>sdiffstore(<i>dstkey, key1, key2,…key N</i>)</b> :求差集并将差集保存到dstkey的集合 </div> <div> <span>Ÿ<span>   </span></span> <b>smembers(<i>key</i>)</b> :返回名称为key的set的所有元素 </div> <div> <span>Ÿ<span>   </span></span> <b>srandmember(<i>key</i>)</b> :随机返回名称为key的set的一个元素 </div> <div> <b><font size="5">21.6<span>对zset</span><span>(sorted set</span><span>)操作的命令</span></font></b> </div> <div> <span>Ÿ<span>   </span></span> <b>zadd(<i>key, score, member</i>)</b>:向名称为key的zset中添加元素member,score用于排序。如果该元素已经存在,则根据score更新该元素的顺序。 </div> <div> <span>Ÿ<span>   </span></span> <b>zrem(<i>key, member</i>)</b> :删除名称为key的zset中的元素member </div> <div> <span>Ÿ<span>   </span></span> <b>zincrby(<i>key, increment, member</i>) </b>:如果在名称为key的zset中已经存在元素member,则该元素的score增加increment;否则向集合中添加该元素,其score的值为increment </div> <div> <span>Ÿ<span>   </span></span> <b>zrank(<i>key, member</i>) </b>:返回名称为key的zset(元素已按score从小到大排序)中member元素的rank(即index,从0开始),若没有member元素,返回“nil” </div> <div> <span>Ÿ<span>   </span></span> <b>zrevrank(<i>key, member</i>) </b>:返回名称为key的zset(元素已按score从大到小排序)中member元素的rank(即index,从0开始),若没有member元素,返回“nil” </div> <div> <span>Ÿ<span>   </span></span> <b>zrange(<i>key, start, end</i>)</b>:返回名称为key的zset(元素已按score从小到大排序)中的index从start到end的所有元素 </div> <div> <span>Ÿ<span>   </span></span> <b>zrevrange(<i>key, start, end</i>)</b>:返回名称为key的zset(元素已按score从大到小排序)中的index从start到end的所有元素 </div> <div> <span>Ÿ<span>   </span></span> <b>zrangebyscore(<i>key, min, max</i>)</b>:返回名称为key的zset中score >= min且score <= max的所有元素 </div> <div> <span>Ÿ<span>   </span></span> <b>zcard(<i>key</i>)</b>:返回名称为key的zset的基数 </div> <div> <span>Ÿ<span>   </span></span> <b>zscore(<i>key, element</i>)</b>:返回名称为key的zset中元素element的score </div> <div> <span>Ÿ<span>   </span></span> <b>zremrangebyrank(<i>key, min, max</i>)</b>:删除名称为key的zset中rank >= min且rank <= max的所有元素 </div> <div> <span>Ÿ<span>   </span></span> <b>zremrangebyscore(<i>key, min, max</i>)</b> :删除名称为key的zset中score >= min且score <= max的所有元素 </div> <div> <span>Ÿ<span>   </span></span> <b>zunionstore / zinterstore(<i>dstkeyN</i>, <i>key1,…,keyN</i>, WEIGHTS<i> w1,…wN, </i>AGGREGATE SUM|MIN|MAX)</b>:对N个zset求并集和交集,并将最后的集合保存在dstkeyN中。对于集合中每一个元素的score,在进行AGGREGATE运算前,都要乘以对于的WEIGHT参数。如果没有提供WEIGHT,默认为1。默认的AGGREGATE是SUM,即结果集合中元素的score是所有集合对应元素进行SUM运算的值,而MIN和MAX是指,结果集合中元素的score是所有集合对应元素中最小值和最大值。 </div> <div> <b><font size="5">21.7<span>对Hash</span><span>操作的命令</span></font></b> </div> <div> <span>Ÿ<span>   </span></span> <b>hset(<i>key, field, value</i>)</b>:向名称为key的hash中添加元素field<—>value </div> <div> <span>Ÿ<span>   </span></span> <b>hget(<i>key, field</i>)</b>:返回名称为key的hash中field对应的value </div> <div> <span>Ÿ<span>   </span></span> <b>hmget(<i>key, field1, …,field N</i>)</b>:返回名称为key的hash中field <b><i>i</i></b>对应的value </div> <div> <span>Ÿ<span>   </span></span> <b>hmset(<i>key, field1, value1,…,field N, value N</i>)</b>:向名称为key的hash中添加元素field <b><i>i</i></b><—>value <b><i>i</i></b> </div> <div> <span>Ÿ<span>   </span></span> <b>hincrby(<i>key, field, integer</i>)</b>:将名称为key的hash中field的value增加integer </div> <div> <span>Ÿ<span>   </span></span> <b>hexists(<i>key, field</i>)</b>:名称为key的hash中是否存在键为field的域 </div> <div> <span>Ÿ<span>   </span></span> <b>hdel(<i>key, field</i>)</b>:删除名称为key的hash中键为field的域 </div> <div> <span>Ÿ<span>   </span></span> <b>hlen(<i>key</i>)</b>:返回名称为key的hash中元素个数 </div> <div> <span>Ÿ<span>   </span></span> <b>hkeys(<i>key</i>)</b>:返回名称为key的hash中所有键 </div> <div> <span>Ÿ<span>   </span></span> <b>hvals(<i>key</i>)</b>:返回名称为key的hash中所有键对应的value </div> <div> <span>Ÿ<span>   </span></span> <b>hgetall(<i>key</i>)</b>:返回名称为key的hash中所有的键(field)及其对应的value </div> <div> <b><font size="5">21.8<span>持久化</span></font></b> </div> <div> <span>Ÿ<span>   </span></span> <b>save</b>:将数据同步保存到磁盘 </div> <div> <span>Ÿ<span>   </span></span> <b>bgsave</b>:将数据异步保存到磁盘 </div> <div> <span>Ÿ<span>   </span></span> <b>lastsave</b>:返回上次成功将数据保存到磁盘的Unix时戳 </div> <div> <span>Ÿ<span>   </span></span> <b>shundown</b>:将数据同步保存到磁盘,然后关闭服务 </div> <div> <b><font size="5">21.9<span>远程服务控制</span></font></b> </div> <div> <span>Ÿ<span>   </span></span> <b>info</b>:提供服务器的信息和统计 </div> <div> <span>Ÿ<span>   </span></span> <b>monitor</b>:实时转储收到的请求 </div> <div> <span>Ÿ<span>   </span></span> <b>slaveof</b>:改变复制策略设置 </div> <div> <span>Ÿ<span>   </span></span> <b>config</b>:在运行时配置Redis服务器 </div> <div>   </div> </div> </div> </div> </div> </div> <!--PC和WAP自适应版--> <div id="SOHUCS" sid="1225384099506655232"></div> <script type="text/javascript" src="/views/front/js/chanyan.js"></script> <!-- 文章页-底部 动态广告位 --> <div class="youdao-fixed-ad" id="detail_ad_bottom"></div> </div> <div class="col-md-3"> <div class="row" id="ad"> <!-- 文章页-右侧1 动态广告位 --> <div id="right-1" class="col-lg-12 col-md-12 col-sm-4 col-xs-4 ad"> <div class="youdao-fixed-ad" id="detail_ad_1"> </div> </div> <!-- 文章页-右侧2 动态广告位 --> <div id="right-2" class="col-lg-12 col-md-12 col-sm-4 col-xs-4 ad"> <div class="youdao-fixed-ad" id="detail_ad_2"></div> </div> <!-- 文章页-右侧3 动态广告位 --> <div id="right-3" class="col-lg-12 col-md-12 col-sm-4 col-xs-4 ad"> <div class="youdao-fixed-ad" id="detail_ad_3"></div> </div> </div> </div> </div> </div> </div> <div class="container"> <h4 class="pt20 mb15 mt0 border-top">你可能感兴趣的:(数据库,Redis,NoSQL,分布式与并行计算)</h4> <div id="paradigm-article-related"> <div class="recommend-post mb30"> <ul class="widget-links"> <li><a href="/article/1901039965454790656.htm" title="Elasticsearch大文件检索性能提升20倍实践(干货)_elasticsearch 查询优化" target="_blank">Elasticsearch大文件检索性能提升20倍实践(干货)_elasticsearch 查询优化</a> <span class="text-muted">2401_84247505</span> <a class="tag" taget="_blank" href="/search/2024%E5%B9%B4%E7%A8%8B%E5%BA%8F%E5%91%98%E5%AD%A6%E4%B9%A0/1.htm">2024年程序员学习</a><a class="tag" taget="_blank" href="/search/elasticsearch/1.htm">elasticsearch</a><a class="tag" taget="_blank" href="/search/jenkins/1.htm">jenkins</a><a class="tag" taget="_blank" href="/search/%E5%A4%A7%E6%95%B0%E6%8D%AE/1.htm">大数据</a> <div>3、问题排查与定位步骤1:限定返回记录条数。不提供直接访问末页的入口。baidu,360,搜狗等搜索引擎都不提供访问末页的请求方式。都是基于如下的请求方式:通过点击上一下、下一页逐页访问。这个从用户的角度也很好理解,搜索引擎返回的前面都是相关度最高的,也是用户最关心的信息。Elasticsearch的默认支持的数据条数是10000条,可以通过post请求修改。最终,本步骤将支持ES最大返回值100</div> </li> <li><a href="/article/1901039585656369152.htm" title="Spring Boot整合JWT 实现双Token机制" target="_blank">Spring Boot整合JWT 实现双Token机制</a> <span class="text-muted">Cloud_.</span> <a class="tag" taget="_blank" href="/search/spring/1.htm">spring</a><a class="tag" taget="_blank" href="/search/boot/1.htm">boot</a><a class="tag" taget="_blank" href="/search/%E5%90%8E%E7%AB%AF/1.htm">后端</a><a class="tag" taget="_blank" href="/search/java/1.htm">java</a> <div>目录JWT核心概念解析SpringBoot整合步骤2.1基础环境搭建2.2Token生成与解析2.3拦截器实现企业级增强方案3.1双Token刷新机制3.2安全防护策略常见问题与解决方案1.JWT核心概念解析1.1Token的三重使命身份凭证:替代Session实现无状态认证信息载体:存储用户基础信息(如userid、roles)安全屏障:数字签名防止数据篡改1.2JWT结构示例Header{"a</div> </li> <li><a href="/article/1901038955428638720.htm" title="Manus 一码难求,MetaGPT、OpenManus、Camel AI 会是替代方案吗?" target="_blank">Manus 一码难求,MetaGPT、OpenManus、Camel AI 会是替代方案吗?</a> <span class="text-muted">全干程序员demo</span> <a class="tag" taget="_blank" href="/search/%E6%8A%80%E6%9C%AF%E7%83%AD%E6%96%87/1.htm">技术热文</a><a class="tag" taget="_blank" href="/search/%E4%BA%BA%E5%B7%A5%E6%99%BA%E8%83%BD/1.htm">人工智能</a> <div>Manus一码难求,MetaGPT、OpenManus、CamelAI会是替代方案吗?一、Manus的现象与问题Manus作为一款号称“全球首个通用AI智能体”的产品,凭借其强大的功能和新颖的营销策略迅速走红。然而,其封闭的邀请码机制和高昂的使用门槛,让普通开发者望而却步。Manus的邀请码被炒至高价,甚至出现账号冻结等现象,这引发了用户对其技术壁垒和实际应用价值的质疑。二、MetaGPT、Ope</div> </li> <li><a href="/article/1901037065106157568.htm" title="信息学奥赛一本通C++语言-----1119:矩阵交换行" target="_blank">信息学奥赛一本通C++语言-----1119:矩阵交换行</a> <span class="text-muted">宝祺祺吖</span> <a class="tag" taget="_blank" href="/search/c%2B%2B/1.htm">c++</a><a class="tag" taget="_blank" href="/search/%E7%AE%97%E6%B3%95/1.htm">算法</a> <div>【题目描述】给定一个5×55×5的矩阵(数学上,一个r×cr×c的矩阵是一个由rr行cc列元素排列成的矩形阵列),将第nn行和第mm行交换,输出交换后的结果。【输入】输入共66行,前55行为矩阵的每一行元素,元素与元素之间以一个空格分开。第66行包含两个整数m、nm、n,以一个空格分开(1≤m,n≤5)(1≤m,n≤5)。【输出】输出交换之后的矩阵,矩阵的每一行元素占一行,元素之间以一个空格分开。</div> </li> <li><a href="/article/1901036183715115008.htm" title="程序员必看!DeepSeek全栈开发指南:从代码生成到分布式训练的黑科技解析" target="_blank">程序员必看!DeepSeek全栈开发指南:从代码生成到分布式训练的黑科技解析</a> <span class="text-muted">AI创享派</span> <a class="tag" taget="_blank" href="/search/%E5%90%8E%E7%AB%AF/1.htm">后端</a> <div>一、DeepSeek技术新突破:程序员必须掌握的MoE架构实战2025年2月25日,DeepSeek开源了专为MoE模型设计的DeepEP通信库,这项技术革新直接影响了分布式训练和推理效率。该库支持FP8精度与NVLink/RDMA技术,吞吐量提升3倍以上,特别适合处理千亿级参数的分布式任务。对于后端工程师而言,DeepEP的以下特性值得关注:计算-通信重叠机制:通过回调函数实现GPU资源动态分配</div> </li> <li><a href="/article/1901035426882318336.htm" title="Android StrictMode 使用与原理深度解析" target="_blank">Android StrictMode 使用与原理深度解析</a> <span class="text-muted">伟江.Zeng</span> <a class="tag" taget="_blank" href="/search/Android%E5%9F%BA%E7%A1%80/1.htm">Android基础</a><a class="tag" taget="_blank" href="/search/android/1.htm">android</a><a class="tag" taget="_blank" href="/search/StrictMode/1.htm">StrictMode</a><a class="tag" taget="_blank" href="/search/%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96/1.htm">性能优化</a><a class="tag" taget="_blank" href="/search/%E5%86%85%E5%AD%98%E6%B3%84%E6%BC%8F/1.htm">内存泄漏</a><a class="tag" taget="_blank" href="/search/%E4%BB%A3%E7%A0%81%E8%A7%84%E8%8C%83/1.htm">代码规范</a><a class="tag" taget="_blank" href="/search/%E8%80%97%E6%97%B6%E6%A3%80%E6%B5%8B/1.htm">耗时检测</a><a class="tag" taget="_blank" href="/search/kotlin/1.htm">kotlin</a> <div>AndroidStrictMode是Android系统提供的一种开发者工具,用于检测应用主线程中不合理的耗时操作(如磁盘I/O、网络请求等)和内存泄漏问题。通过配置策略和惩罚机制,它帮助开发者在早期发现潜在性能问题,提升应用流畅性。以下从使用方式和实现原理两方面进行深度解析。一、StrictMode使用详解1.基础配置在Application或Activity的onCreate()中初始化Stri</div> </li> <li><a href="/article/1901034544564334592.htm" title="【Android】adb shell基本使用教程" target="_blank">【Android】adb shell基本使用教程</a> <span class="text-muted">Vesper63</span> <a class="tag" taget="_blank" href="/search/android/1.htm">android</a><a class="tag" taget="_blank" href="/search/adb/1.htm">adb</a> <div>adbshell是AndroidDebugBridge(ADB)工具中的一个命令,用于在连接的Android设备或模拟器上执行shell命令。通过adbshell,你可以直接与设备的Linux内核交互,执行各种操作。基本用法启动adbshell:在终端或命令提示符中输入以下命令:adbshell这将进入设备的shell环境,提示符通常会变为$或#(#表示root权限)。执行单个命令:如果你只想执行</div> </li> <li><a href="/article/1901034166636572672.htm" title="MATLAB算法实战应用案例精讲-【深度学习】归一化" target="_blank">MATLAB算法实战应用案例精讲-【深度学习】归一化</a> <span class="text-muted">林聪木</span> <a class="tag" taget="_blank" href="/search/matlab/1.htm">matlab</a><a class="tag" taget="_blank" href="/search/%E7%AE%97%E6%B3%95/1.htm">算法</a><a class="tag" taget="_blank" href="/search/%E6%B7%B1%E5%BA%A6%E5%AD%A6%E4%B9%A0/1.htm">深度学习</a> <div>目录为什么要做特征归一化/标准化?常用featurescaling方法计算方式上对比分析featurescaling需要还是不需要什么时候需要featurescaling?什么时候不需要FeatureScaling?归一化基础知识点1.什么是归一化2.为什么要归一化3.为什么归一化能提高求解最优解的速度4.归一化有哪些类型5.不同归一化的使用条件6.归一化和标准化的联系与区别层归一化综述提出背景概</div> </li> <li><a href="/article/1901032402994655232.htm" title="Redis7——进阶篇(四)" target="_blank">Redis7——进阶篇(四)</a> <span class="text-muted">啥也不会的小神龙·</span> <a class="tag" taget="_blank" href="/search/Redis%E7%B3%BB%E5%88%97/1.htm">Redis系列</a><a class="tag" taget="_blank" href="/search/redis/1.htm">redis</a><a class="tag" taget="_blank" href="/search/%E7%BC%93%E5%AD%98/1.htm">缓存</a><a class="tag" taget="_blank" href="/search/%E5%AD%A6%E4%B9%A0/1.htm">学习</a><a class="tag" taget="_blank" href="/search/redis%E7%BB%8F%E5%85%B8%E9%9D%A2%E8%AF%95%E9%A2%98/1.htm">redis经典面试题</a> <div>前言:此篇文章系本人学习过程中记录下来的笔记,里面难免会有不少欠缺的地方,诚心期待大家多多给予指教。基础篇:Redis(一)Redis(二)Redis(三)Redis(四)Redis(五)Redis(六)Redis(七)Redis(八)进阶篇:Redis(九)Redis(十)Redis(十一)接上期内容:上期完成了缓存双写一致性方面的学习。下面学习HyperLogLog/Geo/Bitmap实际案</div> </li> <li><a href="/article/1901030764212973568.htm" title="PCIe信号传输的幕后:HCSL与LP-HCSL深度解析" target="_blank">PCIe信号传输的幕后:HCSL与LP-HCSL深度解析</a> <span class="text-muted">赛卡</span> <a class="tag" taget="_blank" href="/search/%E5%8D%95%E7%89%87%E6%9C%BA/1.htm">单片机</a><a class="tag" taget="_blank" href="/search/%E5%B5%8C%E5%85%A5%E5%BC%8F%E7%A1%AC%E4%BB%B6/1.htm">嵌入式硬件</a><a class="tag" taget="_blank" href="/search/%E6%9C%8D%E5%8A%A1%E5%99%A8/1.htm">服务器</a><a class="tag" taget="_blank" href="/search/%E4%BA%BA%E5%B7%A5%E6%99%BA%E8%83%BD/1.htm">人工智能</a><a class="tag" taget="_blank" href="/search/%E7%A1%AC%E4%BB%B6%E6%9E%B6%E6%9E%84/1.htm">硬件架构</a><a class="tag" taget="_blank" href="/search/fpga%E5%BC%80%E5%8F%91/1.htm">fpga开发</a> <div>在数字化浪潮席卷的当下,PCIe(PeripheralComponentInterconnectExpress)作为高速串行计算机扩展总线标准,已然成为计算机内部硬件设备连接领域的中流砥柱。其信号传输的质量与完整性,恰似计算机系统运行的“命门”,对系统整体性能起着决定性作用。在PCIe体系架构里,HCSL(High-speedCurrentSteeringLogic)与LP-HCSL(Low-Po</div> </li> <li><a href="/article/1901030765022474240.htm" title="半导体可靠性测试解析:HTOL、LTOL与Burn-In" target="_blank">半导体可靠性测试解析:HTOL、LTOL与Burn-In</a> <span class="text-muted">赛卡</span> <a class="tag" taget="_blank" href="/search/%E7%A1%AC%E4%BB%B6%E6%9E%B6%E6%9E%84/1.htm">硬件架构</a><a class="tag" taget="_blank" href="/search/%E6%B1%BD%E8%BD%A6/1.htm">汽车</a><a class="tag" taget="_blank" href="/search/%E8%BD%A6%E8%BD%BD%E7%B3%BB%E7%BB%9F/1.htm">车载系统</a> <div>引言在半导体器件复杂度与可靠性要求同步提升的今天,高温工作寿命测试(HTOL)、低温寿命测试(LTOL)和老化筛选测试(Burn-In)构成了芯片可靠性验证的三大支柱。这些测试通过模拟极端环境下的失效机制,帮助制造商提前发现潜在缺陷,优化设计并满足汽车、工业等领域的严苛标准。本文将从测试原理、标准要求及报告解读维度展开深度解析。一、核心测试方法的技术边界与协同逻辑1.HTOL(高温工作寿命测试)测</div> </li> <li><a href="/article/1901030512059805696.htm" title="设计空间探索:乘法器设计的面积、延时、功耗优化" target="_blank">设计空间探索:乘法器设计的面积、延时、功耗优化</a> <span class="text-muted">赛卡</span> <a class="tag" taget="_blank" href="/search/%E4%BA%BA%E5%B7%A5%E6%99%BA%E8%83%BD/1.htm">人工智能</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/%E7%AE%97%E6%B3%95/1.htm">算法</a> <div>复杂压缩器可压缩更多高度,减少层数(外层while循环次数),但延迟较高。使用哪些压缩器以何种方案进行压缩,是一个设计空间探索问题。1.压缩器种类的选择4-2压缩器:由两个全加器(FA)组成,能够将4个输入压缩为2个输出(和与进位)。适用于中等规模的压缩需求,可以有效减少部分积的位宽。6-2压缩器:能够将6个输入压缩为2个输出,适用于较大规模的压缩需求,尤其在多列压缩时可以减少层次数量。9-2压缩</div> </li> <li><a href="/article/1901028369089228800.htm" title="Assembly语言的自然语言处理" target="_blank">Assembly语言的自然语言处理</a> <span class="text-muted">花韵婷</span> <a class="tag" taget="_blank" href="/search/%E5%8C%85%E7%BD%97%E4%B8%87%E8%B1%A1/1.htm">包罗万象</a><a class="tag" taget="_blank" href="/search/golang/1.htm">golang</a><a class="tag" taget="_blank" href="/search/%E5%BC%80%E5%8F%91%E8%AF%AD%E8%A8%80/1.htm">开发语言</a><a class="tag" taget="_blank" href="/search/%E5%90%8E%E7%AB%AF/1.htm">后端</a> <div>Assembly语言在自然语言处理中的应用引言自然语言处理(NaturalLanguageProcessing,NLP)作为人工智能的一个重要分支,致力于实现计算机与人类语言之间的互动。随着计算能力的提升以及大数据的蓬勃发展,NLP在各个领域的应用如火如荼。从语音识别、机器翻译到情感分析等,NLP正在改变我们与信息之间的互动方式。不过,当前主流的NLP研究通常是用高级编程语言(如Python、Ja</div> </li> <li><a href="/article/1901028242073120768.htm" title="Groovy语言的漏洞扫描" target="_blank">Groovy语言的漏洞扫描</a> <span class="text-muted">花韵婷</span> <a class="tag" taget="_blank" href="/search/%E5%8C%85%E7%BD%97%E4%B8%87%E8%B1%A1/1.htm">包罗万象</a><a class="tag" taget="_blank" href="/search/golang/1.htm">golang</a><a class="tag" taget="_blank" href="/search/%E5%BC%80%E5%8F%91%E8%AF%AD%E8%A8%80/1.htm">开发语言</a><a class="tag" taget="_blank" href="/search/%E5%90%8E%E7%AB%AF/1.htm">后端</a> <div>Groovy语言漏洞扫描:深入分析与实践引言Groovy是一种基于Java虚拟机(JVM)的动态编程语言,它结合了Python、Ruby和Smalltalk等语言的特性,提供了简洁的语法和强大的功能。Groovy广泛应用于脚本编写、自动化测试、构建工具(如Gradle)以及Web开发等领域。然而,随着Groovy的广泛应用,其安全性问题也逐渐显现出来。本文将深入探讨Groovy语言中的常见漏洞类型</div> </li> <li><a href="/article/1901025595387604992.htm" title="软考高级《系统架构设计师》知识点(十三)" target="_blank">软考高级《系统架构设计师》知识点(十三)</a> <span class="text-muted">Ritchie里其</span> <a class="tag" taget="_blank" href="/search/%E7%B3%BB%E7%BB%9F%E6%9E%B6%E6%9E%84/1.htm">系统架构</a> <div>系统架构设计软件架构的概念一个程序和计算系统软件体系结构是指系统的一个或者多个结构。结构中包括软件的构件,构件的外部可见属性以及它们之间的相互关系。体系结构并非可运行软件。确切地说,它是一种表达,使软件工程师能够:分析设计在满足所规定的需求方面的有效性:在设计变更相对容易的阶段,考虑体系结构可能的选择方案;降低与软件构造相关联的风险。软件构件简单到可以是程序模块或者面向对象的类,也可以扩充到包含数</div> </li> <li><a href="/article/1901024965520584704.htm" title="PCDN 与边缘计算的结合:未来内容分发的新趋势" target="_blank">PCDN 与边缘计算的结合:未来内容分发的新趋势</a> <span class="text-muted">yczykjyxgs</span> <a class="tag" taget="_blank" href="/search/pcdn/1.htm">pcdn</a><a class="tag" taget="_blank" href="/search/%E6%99%BA%E8%83%BD%E8%B7%AF%E7%94%B1%E5%99%A8/1.htm">智能路由器</a> <div>在数字化浪潮中,内容分发面临着前所未有的挑战与机遇。PCDN(P2P内容分发网络)与边缘计算的结合,正逐渐崭露头角,成为未来内容分发的新趋势。PCDN通过P2P技术,利用用户节点的闲置资源进行内容分发,有效减轻了中心服务器的压力,降低了传输成本。然而,在面对实时性要求极高的业务场景时,PCDN仍存在一定局限。边缘计算的出现,为解决这一问题提供了新思路。边缘计算将计算和存储能力下沉到网络边缘,靠近用</div> </li> <li><a href="/article/1901024335905222656.htm" title="PKI及SSL协议分析实验报告" target="_blank">PKI及SSL协议分析实验报告</a> <span class="text-muted">只会复制粘贴的</span> <a class="tag" taget="_blank" href="/search/ssl/1.htm">ssl</a><a class="tag" taget="_blank" href="/search/https/1.htm">https</a><a class="tag" taget="_blank" href="/search/%E6%9C%8D%E5%8A%A1%E5%99%A8/1.htm">服务器</a> <div>PKI及SSL协议分析实验报告一、实验目的通过该实验了解和掌握证书服务的安装,理解证书的发放过程,掌握在WEB服务器上配置SSL,使用HTTPS协议访问网站以验证结果,最后对HTTPS协议进行分析。二、实验环境WindowServer*2本实验中自己指定CA服务器与申请证书的网站。实验过程中建议使用IE浏览器,如果不使用IE,可能会导致后续实验过程中证书不能下载。三、实验内容与实验要求实验内容、原</div> </li> <li><a href="/article/1901024209631506432.htm" title="自动同步多服务器下SQL脚本3.0" target="_blank">自动同步多服务器下SQL脚本3.0</a> <span class="text-muted">a栋栋栋</span> <a class="tag" taget="_blank" href="/search/%E9%81%87%E5%88%B0%E7%9A%84%E9%97%AE%E9%A2%98/1.htm">遇到的问题</a><a class="tag" taget="_blank" href="/search/sql/1.htm">sql</a><a class="tag" taget="_blank" href="/search/%E8%87%AA%E5%8A%A8%E5%8C%96/1.htm">自动化</a><a class="tag" taget="_blank" href="/search/%E4%BA%8B%E5%8A%A1%E5%A4%B1%E6%95%88/1.htm">事务失效</a> <div>由于上一版发现数据库【MySQL】不支持DML事务回滚,该迭代主要是去兼容这种问题。数据表新增一个completed字段,用来表示当前版本下同步成功的个数。数据表CREATETABLE`auto_sql_version`(`id`intNOTNULLAUTO_INCREMENT,`version`varchar(20)CHARACTERSETutf8mb4COLLATEutf8mb4_0900_a</div> </li> <li><a href="/article/1901024083332624384.htm" title="云计算、边缘计算与雾计算" target="_blank">云计算、边缘计算与雾计算</a> <span class="text-muted">白小白呀</span> <a class="tag" taget="_blank" href="/search/%E7%AC%94%E8%AE%B0/1.htm">笔记</a><a class="tag" taget="_blank" href="/search/%E5%A4%A7%E6%95%B0%E6%8D%AE/1.htm">大数据</a> <div>云计算(数据上传到云端进行处理)云计算(CloudComputing)是一种基于互联网的计算方式,通过这种方式,共享的软硬件资源和信息可以按需提供给计算机和其他设备。通俗的讲,云是网络、互联网的一种比喻说法,即互联网与建立互联网所需要的底层基础设施的抽象体。“计算”指的是一台足够强大的计算机提供的计算服务(包括各种功能,资源,存储)。“云计算”可以理解为:通过互联网可以使用足够强大的计算机为用户提</div> </li> <li><a href="/article/1901020550696857600.htm" title="【PCDN】2020架构: 提高穿透和分享、BGP协议" target="_blank">【PCDN】2020架构: 提高穿透和分享、BGP协议</a> <span class="text-muted">等风来不如迎风去</span> <a class="tag" taget="_blank" href="/search/%E4%BC%A0%E8%BE%93%E6%8E%A2%E7%B4%A2%E5%AE%9E%E8%B7%B5/1.htm">传输探索实践</a><a class="tag" taget="_blank" href="/search/%E6%9E%B6%E6%9E%84/1.htm">架构</a><a class="tag" taget="_blank" href="/search/%E6%9C%8D%E5%8A%A1%E5%99%A8/1.htm">服务器</a><a class="tag" taget="_blank" href="/search/%E8%BF%90%E7%BB%B4/1.htm">运维</a> <div>小溪流科技自研海外PCDN系统技术架构与演进转载自腾讯云文/张道远整理/核心组网我们自己的P2P组网模型。我们采用了树形组网,但是我们规避优化了传统树形模型的缺点。为防止延时过高,我们在调度时会严格控制树形高度。为弥补父节点掉线造成孤儿状态的不足,我们使系统中每个节点都首先从CDN拉流。如果出现父节点掉线的情况,它立即向服务器补片,同时触发新的组网。对于纯粹的消费者模型,我们目前有两种方案,其中一</div> </li> <li><a href="/article/1901019035911385088.htm" title="大语言模型原理与工程实践:大语言模型强化对齐" target="_blank">大语言模型原理与工程实践:大语言模型强化对齐</a> <span class="text-muted">AGI大模型与大数据研究院</span> <a class="tag" taget="_blank" href="/search/DeepSeek/1.htm">DeepSeek</a><a class="tag" taget="_blank" href="/search/R1/1.htm">R1</a><a class="tag" taget="_blank" href="/search/%26amp%3B/1.htm">&</a><a class="tag" taget="_blank" href="/search/%E5%A4%A7%E6%95%B0%E6%8D%AEAI%E4%BA%BA%E5%B7%A5%E6%99%BA%E8%83%BD/1.htm">大数据AI人工智能</a><a class="tag" taget="_blank" href="/search/%E8%AE%A1%E7%AE%97%E7%A7%91%E5%AD%A6/1.htm">计算科学</a><a class="tag" taget="_blank" href="/search/%E7%A5%9E%E7%BB%8F%E8%AE%A1%E7%AE%97/1.htm">神经计算</a><a class="tag" taget="_blank" href="/search/%E6%B7%B1%E5%BA%A6%E5%AD%A6%E4%B9%A0/1.htm">深度学习</a><a class="tag" taget="_blank" href="/search/%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/1.htm">神经网络</a><a class="tag" taget="_blank" href="/search/%E5%A4%A7%E6%95%B0%E6%8D%AE/1.htm">大数据</a><a class="tag" taget="_blank" href="/search/%E4%BA%BA%E5%B7%A5%E6%99%BA%E8%83%BD/1.htm">人工智能</a><a class="tag" taget="_blank" href="/search/%E5%A4%A7%E5%9E%8B%E8%AF%AD%E8%A8%80%E6%A8%A1%E5%9E%8B/1.htm">大型语言模型</a><a class="tag" taget="_blank" href="/search/AI/1.htm">AI</a><a class="tag" taget="_blank" href="/search/AGI/1.htm">AGI</a><a class="tag" taget="_blank" href="/search/LLM/1.htm">LLM</a><a class="tag" taget="_blank" href="/search/Java/1.htm">Java</a><a class="tag" taget="_blank" href="/search/Python/1.htm">Python</a><a class="tag" taget="_blank" href="/search/%E6%9E%B6%E6%9E%84%E8%AE%BE%E8%AE%A1/1.htm">架构设计</a><a class="tag" taget="_blank" href="/search/Agent/1.htm">Agent</a><a class="tag" taget="_blank" href="/search/RPA/1.htm">RPA</a> <div>大语言模型原理与工程实践:大语言模型强化对齐作者:禅与计算机程序设计艺术/ZenandtheArtofComputerProgramming1.背景介绍1.1问题的由来随着人工智能技术的迅猛发展,大语言模型(LargeLanguageModels,LLMs)如GPT-3、LaMDA等,在自然语言处理(NLP)领域取得了显著的突破。这些模型在问答、翻译、文本生成等方面展现出惊人的能力,但同时也引发了</div> </li> <li><a href="/article/1901018532175474688.htm" title="LLM对齐方法作用:主要解决大型语言模型(LLMs)输出与人类价值观、需求和安全规范不一致的问题" target="_blank">LLM对齐方法作用:主要解决大型语言模型(LLMs)输出与人类价值观、需求和安全规范不一致的问题</a> <span class="text-muted">ZhangJiQun&MXP</span> <a class="tag" taget="_blank" href="/search/2021/1.htm">2021</a><a class="tag" taget="_blank" href="/search/AI/1.htm">AI</a><a class="tag" taget="_blank" href="/search/python/1.htm">python</a><a class="tag" taget="_blank" href="/search/2024%E5%A4%A7%E6%A8%A1%E5%9E%8B%E4%BB%A5%E5%8F%8A%E7%AE%97%E5%8A%9B/1.htm">2024大模型以及算力</a><a class="tag" taget="_blank" href="/search/2021%E6%95%B0%E5%AD%97%E4%BA%A4%E6%98%93%E6%95%B0%E5%AD%97%E8%B5%84%E4%BA%A7/1.htm">2021数字交易数字资产</a><a class="tag" taget="_blank" href="/search/%E8%AF%AD%E8%A8%80%E6%A8%A1%E5%9E%8B/1.htm">语言模型</a><a class="tag" taget="_blank" href="/search/%E5%AE%89%E5%85%A8/1.htm">安全</a><a class="tag" taget="_blank" href="/search/%E4%BA%BA%E5%B7%A5%E6%99%BA%E8%83%BD/1.htm">人工智能</a><a class="tag" taget="_blank" href="/search/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0/1.htm">机器学习</a><a class="tag" taget="_blank" href="/search/%E8%87%AA%E7%84%B6%E8%AF%AD%E8%A8%80%E5%A4%84%E7%90%86/1.htm">自然语言处理</a><a class="tag" taget="_blank" href="/search/%E7%AE%97%E6%B3%95/1.htm">算法</a> <div>LLM对齐方法作用:主要解决大型语言模型(LLMs)输出与人类价值观、需求和安全规范不一致的问题对齐方法(AlignmentMethods)主要解决大型语言模型(LLMs)输出与人类价值观、需求和安全规范不一致的问题。其核心目标是让模型生成的内容更符合人类预期,同时确保伦理合规性和实用性。以下是对齐方法解决的具体问题及典型场景:1.安全性与伦理问题问题:基础LLMs可能生成有害内容(如暴力、歧视、</div> </li> <li><a href="/article/1901018405771735040.htm" title="Redis 常用数据类型" target="_blank">Redis 常用数据类型</a> <span class="text-muted">27xixi</span> <a class="tag" taget="_blank" href="/search/java%E6%8A%80%E6%9C%AF%E6%A0%88/1.htm">java技术栈</a><a class="tag" taget="_blank" href="/search/redis/1.htm">redis</a><a class="tag" taget="_blank" href="/search/%E6%95%B0%E6%8D%AE%E5%BA%93/1.htm">数据库</a><a class="tag" taget="_blank" href="/search/%E7%BC%93%E5%AD%98/1.htm">缓存</a> <div>Redis常用数据类型的详细介绍及其典型应用场景:String(字符串)描述:最基本的数据类型,可存储文本、数字或二进制数据(最大512MB)。常用命令:SETkeyvalue:设置值GETkey:获取值INCRkey:将值自增1(原子性操作)EXPIREkeyseconds:设置过期时间应用场景:缓存简单键值对(如用户会话、配置项)。计数器(如文章阅读量、库存扣减)。分布式锁(结合SETNX命令</div> </li> <li><a href="/article/1901017397758849024.htm" title="【HarmonyOS NEXT 】应用开发:使用@ohos.net.webSocket发送webSocket" target="_blank">【HarmonyOS NEXT 】应用开发:使用@ohos.net.webSocket发送webSocket</a> <span class="text-muted">纳米小川</span> <a class="tag" taget="_blank" href="/search/HarmonyOS/1.htm">HarmonyOS</a><a class="tag" taget="_blank" href="/search/harmonyos/1.htm">harmonyos</a><a class="tag" taget="_blank" href="/search/.net/1.htm">.net</a><a class="tag" taget="_blank" href="/search/websocket/1.htm">websocket</a> <div>@ohos.net.webSocket模块可以建立WebSocket连接,实现与服务器之间的实时双向通信。WebSocket提供了一种低延迟的通信方式,非常适合实时应用,如聊天应用、在线游戏等。下面是使用@ohos.net.webSocket模块建立WebSocket连接的步骤:1、添加权限确保在config.json文件中添加了网络访问权限:{"name":"com.example.myappl</div> </li> <li><a href="/article/1901017145060421632.htm" title="python高并发访问mysql_Python访问MySQL" target="_blank">python高并发访问mysql_Python访问MySQL</a> <span class="text-muted">阿廖林诺</span> <div>Python访问数据库作为Python开发工程师,选择哪个数据库呢?当然是MySQL。因为MySQL不仅免费,普及率最高,出了错,可以很容易找到解决方法。而且,围绕MySQL有一大堆监控和运维的工具,安装和使用很方便。使用MySQLMySQL是Web世界中使用最广泛的数据库服务器。SQLite的特点是轻量级、可嵌入,但不能承受高并发访问,适合桌面和移动应用。而MySQL是为服务器端设计的数据库,能</div> </li> <li><a href="/article/1901017015540314112.htm" title="Redis 源码分析-内部数据结构 quicklist" target="_blank">Redis 源码分析-内部数据结构 quicklist</a> <span class="text-muted">笨手笨脚の</span> <a class="tag" taget="_blank" href="/search/%23/1.htm">#</a><a class="tag" taget="_blank" href="/search/Redis/1.htm">Redis</a><a class="tag" taget="_blank" href="/search/redis/1.htm">redis</a><a class="tag" taget="_blank" href="/search/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/1.htm">数据结构</a><a class="tag" taget="_blank" href="/search/%E6%95%B0%E6%8D%AE%E5%BA%93/1.htm">数据库</a><a class="tag" taget="_blank" href="/search/quicklist/1.htm">quicklist</a><a class="tag" taget="_blank" href="/search/%E9%93%BE%E8%A1%A8/1.htm">链表</a><a class="tag" taget="_blank" href="/search/%E5%BF%AB%E9%80%9F%E9%93%BE%E8%A1%A8/1.htm">快速链表</a><a class="tag" taget="_blank" href="/search/ziplist/1.htm">ziplist</a> <div>Redis源码分析-内部数据结构quicklistquicklist是Redis对外暴露的list数据结构的内部实现,经常被当作队列或栈使用,我们可以从常用的一些api上先思考一下它的结构最常用的就是lpush、lpop、rpush、rpop,同时它也支持lindex查询某元素在list中的索引,linsert在指定元素旁边插入新元素。从头、尾节点的push、pop来看,这就是双向链表最优秀的设计</div> </li> <li><a href="/article/1901015756703854592.htm" title="【AI热点】Manus技术细致洞察报告(篇2)" target="_blank">【AI热点】Manus技术细致洞察报告(篇2)</a> <span class="text-muted">碣石潇湘无限路</span> <a class="tag" taget="_blank" href="/search/%E4%BA%BA%E5%B7%A5%E6%99%BA%E8%83%BD/1.htm">人工智能</a> <div>针对大家对Manus产品褒贬不一的现象,基于近期对Manus的多方实测、公开信息与开源竞品的比对分析而撰写,旨在为从业者、技术爱好者以及潜在用户提供一个较为系统、专业的视角。报告将围绕Manus的核心原理、功能特点、技术亮点、常见应用场景与不足,以及与其他Agent产品和开源方案的对比进行深入探讨。1.引言与背景1.1产品崛起与「全自主通用Agent」的概念自2023年底至2024年初,大模型及其</div> </li> <li><a href="/article/1901012983962726400.htm" title="Python 爬取大量数据如何并发抓取与性能优化" target="_blank">Python 爬取大量数据如何并发抓取与性能优化</a> <span class="text-muted">chusheng1840</span> <a class="tag" taget="_blank" href="/search/Python/1.htm">Python</a><a class="tag" taget="_blank" href="/search/%E6%95%99%E7%A8%8B/1.htm">教程</a><a class="tag" taget="_blank" href="/search/python/1.htm">python</a><a class="tag" taget="_blank" href="/search/%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96/1.htm">性能优化</a><a class="tag" taget="_blank" href="/search/%E5%BC%80%E5%8F%91%E8%AF%AD%E8%A8%80/1.htm">开发语言</a> <div>Python并发抓取与性能优化在进行网络爬虫开发时,爬取大量数据可能非常耗时。尤其是在处理许多网页或API请求时,逐个请求速度会非常慢。为了解决这个问题,我们可以通过并发抓取提高爬取效率。同时,通过性能优化来进一步减少耗时和资源占用,使爬虫更高效。本篇文章将带大家了解Python中常用的并发抓取方法,并介绍如何进行性能优化。1.并发抓取的基本概念并发抓取指的是同时发出多个请求的技术,而不是顺序地等</div> </li> <li><a href="/article/1901012480218427392.htm" title="安科瑞ACCU-100微电网协调控制器:助力绿色能源系统运行" target="_blank">安科瑞ACCU-100微电网协调控制器:助力绿色能源系统运行</a> <span class="text-muted">安科瑞蒋静</span> <a class="tag" taget="_blank" href="/search/%E8%83%BD%E6%BA%90/1.htm">能源</a> <div>随着全球能源结构的转型和可再生能源的快速发展,微电网作为一种新型的电力系统,逐渐成为解决分布式能源接入、提高能源利用效率的重要手段。微电网不仅能够实现新能源的就地消纳,还能有效提高电网的稳定性和可靠性。在这一背景下,安科瑞电气股份有限公司推出的ACCU-100微电网协调控制器,凭借其强大的功能和灵活的配置,成为微电网系统中的核心控制设备。一、产品概述ACCU-100微电网协调控制器是一款应用于微电</div> </li> <li><a href="/article/1901011220790571008.htm" title="【云原生】动态资源分配(DRA)深度洞察报告" target="_blank">【云原生】动态资源分配(DRA)深度洞察报告</a> <span class="text-muted">碣石潇湘无限路</span> <a class="tag" taget="_blank" href="/search/%E4%BA%91%E5%8E%9F%E7%94%9F/1.htm">云原生</a> <div>1.DRA的发展与设计灵感Kubernetes早期通过DevicePlugin(设备插件)机制支持GPU、NIC等特殊硬件,将节点上可用设备数量上报给kubelet和调度器。但设备插件模式存在局限:调度器只能根据节点标签等属性粗粒度筛选,无法精准指定某型号/属性的设备;此外调度器与设备插件缺乏联动,可能把Pod调度到尚未准备好相应设备的节点上。结果就是难以满足复杂场景下对特定硬件的精细化需求。为解</div> </li> <li><a href="/article/13.htm" title="github中多个平台共存" target="_blank">github中多个平台共存</a> <span class="text-muted">jackyrong</span> <a class="tag" taget="_blank" href="/search/github/1.htm">github</a> <div>在个人电脑上,如何分别链接比如oschina,github等库呢,一般教程之列的,默认 ssh链接一个托管的而已,下面讲解如何放两个文件 1) 设置用户名和邮件地址 $ git config --global user.name "xx" $ git config --global user.email "test@gmail.com"</div> </li> <li><a href="/article/140.htm" title="ip地址与整数的相互转换(javascript)" target="_blank">ip地址与整数的相互转换(javascript)</a> <span class="text-muted">alxw4616</span> <a class="tag" taget="_blank" href="/search/JavaScript/1.htm">JavaScript</a> <div>//IP转成整型 function ip2int(ip){ var num = 0; ip = ip.split("."); num = Number(ip[0]) * 256 * 256 * 256 + Number(ip[1]) * 256 * 256 + Number(ip[2]) * 256 + Number(ip[3]); n</div> </li> <li><a href="/article/267.htm" title="读书笔记-jquey+数据库+css" target="_blank">读书笔记-jquey+数据库+css</a> <span class="text-muted">chengxuyuancsdn</span> <a class="tag" taget="_blank" href="/search/html/1.htm">html</a><a class="tag" taget="_blank" href="/search/jquery/1.htm">jquery</a><a class="tag" taget="_blank" href="/search/oracle/1.htm">oracle</a> <div>1、grouping ,group by rollup, GROUP BY GROUPING SETS区别 2、$("#totalTable tbody>tr td:nth-child(" + i + ")").css({"width":tdWidth, "margin":"0px", &q</div> </li> <li><a href="/article/394.htm" title="javaSE javaEE javaME == API下载" target="_blank">javaSE javaEE javaME == API下载</a> <span class="text-muted">Array_06</span> <a class="tag" taget="_blank" href="/search/java/1.htm">java</a> <div>oracle下载各种API文档: http://www.oracle.com/technetwork/java/embedded/javame/embed-me/documentation/javame-embedded-apis-2181154.html JavaSE文档: http://docs.oracle.com/javase/8/docs/api/ JavaEE文档: ht</div> </li> <li><a href="/article/521.htm" title="shiro入门学习" target="_blank">shiro入门学习</a> <span class="text-muted">cugfy</span> <a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/Web/1.htm">Web</a><a class="tag" taget="_blank" href="/search/%E6%A1%86%E6%9E%B6/1.htm">框架</a> <div>声明本文只适合初学者,本人也是刚接触而已,经过一段时间的研究小有收获,特来分享下希望和大家互相交流学习。 首先配置我们的web.xml代码如下,固定格式,记死就成 <filter>         <filter-name>shiroFilter</filter-name> &nbs</div> </li> <li><a href="/article/648.htm" title="Array添加删除方法" target="_blank">Array添加删除方法</a> <span class="text-muted">357029540</span> <a class="tag" taget="_blank" href="/search/js/1.htm">js</a> <div>     刚才做项目前台删除数组的固定下标值时,删除得不是很完整,所以在网上查了下,发现一个不错的方法,也提供给需要的同学。 //给数组添加删除             Array.prototype.del = function(n){ </div> </li> <li><a href="/article/775.htm" title="navigation bar 更改颜色" target="_blank">navigation bar 更改颜色</a> <span class="text-muted">张亚雄</span> <a class="tag" taget="_blank" href="/search/IO/1.htm">IO</a> <div>今天郁闷了一下午,就因为objective-c默认语言是英文,我写的中文全是一些乱七八糟的样子,到不是乱码,但是,前两个自字是粗体,后两个字正常体,这可郁闷死我了,问了问大牛,人家告诉我说更改一下字体就好啦,比如改成黑体,哇塞,茅塞顿开。       翻书看,发现,书上有介绍怎么更改表格中文字字体的,代码如下    </div> </li> <li><a href="/article/902.htm" title="unicode转换成中文" target="_blank">unicode转换成中文</a> <span class="text-muted">adminjun</span> <a class="tag" taget="_blank" href="/search/unicode/1.htm">unicode</a><a class="tag" taget="_blank" href="/search/%E7%BC%96%E7%A0%81%E8%BD%AC%E6%8D%A2/1.htm">编码转换</a> <div>  在Java程序中总会出现\u6b22\u8fce\u63d0\u4ea4\u5fae\u535a\u641c\u7d22\u4f7f\u7528\u53cd\u9988\uff0c\u8bf7\u76f4\u63a5这个的字符,这是unicode编码,使用时有时候不会自动转换成中文就需要自己转换了使用下面的方法转换一下即可。 /** * unicode 转换成 中文 </div> </li> <li><a href="/article/1029.htm" title="一站式 Java Web 框架 firefly" target="_blank">一站式 Java Web 框架 firefly</a> <span class="text-muted">aijuans</span> <a class="tag" taget="_blank" href="/search/Java+Web/1.htm">Java Web</a> <div>Firefly是一个高性能一站式Web框架。 涵盖了web开发的主要技术栈。 包含Template engine、IOC、MVC framework、HTTP Server、Common tools、Log、Json parser等模块。 firefly-2.0_07修复了模版压缩对javascript单行注释的影响,并新增了自定义错误页面功能。 更新日志: 增加自定义系统错误页面功能</div> </li> <li><a href="/article/1156.htm" title="设计模式——单例模式" target="_blank">设计模式——单例模式</a> <span class="text-muted">ayaoxinchao</span> <a class="tag" taget="_blank" href="/search/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/1.htm">设计模式</a> <div>定义          Java中单例模式定义:“一个类有且仅有一个实例,并且自行实例化向整个系统提供。”   分析          从定义中可以看出单例的要点有三个:一是某个类只能有一个实例;二是必须自行创建这个实例;三是必须自行向系统提供这个实例。   &nb</div> </li> <li><a href="/article/1283.htm" title="Javascript 多浏览器兼容性问题及解决方案" target="_blank">Javascript 多浏览器兼容性问题及解决方案</a> <span class="text-muted">BigBird2012</span> <a class="tag" taget="_blank" href="/search/JavaScript/1.htm">JavaScript</a> <div>不论是网站应用还是学习js,大家很注重ie与firefox等浏览器的兼容性问题,毕竟这两中浏览器是占了绝大多数。 一、document.formName.item(”itemName”) 问题 问题说明:IE下,可以使用 document.formName.item(”itemName”) 或 document.formName.elements ["elementName&quo</div> </li> <li><a href="/article/1410.htm" title="JUnit-4.11使用报java.lang.NoClassDefFoundError: org/hamcrest/SelfDescribing错误" target="_blank">JUnit-4.11使用报java.lang.NoClassDefFoundError: org/hamcrest/SelfDescribing错误</a> <span class="text-muted">bijian1013</span> <a class="tag" taget="_blank" href="/search/junit4.11/1.htm">junit4.11</a><a class="tag" taget="_blank" href="/search/%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95/1.htm">单元测试</a> <div>        下载了最新的JUnit版本,是4.11,结果尝试使用发现总是报java.lang.NoClassDefFoundError: org/hamcrest/SelfDescribing这样的错误,上网查了一下,一般的解决方案是,换一个低一点的版本就好了。还有人说,是缺少hamcrest的包。去官网看了一下,如下发现:    </div> </li> <li><a href="/article/1537.htm" title="[Zookeeper学习笔记之二]Zookeeper部署脚本" target="_blank">[Zookeeper学习笔记之二]Zookeeper部署脚本</a> <span class="text-muted">bit1129</span> <a class="tag" taget="_blank" href="/search/zookeeper/1.htm">zookeeper</a> <div>Zookeeper伪分布式安装脚本(此脚本在一台机器上创建Zookeeper三个进程,即创建具有三个节点的Zookeeper集群。这个脚本和zookeeper的tar包放在同一个目录下,脚本中指定的名字是zookeeper的3.4.6版本,需要根据实际情况修改):   #!/bin/bash #!!!Change the name!!! #The zookeepe</div> </li> <li><a href="/article/1664.htm" title="【Spark八十】Spark RDD API二" target="_blank">【Spark八十】Spark RDD API二</a> <span class="text-muted">bit1129</span> <a class="tag" taget="_blank" href="/search/spark/1.htm">spark</a> <div>coGroup package spark.examples.rddapi import org.apache.spark.{SparkConf, SparkContext} import org.apache.spark.SparkContext._ object CoGroupTest_05 { def main(args: Array[String]) { v</div> </li> <li><a href="/article/1791.htm" title="Linux中编译apache服务器modules文件夹缺少模块(.so)的问题" target="_blank">Linux中编译apache服务器modules文件夹缺少模块(.so)的问题</a> <span class="text-muted">ronin47</span> <a class="tag" taget="_blank" href="/search/modules/1.htm">modules</a> <div>在modules目录中只有httpd.exp,那些so文件呢? 我尝试在fedora core 3中安装apache 2. 当我解压了apache 2.0.54后使用configure工具并且加入了 --enable-so 或者 --enable-modules=so (两个我都试过了) 去make并且make install了。我希望在/apache2/modules/目录里有各种模块,</div> </li> <li><a href="/article/1918.htm" title="Java基础-克隆" target="_blank">Java基础-克隆</a> <span class="text-muted">BrokenDreams</span> <a class="tag" taget="_blank" href="/search/java%E5%9F%BA%E7%A1%80/1.htm">java基础</a> <div>        Java中怎么拷贝一个对象呢?可以通过调用这个对象类型的构造器构造一个新对象,然后将要拷贝对象的属性设置到新对象里面。Java中也有另一种不通过构造器来拷贝对象的方式,这种方式称为 克隆。         Java提供了java.lang.</div> </li> <li><a href="/article/2045.htm" title="读《研磨设计模式》-代码笔记-适配器模式-Adapter" target="_blank">读《研磨设计模式》-代码笔记-适配器模式-Adapter</a> <span class="text-muted">bylijinnan</span> <a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/1.htm">设计模式</a> <div>声明: 本文只为方便我个人查阅和理解,详细的分析以及源代码请移步 原作者的博客http://chjavach.iteye.com/ package design.pattern; /* * 适配器模式解决的主要问题是,现有的方法接口与客户要求的方法接口不一致 * 可以这样想,我们要写这样一个类(Adapter): * 1.这个类要符合客户的要求 ---> 那显然要</div> </li> <li><a href="/article/2172.htm" title="HDR图像PS教程集锦&心得" target="_blank">HDR图像PS教程集锦&心得</a> <span class="text-muted">cherishLC</span> <a class="tag" taget="_blank" href="/search/PS/1.htm">PS</a> <div>HDR是指高动态范围的图像,主要原理为提高图像的局部对比度。 软件有photomatix和nik hdr efex。 一、教程 叶明在知乎上的回答: http://www.zhihu.com/question/27418267/answer/37317792 大意是修完后直方图最好是等值直方图,方法是HDR软件调一遍,再结合不透明度和蒙版细调。 二、心得 1、去除阴影部分的</div> </li> <li><a href="/article/2299.htm" title="maven-3.3.3 mvn archetype 列表" target="_blank">maven-3.3.3 mvn archetype 列表</a> <span class="text-muted">crabdave</span> <a class="tag" taget="_blank" href="/search/ArcheType/1.htm">ArcheType</a> <div>maven-3.3.3 mvn archetype 列表 可以参考最新的:http://repo1.maven.org/maven2/archetype-catalog.xml   [INFO] Scanning for projects... [INFO]                 </div> </li> <li><a href="/article/2426.htm" title="linux shell 中文件编码查看及转换方法" target="_blank">linux shell 中文件编码查看及转换方法</a> <span class="text-muted">daizj</span> <a class="tag" taget="_blank" href="/search/shell/1.htm">shell</a><a class="tag" taget="_blank" href="/search/%E4%B8%AD%E6%96%87%E4%B9%B1%E7%A0%81/1.htm">中文乱码</a><a class="tag" taget="_blank" href="/search/vim/1.htm">vim</a><a class="tag" taget="_blank" href="/search/%E6%96%87%E4%BB%B6%E7%BC%96%E7%A0%81/1.htm">文件编码</a> <div>一、查看文件编码。     在打开文件的时候输入:set fileencoding     即可显示文件编码格式。 二、文件编码转换     1、在Vim中直接进行转换文件编码,比如将一个文件转换成utf-8格式       &</div> </li> <li><a href="/article/2553.htm" title="MySQL--binlog日志恢复数据" target="_blank">MySQL--binlog日志恢复数据</a> <span class="text-muted">dcj3sjt126com</span> <a class="tag" taget="_blank" href="/search/binlog/1.htm">binlog</a> <div> 恢复数据的重要命令如下 mysql> flush logs; 默认的日志是mysql-bin.000001,现在刷新了重新开启一个就多了一个mysql-bin.000002                  </div> </li> <li><a href="/article/2680.htm" title="数据库中数据表数据迁移方法" target="_blank">数据库中数据表数据迁移方法</a> <span class="text-muted">dcj3sjt126com</span> <a class="tag" taget="_blank" href="/search/sql/1.htm">sql</a> <div>刚开始想想好像挺麻烦的,后来找到一种方法了,就SQL中的 INSERT 语句,不过内容是现从另外的表中查出来的,其实就是 MySQL中INSERT INTO SELECT的使用   下面看看如何使用   语法:MySQL中INSERT INTO SELECT的使用 1. 语法介绍       有三张表a、b、c,现在需要从表b</div> </li> <li><a href="/article/2807.htm" title="Java反转字符串" target="_blank">Java反转字符串</a> <span class="text-muted">dyy_gusi</span> <a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E5%8F%8D%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2/1.htm">反转字符串</a> <div>       前几天看见一篇文章,说使用Java能用几种方式反转一个字符串。首先要明白什么叫反转字符串,就是将一个字符串到过来啦,比如"倒过来念的是小狗"反转过来就是”狗小是的念来过倒“。接下来就把自己能想到的所有方式记录下来了。 1、第一个念头就是直接使用String类的反转方法,对不起,这样是不行的,因为Stri</div> </li> <li><a href="/article/2934.htm" title="UI设计中我们为什么需要设计动效" target="_blank">UI设计中我们为什么需要设计动效</a> <span class="text-muted">gcq511120594</span> <a class="tag" taget="_blank" href="/search/UI/1.htm">UI</a><a class="tag" taget="_blank" href="/search/linux/1.htm">linux</a> <div>随着国际大品牌苹果和谷歌的引领,最近越来越多的国内公司开始关注动效设计了,越来越多的团队已经意识到动效在产品用户体验中的重要性了,更多的UI设计师们也开始投身动效设计领域。 但是说到底,我们到底为什么需要动效设计?或者说我们到底需要什么样的动效?做动效设计也有段时间了,于是尝试用一些案例,从产品本身出发来说说我所思考的动效设计。 一、加强体验舒适度 嗯,就是让用户更加爽更加爽的用</div> </li> <li><a href="/article/3061.htm" title="JBOSS服务部署端口冲突问题" target="_blank">JBOSS服务部署端口冲突问题</a> <span class="text-muted">HogwartsRow</span> <a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E5%BA%94%E7%94%A8%E6%9C%8D%E5%8A%A1%E5%99%A8/1.htm">应用服务器</a><a class="tag" taget="_blank" href="/search/jboss/1.htm">jboss</a><a class="tag" taget="_blank" href="/search/server/1.htm">server</a><a class="tag" taget="_blank" href="/search/EJB3/1.htm">EJB3</a> <div>服务端口冲突问题的解决方法,一般修改如下三个文件中的部分端口就可以了。   1、jboss5/server/default/conf/bindingservice.beans/META-INF/bindings-jboss-beans.xml   2、./server/default/deploy/jbossweb.sar/server.xml   3、.</div> </li> <li><a href="/article/3188.htm" title="第三章 Redis/SSDB+Twemproxy安装与使用" target="_blank">第三章 Redis/SSDB+Twemproxy安装与使用</a> <span class="text-muted">jinnianshilongnian</span> <a class="tag" taget="_blank" href="/search/ssdb/1.htm">ssdb</a><a class="tag" taget="_blank" href="/search/reids/1.htm">reids</a><a class="tag" taget="_blank" href="/search/twemproxy/1.htm">twemproxy</a> <div>目前对于互联网公司不使用Redis的很少,Redis不仅仅可以作为key-value缓存,而且提供了丰富的数据结果如set、list、map等,可以实现很多复杂的功能;但是Redis本身主要用作内存缓存,不适合做持久化存储,因此目前有如SSDB、ARDB等,还有如京东的JIMDB,它们都支持Redis协议,可以支持Redis客户端直接访问;而这些持久化存储大多数使用了如LevelDB、RocksD</div> </li> <li><a href="/article/3315.htm" title="ZooKeeper原理及使用 " target="_blank">ZooKeeper原理及使用 </a> <span class="text-muted">liyonghui160com</span> <div>           ZooKeeper是Hadoop Ecosystem中非常重要的组件,它的主要功能是为分布式系统提供一致性协调(Coordination)服务,与之对应的Google的类似服务叫Chubby。今天这篇文章分为三个部分来介绍ZooKeeper,第一部分介绍ZooKeeper的基本原理,第二部分介绍ZooKeeper</div> </li> <li><a href="/article/3442.htm" title="程序员解决问题的60个策略" target="_blank">程序员解决问题的60个策略</a> <span class="text-muted">pda158</span> <a class="tag" taget="_blank" href="/search/%E6%A1%86%E6%9E%B6/1.htm">框架</a><a class="tag" taget="_blank" href="/search/%E5%B7%A5%E4%BD%9C/1.htm">工作</a><a class="tag" taget="_blank" href="/search/%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95/1.htm">单元测试</a> <div>根本的指导方针 1. 首先写代码的时候最好不要有缺陷。最好的修复方法就是让 bug 胎死腹中。 良好的单元测试 强制数据库约束 使用输入验证框架 避免未实现的“else”条件 在应用到主程序之前知道如何在孤立的情况下使用   日志 2. print 语句。往往额外输出个一两行将有助于隔离问题。 3. 切换至详细的日志记录。详细的日</div> </li> <li><a href="/article/3569.htm" title="Create the Google Play Account" target="_blank">Create the Google Play Account</a> <span class="text-muted">sillycat</span> <a class="tag" taget="_blank" href="/search/Google/1.htm">Google</a> <div>Create the Google Play Account Having a Google account, pay 25$, then you get your google developer account. References: http://developer.android.com/distribute/googleplay/start.html https://p</div> </li> <li><a href="/article/3696.htm" title="JSP三大指令" target="_blank">JSP三大指令</a> <span class="text-muted">vikingwei</span> <a class="tag" taget="_blank" href="/search/jsp/1.htm">jsp</a> <div>JSP三大指令   一个jsp页面中,可以有0~N个指令的定义! 1. page --> 最复杂:<%@page language="java" info="xxx"...%>   * pageEncoding和contentType:     > pageEncoding:它</div> </li> </ul> </div> </div> </div> <div> <div class="container"> <div class="indexes"> <strong>按字母分类:</strong> <a href="/tags/A/1.htm" target="_blank">A</a><a href="/tags/B/1.htm" target="_blank">B</a><a href="/tags/C/1.htm" target="_blank">C</a><a href="/tags/D/1.htm" target="_blank">D</a><a href="/tags/E/1.htm" target="_blank">E</a><a href="/tags/F/1.htm" target="_blank">F</a><a href="/tags/G/1.htm" target="_blank">G</a><a href="/tags/H/1.htm" target="_blank">H</a><a href="/tags/I/1.htm" target="_blank">I</a><a href="/tags/J/1.htm" target="_blank">J</a><a href="/tags/K/1.htm" target="_blank">K</a><a href="/tags/L/1.htm" target="_blank">L</a><a href="/tags/M/1.htm" target="_blank">M</a><a href="/tags/N/1.htm" target="_blank">N</a><a href="/tags/O/1.htm" target="_blank">O</a><a href="/tags/P/1.htm" target="_blank">P</a><a href="/tags/Q/1.htm" target="_blank">Q</a><a href="/tags/R/1.htm" target="_blank">R</a><a href="/tags/S/1.htm" target="_blank">S</a><a href="/tags/T/1.htm" target="_blank">T</a><a href="/tags/U/1.htm" target="_blank">U</a><a href="/tags/V/1.htm" target="_blank">V</a><a href="/tags/W/1.htm" target="_blank">W</a><a href="/tags/X/1.htm" target="_blank">X</a><a href="/tags/Y/1.htm" target="_blank">Y</a><a href="/tags/Z/1.htm" target="_blank">Z</a><a href="/tags/0/1.htm" target="_blank">其他</a> </div> </div> </div> <footer id="footer" class="mb30 mt30"> <div class="container"> <div class="footBglm"> <a target="_blank" href="/">首页</a> - <a target="_blank" href="/custom/about.htm">关于我们</a> - <a target="_blank" href="/search/Java/1.htm">站内搜索</a> - <a target="_blank" href="/sitemap.txt">Sitemap</a> - <a target="_blank" href="/custom/delete.htm">侵权投诉</a> </div> <div class="copyright">版权所有 IT知识库 CopyRight © 2000-2050 E-COM-NET.COM , All Rights Reserved. <!-- <a href="https://beian.miit.gov.cn/" rel="nofollow" target="_blank">京ICP备09083238号</a><br>--> </div> </div> </footer> <!-- 代码高亮 --> <script type="text/javascript" src="/static/syntaxhighlighter/scripts/shCore.js"></script> <script type="text/javascript" src="/static/syntaxhighlighter/scripts/shLegacy.js"></script> <script type="text/javascript" src="/static/syntaxhighlighter/scripts/shAutoloader.js"></script> <link type="text/css" rel="stylesheet" href="/static/syntaxhighlighter/styles/shCoreDefault.css"/> <script type="text/javascript" src="/static/syntaxhighlighter/src/my_start_1.js"></script> </body> </html>