首页 文章 精选 留言 我的

精选列表

搜索[监督学习],共10000篇文章
优秀的个人博客,低调大师

机器学习算法之BIRCH

BIRCH(BalancedIterative Reducing and Clustering Using Hierarchies)全称是:利用层次方法的平衡迭代规约和聚类。BIRCH算法是1996年由TianZhang提出来的。Birch算法就是通过聚类特征(CF)形成一个聚类特征树,root层的CF个数就是聚类个数。 BIRCH算法实现分为4个步骤: 1、扫描所有数据,建立初始化的CF树,把稠密数据分成簇,稀疏数据作为孤立点对待。 2、这个步骤是可选的,步骤3的全局或半全局聚类算法有着输入范围的要求,以达到速度与质量的要求,所以此阶段在步骤1的基础上,建立一个更小的CF树。 3、补救由于输入顺序和页面大小带来的分裂,使用全局/半全局算法对全部叶节点进行聚类。 4、这个步骤也是可选的,把步骤3的中心点作为种子,将数据点重新分配到最近的种子上,保证重复数据分到同一个簇中,同时添加簇标签。 聚类特征(CF):每一个CF都是一个三元组,可以用(N,LS,SS)表示。其中N代表了这个CF中拥有的样本点的数量;LS代表了这个CF中拥有的样本点各特征维度的和向量,SS代表了这个CF中拥有的样本点各特征维度的平方和。 比如:CF中含有N=5个点,以两维样本点值为:(3,4)、(2,6)、(4,5)、(4,7)、(3,8)。 然后计算: LS=(3+2+4+4+3,4+6+5+7+8)=(16,30) SS=(32+22+42+42+32,42+62+52+72+82)=(54,190) 对于上图中的CF Tree,限定了B=7,L=5,也就是说内部节点最多有7个CF(含有的分支点数目),而叶子节点最多有5个CF(每个叶子还有的CF个数,实际上就是每个叶子中包含的样本数目)。叶子节点是通过双向链表连通的。 BIRCH算法举例: Birch算法在sklearn.cluster中 具体代码如下 #coding = utf-8##算法涉及主要参数##n_clusters:簇数##threshold :扫描阈值##branches_factors: 每个节点中CF子集群的最大数量,默认值为50##最后通过读取:label_;来获知每个数据点的分类情况import numpy as npimport matplotlib.pyplot as pltfrom sklearn.datasets.samples_generator import make_blobsfrom sklearn.cluster import Birch## X为样本特征,Y为样本簇类别,共500个样本,每个样本2个特征,共4个簇,## 簇中心在[-1,-1],[0,0],[1,1],[2,2]X,Y = make_blobs(n_samples = 500,n_features = 2, centers=[[-1,-1],[0,0],[1,1],[2,2]], cluster_std=[0.5,0.4,0.5,0.4],random_state=9)##设置birch函数birch = Birch(n_clusters = None)##训练数据y_pred = birch.fit_predict(X)##绘图plt.figure()plt.subplot(2,2,1)plt.scatter(X[:,0],X[:,1])plt.title('DataSample')plt.subplot(2,2,2)plt.scatter(X[:,0],X[:,1],c=y_pred)plt.title('None')##设置birch函数birch =Birch(n_clusters = 4)##训练数据y_pred =birch.fit_predict(X)plt.subplot(2,2,3)plt.scatter(X[:,0], X[:, 1], c=y_pred)plt.title('n_clusters=4')plt.show() 最后的效果:

优秀的个人博客,低调大师

java学习记录-树结构

概念 树是一种重要的非线性数据结构,直观地看,它是数据元素(在树中称为结点)按分支关系组织起来的结构,很象自然界中的树那样。 树是由结点或顶点和边组成的(可能是非线性的)且不存在着任何环的一种数据结构。没有结点的树称为空(null或empty)树。一棵非空的树包括一个根结点,还(很可能)有多个附加结点,所有结点构成一个多级分层结构 结点:下面就是一个简单的树,每一个元素都称为一个结点,而最顶端的是根结点,最末端的是叶子结点, 每个结点有零个或多个子结点;每一个非根结点有且只有一个父结点;除了根结点外,每个子结点可以分为多个不相交的子树 度:度就是一棵树里面最大的宽度,下图树(包含子树)的子结点数最大都不超过2所以该树的度为2 深度:由根结点到叶子结点组成该树各结点的最大层次 二叉树 二叉树又分为二叉查找树、完全二叉树、满二叉树、平衡二叉树、红黑树、B树 为什么二叉树也还要区分那么多种类型?因为单种二叉树不能完全保证我们运行或储存效率,所以需要多种类型二叉树应对不同的使用场景 下面先看一下二叉查找树 录入的顺序 为 E-->F-->C-->B-->D-->A--G 二叉树与树的区别 1.树的度没有限制,二叉树的度最大为2 2.二叉树每个子树都是有序的,例如二叉树的左子树如果非空,左子树所以结点的值都小于根节点的值,如果右子树非空,则右子树所有结点的值都大于根结点的值(左小右大) 因为二叉树左小右大的特点,所以二叉查找树有个比较极端的情况 录入的顺序 为 A-->B-->C-->D-->E 从小到大的开始录入,大的永远在右边,就造成了右斜树,与链表(线性结构)一样这种树并不能保证我们的运行效率 平衡二叉树(AVL树) 平衡二叉树是基于二叉查找树优化而来的 录入顺序: A-->B-->C-->D-->E-->F 录入顺序与一般二叉树一样,都是从小到大开始录入,但是平衡二叉树每次插入数据会判断数据的大小,从而进行左右旋转,使得我们的数据分布均匀,保证了一定的运行效率 平衡二叉树与二叉查找树的区别主要体现在二叉查找树的根结点不能变,平衡二叉树为了保证根结点左右子树的层级差不超过1,所以会进行左右旋转操作,这个时候根结点就会发生改变 优点:因为左右子树结点数量相差较少,所以查询速度极快 缺点:插入数据时候因为旋转次数不确定,所以插速度会相对慢 红黑树 性质: 1. 节点是红色或黑色。 2. 根节点是黑色。 3 每个红色节点的两个子节点都是黑色。(从每个叶子到根的所有路径上不能有两个连续的红色节点) 4. 从任一节点到其每个叶子的所有路径都包含相同数目的黑色节点 红黑树与平衡二叉树相似,平衡二叉树基于 根结点左右子树的层级差不超过1 进行旋转操作,而红黑树则是基于 没有任何一条路径比其他路径长两倍以上进行(旋转次数不超过3次,新增不超过2次,删除不超过3次)旋转 录入顺序: A-->B-->C-->D-->E-->F-->G 录入顺序: A-->B-->C-->D-->E-->F-->G-->H 由第一张红黑树图可以看出,红黑树的平衡度并没有AVL树平衡度那么严格(只保持黑结点平衡)由于旋转次数是保证在3以内的,所以插入或删除结点时候性能要比平衡二叉树好 B树 ---Balance-tree(平衡多路查找树) 下面是一棵三阶的B树 录入顺序: A-->B-->C-->D-->E-->F-->G-->H 阶:每个B树都有个指定的阶(M),阶决定了每个结点最多拥有多少个子结点,例如三阶B树每个结点最多只能拥有三个子结点 阶与度不一样,上图树的度为2,阶为3,但是阶决定度的最大值 关键字:例如每一个结点里面的值就是一个关键字,例如,该结点就有2个关键字,G和H B树的性质 1.每个结点里面的关键字数量最多为M-1,根节点最少可以只有1个关键字,非根节点至少有M/2(上取整)个关键字。 2.每个结点至少有2个子结点,叶子结点除外 3.除根结点以外的所有结点(不包括叶子结点)的度数正好是关键字总数加1 4.B树的叶子结点都是在同一层 例如现在要录入一个A-E的三阶B树 先录入A和B 接下来要录入C,因为根结点的关键字数量为1到M-1和每个结点至少有2个子结点,所以录入C的时候应该B作为根结点,A和C作为子结点 插入D 插入E 插入元素时,如果树结构不满足B树的性质时,就会进行合并或分裂 B树与二叉树的比较 下面使用元素相同的平衡二叉树(二叉树里面查询快)与B树的查询作比较 平衡二叉树查询 H 第一步 第二步 第三步 第四步 B树查询 H 第一步 第二步 第三步 第四步 虽然看上去都是需要四步才能完成H的查询,因为树结构是非线性的,每个结点的地址是不连续的,所以B树的第四步是在一块内存内比较,要比平衡二叉树的第四步重新寻找地址快很多,并且,如果数据是存放在磁盘而不是内存的时候,每次IO操作性能消耗非常大,且随着数据量增大,两者的性能差距更加明显 B+树 B+树与B树的区别在于B+树每一个元素都存在于叶子结点,非叶子结点仅仅提供索引操作,必须到叶子结点才会命中 这样保证了我们寻找任意一个元素时,所需要的时间都是一样的 并且叶子结点以链表形式连接,这样有利于遍历所有数据时候,只需要进行线性查询,而不用一层一层遍历

优秀的个人博客,低调大师

AIoT 开发学习资料汇总

一、阿里云 AIoT 产品/资源矩阵 先盘点一下有哪些可用的产品和服务,以便快速集成,搭建出高可靠应用。 设备服务 设备接入服务 提供安全可靠的设备连接通信能力,帮助用户将海量设备数据采集到阿里云物联网平台,并且客户应用可以通过调用平台提供的 API 下发数据给设备,实现远程控制海量设备的目的。物联网平台还提供了与阿里云众多产品打通的规则引擎,帮助用户将应用快速集成。 AliOS Things(开源 AIoT 操作系统) 丨 GitHub 项目主页丨钉钉群:开发交流 AliOS Things 是 AliOS 家族旗下、面向 IoT 领域的、高可伸缩的物联网操作系统。 设备身份认证 物联网设备身份认证系统,通过可信计算和密码技术为物联网系统提供设备安全认证、安全连接、业务数据加密、密钥管理等端到端的可信接入能力。 物联网云服务 物联网平台 物联网平台提供

优秀的个人博客,低调大师

MongoDB学习:备份恢复(一)

本文主要介绍MongoDB副本集备份恢复的方法、常用命令,以及一些具体的操作过程,最后介绍一种备份方案。 一、备份方法 0、oplog 0.1oplog是什么oplog是一个 capped collection(有上限的集合),位于local库里 0.2local库local库是MongoDB的系统库,记录着时间戳和索引和复制集等信息0.2.1没有建立副本集的时候 > show collections startup_log 0.2.2建立的副本集之后(3.4、3.6和4.0都是这些集合) replSet27017:PRIMARY> use local switched to db local replSet27017:PRIMARY> show collections me #me集合保存了服务器名称 oplog.rs #oplog.rs集合记录对节点的所有操作 replset.election replset.minvalid #replset.minvalid集合保存了数据库最新操作的时间戳 replset.oplogTruncateAfterPoint startup_log #startup_log集合记录这mongod每一次的启动信息 system.replset #system.replset记录着复制集的成员配置信息,rs.conf()读取这个集合 system.rollback.id 0.3查看oplog0.3.1oplog字段说明 replSet27017:PRIMARY> db.oplog.rs.find().pretty().limit(1) { "ts" : Timestamp(1558940829, 599), "t" : NumberLong(12), "h" : NumberLong("6800425020320237930"), "v" : 2, "op" : "i", "ns" : "config.system.sessions", "ui" : UUID("10b4d6ac-37df-4586-8a2d-83a3389d7406"), "wall" : ISODate("2019-05-16T08:44:39.629Z"), "o" : { "_id" : { "id" : UUID("fa4f2ff2-8251-4dec-b517-ebcab6db2eca"), "uid" : BinData(0,"LkqZkoMQbGtpaIwmLLkI3wtgnsDvRhwXsdiic1EAMLE=") }, "lastUse" : ISODate("2019-05-16T08:44:39.629Z"), "user" : { "name" : "test@test01" } } ts: 操作时间,8字节的时间戳,由4字节unix timestamp + 4字节自增计数表示(表示某一秒内的第几次操作) h:操作的全局唯一标识 v:oplog版本信息 op:1字节的操作类型 i:插入操作 u:更新操作 d:删除操作 c:执行命令(如createDatabase,dropDatabase) n:空操作,会定期执行以确保时效性 ns:操作针对的集合 o:操作内容 o2:在执行更新操作时的where条件,仅限于update时才有该属性 #查看oplog的信息 replSet27017:PRIMARY> db.printReplicationInfo() configured oplog size:1024MB log length start to end: 1866871secs (518.58hrs) oplog first event time:Tue May 14 2019 23:15:10 GMT+0800 (CST) oplog last event time:Wed Jun 05 2019 13:49:41 GMT+0800 (CST) now:Mon May 20 2019 03:20:48 GMT+0800 (CST) #查看slave的同步状态 replSet27017:PRIMARY> db.printSlaveReplicationInfo() source: 192.168.1.12:27017 syncedTo: Wed Jun 05 2019 13:49:41 GMT+0800 (CST) 0 secs (0 hrs) behind the primary source: 192.168.1.13:27017 syncedTo: Wed Jun 05 2019 13:49:41 GMT+0800 (CST) 0 secs (0 hrs) behind the primary 0.3.2根据操作类型查操作 查询oplog里的insert记录,对应op为i的记录: replSet27017:PRIMARY> db.oplog.rs.find({"op" : "i"}).pretty().limit(3) 查update操作命令: replSet27017:PRIMARY> db.oplog.rs.find({"op" : "u"}).pretty().limit(3) test:PRIMARY> 查delete操作命令: replSet27017:PRIMARY> db.oplog.rs.find({"op" : "d"}).pretty().limit(3) 0.3.3根据时间查询操作 mongodb里的时间 #操作系统时间 #date Mon May 20 02:33:45 CST 2019 #mongo里显示当地时间 replSet27017:PRIMARY> Date() Mon May 20 2019 02:34:21 GMT+0800 (CST) #构建一个格林尼治时间,我们是东八区,所以需要减去8个小时 replSet27017:PRIMARY> new Date ISODate("2019-05-19T18:34:24.157Z") #也是格林尼治时间 replSet27017:PRIMARY> ISODate() ISODate("2019-05-19T18:34:28.820Z") #时间戳 ISODate().valueOf() 1558291032161 1、复制文件 1.1 文件系统快照要创建一致的备份,必须锁定数据库,并且必须在备份过程中暂停对数据库的所有写入;快照反映了所有的数据和journal log开始的时刻,没有增量备份。1.1.1 使用LVM创建快照 lvcreate --size 100M --snapshot --name mdb-snap01 /dev/vg0/mdb-snap01 --snapshot 创建一个LVM快照--size 快照的上限大小,如果耗尽空间,快照将无法使用 1.1.2 归档快照如将上述快照挂载后压缩 umount /dev/vg0/mdb-snap01 dd if=/dev/vg0/mdb-snap01 | gzip > mdb-snap01.gz 1.1.3 恢复快照 lvcreate --size 1G --name mdb-new vg0 gzip -d -c mdb-snap01.gz | dd of=/dev/vg0/mdb-new mount /dev/vg0/mdb-new /srv/mongodb 将mdb-snap01.gz 解压并放到mdb-new里将mdb-new挂载到 /srv/mongodb目录, 根据需要修改挂载点以对应MongoDB数据文件位置 注意: 还原的快照将具有mongod.lock文件。如果不从快照中删除此文件,MongoDB可能会认为是正常关闭。 如果在启用storage.journal.enabled的情况下运行,并且不使用db.fsyncLock(),则无需删除mongod.lock文件;如果使用db.fsyncLock(),则需要删除mongod.lock文件。 1.1.4 将备份放到远程存储过程与上述相同,只是使用SSH在远程系统上归档和压缩备份。 umount /dev/vg0/mdb-snap01 dd if=/dev/vg0/mdb-snap01 | ssh username@example.com gzip > /opt/backup/mdb-snap01.gz lvcreate --size 1G --name mdb-new vg0 ssh username@example.com gzip -d -c /opt/backup/mdb-snap01.gz | dd of=/dev/vg0/mdb-new mount /dev/vg0/mdb-new /srv/mongodb 1.1.5 大体过程 锁定数据库,使用db.fsyncLock() 执行上述快照备份命令 快照完成,解锁数据库,使用db.fsyncUnlock() 1.2 直接复制文件相比于文件系统快照,直接复制文件更为简单1.2.1 复制数据文件直接cp数据文件无法复制所有的文件,所以需要在备份的时候防止数据文件发生改变,做法也使用fsynclock命令。 replSet27017:PRIMARY> db.fsyncLock() 该命令会锁定(lock)数据库,禁止任何写入,并进行同步(fsync),即将所有的脏页刷到磁盘。Mongod会将之后的所有写操作加入等待队列 cp -R/data1/mongodb27017/* /backup/mongodb27017_20190704 数据复制完成后,解锁数据库: replSet27017:PRIMARY> db.fsyncUnlock(); 注意:如果启用了身份验证,则在调用fsyncLock()和fsynUnlock()期间不要关闭shell。如果断开了连接,则可能无法进行重新连接,并不得不重启mongod。FsyncLok()的设定是在重启后不会保持生效,mongod总是以非锁定模式启动的。 当然,除了使用fsyncLock()外,关闭mongod,复制文件,再启动mongod,也是一种方法。 2、mongodump 与 mongorestore 2.1 mongodump2.1.1 常用参数 -d:数据库名 -c:集合名 -o:要导出的文件名 -q:导出数据的过滤条件 --authenticationDatabase:保存用户凭证的数据库 --gzip:备份时压缩 --oplog:导出的同时生成一个oplog.bson文件,存放在你开始进行dump到dump结束之间所有的oplog 2.1.2常用备份操作 #备份所有库 ./mongodump -h192.168.1.11:27017 -uroot -prootroot --authenticationDatabase admin -o /data/mongodb/backup/full_20190525 #备份test01库 ./mongodump -h192.168.1.11:27017 -uroot -prootroot --authenticationDatabase admin -d test01 -o /data/mongodb/backup/20190525 #备份test01库下 testCollection集合 ./mongodump -h192.168.1.11:27017 -uroot -prootroot --authenticationDatabase admin -d test01 -c testCollection -o /data/mongodb/backup/20190525 2.2 mongorestore2.2.1 常用参数 --drop: 恢复每个集合之前先删除 --oplogReplay: 重放oplog.bson中的操作内容 --oplogLimit: 与--oplogReplay一起使用时,可以限制重放到的时间点 2.3 模拟不断插入操作过程中备份和恢复(恢复到单节点)模拟不断插入集合test.table use test1 for(var i = 0; i < 10000; i++) { db.test.table.insert({a: i}); } 在插入过程中mongodump备份并指定--oplog: ./mongodump -vv -h127.0.0.1:27017 -uroot -prootroot --authenticationDatabase admin --oplog -o /data/mongodb/backup 恢复test1库(在一个单节点恢复) ./mongorestore -h127.0.0.1:27018 -d test1 /data/backup1/test1 查看插入了多少条 > db.test.table.count() 4029 应用插入期间记录的oplogmongorestore -vv -h127.0.0.1:27018 --oplogReplay /data/backup1查看应用了oplog后插入了多少条(说明这些是在备份期间插入的) > db.test.table.count() 4044 注意:--oplog选项只对全库导出有效,所以不能指定-d选项 查看oplog.bson内容 ./bsondump /data/mongodb/backup1/oplog.bson 3、mongoexport 与 mongoimport 3.1 mongoexport参数: -csv:指明要导出为csv格式 -f:指明需要导的字段 备份集合collection1 ./mongoexport -h 192.168.1.12:27017 -uroot -prootroot --authenticationDatabase admin -d db01 -c collection1 -o /data/mongodb/backup1/collection1.json 导出的数据 {"_id":{"$oid":"5cf8c674bd10185cb185067f"},"name":"hushi","num":0.0} ... 导出为csv格式 ./mongoexport -h 192.168.1.12:27017 -uroot -prootroot --authenticationDatabase admin -d db01 -c collection1 --type=csv -f _id,name,num -o /data/mongodb/backup1/collection1.csv 导出的数据 _id,name,num ObjectId(5cf8c674bd10185cb185067f),hushi,0 ObjectId(5cf8c674bd10185cb185068b),hushi,12 ... 3.2 mongoimport参数: --headerline: 指明第一行是列名,不需要导入 -csv:指明要导入的是csv格式 -f:指明需要导入的字段 恢复之前备份的集合 mongoimport -h192.168.1.14:27018 -d test -c collection1 /data/collection1.json 恢复之前备份的集合 mongoimport -h 127.0.0.1:27018 -d test1 -c collection1 --type=csv --headerline --file /data/collection1.csv 4、Percona Server for MongoDB 4.1 热备原理可以想象成xtrabackup工具 备份: 首先会启动一个后台检测的进程,实时检测MongoDB Oplog的变化,一旦发现oplog有新的日志写入,立刻将日志写入到日志文件WiredTiger.backup中(你可以strings WiredTiger.backup查看oplog操作日志的变化); 复制MongoDB dbpath的数据文件和索引文件到指定的备份目录里; 恢复: 将WiredTiger.backup日志进行回放,将操作日志变更应用到WiredTiger引擎里,最终得到一致性快照恢复;把备份目录里的数据文件直接拷贝到你的dbpath下,然后启动MongoDB即可,会自动接入副本集集群。 4.2 下载安装4.2.1 下载热备由percon的mongodb版本实现,所以可以直接用percona版的mongodb,也可以将percona mongo当做一个副本集的二级节点。https://www.percona.com/downloads/percona-server-mongodb-3.6/LATEST/4.2.2 安装启动因为是要加入副本集,所以修改配置文件并启动: cp mongodb27017/mg27017.conf mongodb27018/mg27018.conf cp ../mongodb27017/mongo.keyfile . ./mongod -f /data1/mongodb27018/mg27018.conf 4.2.3 加入副本集percona 从节点: 在主节点上执行: replSet27017:PRIMARY> rs.add({host: "192.168.1.12:27018", priority: 1, hidden: false}) percona 从变为: > replSet27017:OTHER> 执行slaveOk(),为进行过验证 replSet27017:OTHER> rs.slaveOk() replSet27017:SECONDARY> 4.3 备份从节点进行备份: replSet27017:SECONDARY> use admin switched to db admin replSet27017:SECONDARY> db.runCommand({createBackup: 1, backupDir: "/backup/mongodb_20180704"}) { "ok" : 1, ... 开始备份后,立即开始往一个新集合里写数据: replSet27017:PRIMARY> for (i = 0; i < 10000; i++){ db.test6.save({'name':'hushi','num':i,date:new Date()}); } 备份完成后的数据目录:[root@vm4 /backup/mongodb_20180722]#ll -httotal 240K drwx------ 2 root root 221 Jul 22 14:43 test1 drwx------ 2 root root 4.0K Jul 22 14:43 test01 drwx------ 2 root root 4.0K Jul 22 14:43 test drwx------ 2 root root 4.0K Jul 22 14:43 mms_test drwx------ 2 root root 4.0K Jul 22 14:43 local drwx------ 2 root root 38 Jul 22 14:43 journal drwx------ 2 root root 301 Jul 22 14:43 db01 drwx------ 2 root root 216 Jul 22 14:43 config drwx------ 2 root root 4.0K Jul 22 14:43 admin -rw------- 1 root root 44K Jul 22 14:43 sizeStorer.wt -rw------- 1 root root 114 Jul 22 14:43 storage.bson -rw------- 1 root root 44K Jul 22 14:43 _mdb_catalog.wt -rw------- 1 root root 123K Jul 22 14:43 WiredTiger.backup -rw------- 1 root root 45 Jul 22 14:43 WiredTiger 4.4 恢复恢复都单节点,所以去掉配置文件里面的副本集信息传输rsync -r /backup/mongodb_20180704 192.168.1.13:/backup/ 将文件复制到配置文件目录下cp -R /backup/mongodb_20180704/* /data1/mongodb27018 将keyFile和配置文件也复制过来(也可以直接去掉验证,将security相关的参数都注释)修改配置文件后,启动./mongod -f /data1/mongodb27018/mg27018.conf 发现最后一条数据的日期晚于开始备份日期,所以验证了恢复后会直接进行日志重放 5、MongoDB Cloud Manager 5.1 介绍MongoDB Cloud Manager是官方推出的运维自动化管理系统,是企业版才支持的功能,社区用户也可以下载试用。Cloud Manager 主要功能包括 MongoDB 集群(复制集、分片)的自动化部署 集群监控、及报警定制 自动数据备份与还原 5.2 部署MongoDB Cloud Manager5.2.1 下载agent和安装 curl -OL https://cloud.mongodb.com/download/agent/automation/mongodb-mms-automation-agent-10.2.0.5851-1.rhel7_x86_64.tar.gz tar -xvf mongodb-mms-automation-agent-10.2.0.5851-1.rhel7_x86_64.tar.gz cd mongodb-mms-automation-agent-10.2.0.5851-1.rhel7_x86_64 5.2.2 配置 vi local.config mmsGroupId=5d2f52fc9ccf64f3c73b2188 mmsApiKey= #生成ApiKey mkdir /var/lib/mongodb-mms-automation #创建目录,按照配置文件里的路径 mkdir /var/log/mongodb-mms-automation chown `whoami` /var/lib/mongodb-mms-automation #修改归属 chown `whoami` /var/log/mongodb-mms-automation 5.2.3 启动agent nohup ./mongodb-mms-automation-agent --config=local.config >> /var/log/mongodb-mms-automation/automation-agent-fatal.log 2>&1 & 5.3 进行备份5.3.1 备份原理部署了agent后,会将整个副本集的数据同步到MongoDB的数据中心。初始同步完成后,agent会将加密和压缩的oplog数据流式传输到Cloud Manager,以提供数据的连续备份。 5.3.2 开始备份点击start即可开始备份 可以看到oplog一直是延迟极小的 mongodb的备份,默认6小时一次。然后oplog一直备份,秒级延迟。 备份完成后的数据目录:[root@vm4 /backup/replSet27017]#ll -httotal 288K drwxr-xr-x 2 root root 176 Jul 18 16:04 test1 drwxr-xr-x 2 root root 4.0K Jul 18 16:04 test01 drwxr-xr-x 2 root root 4.0K Jul 18 16:04 test drwxr-xr-x 2 root root 172 Jul 18 16:04 mms_test drwxr-xr-x 2 root root 299 Jul 18 16:04 db01 drwxr-xr-x 2 root root 4.0K Jul 18 16:04 admin -rw-r--r-- 1 root root 114 Jul 18 16:04 storage.bson -rw-r--r-- 1 root root 36K Jul 18 16:04 sizeStorer.wt -rw-r--r-- 1 root root 40K Jul 18 16:04 _mdb_catalog.wt -rw-r--r-- 1 root root 373 Jul 18 16:04 restoreInfo.txt -rw-r--r-- 1 root root 755 Jul 18 16:04 seedSecondary.bat -r-x---r-x 1 root root 768 Jul 18 16:04 seedSecondary.sh -rw-r--r-- 1 root root 4.0K Jul 18 16:04 WiredTigerLAS.wt -rw-r--r-- 1 root root 168K Jul 18 16:04 WiredTiger.wt -rw-r--r-- 1 root root 45 Jul 18 16:04 WiredTiger -rw-r--r-- 1 root root 21 Jul 18 16:04 WiredTiger.lock -rw-r--r-- 1 root root 1.2K Jul 18 16:04 WiredTiger.turtle 下载到本地恢复,可以发现oplog应用点和快照点时间基本是一致的: [root@vm4 /backup/replSet27017]#cat restoreInfo.txt Restore Information Group Name: testProject1 Replica Set: replSet27017 Snapshot timestamp: Thu Jul 18 04:12:24 GMT 2019 Last Oplog Applied: Thu Jul 18 04:12:23 GMT 2019 (1563423143, 1) 可以发现没有local库和journal库,所以不能直接恢复加入到副本集里,更适合数据误删恢复。 5.4 进行恢复5.4.1 恢复原理备份后的文件,是物理文件,下载后的数据是备份结束时刻的数据(应用了备份期间oplog)因为mongodb的备份,默认6小时一次。然后oplog一直备份,秒级延迟。所以恢复的时候有了任何时刻的oplog了。恢复有三种选项: 恢复快照(也就是恢复到备份结束时刻) 恢复到oplog timestamp 恢复到point in time(也是转换成oplog timestamp)5.4.2 开始恢复 在线恢复只能恢复到一个新的副本集 只下载备份,就是备份结束时刻;选择oplog点,就是继续应用oplog 按照上图所示选择时间点,会生成一条对应的命令: ./mongodb-backup-restore-util --host --port --rsId replSet27017 --groupId 5d2d88adf2a30bbee892ef0d --opStart 1563423143:1 --opEnd 1563430620:502 --oplogSourceAddr https://api-backup.us-east-1.mongodb.com --apiKey 是直接调用了mongodb官方的API,应用oplog。mongodb-backup-restore-util 是官方提供的恢复工具。 选择point time: ./mongodb-backup-restore-util --host --port --rsId replSet27017 --groupId 5d2d88adf2a30bbee892ef0d --opStart 1563423143:1 --opEnd 1563429600:0 --oplogSourceAddr https://api-backup.us-east-1.mongodb.com --apiKey 发现生成的命令和选择oplog timestamp是一样的,只是把point time转换成oplog timestamp。 seedSecondary.sh文件:因为mongodb cloud manager提供的全备恢复后没有local库,所以会自动生成一个创建oplog的文件。用于创建oplog,插入一条数据,指定副本集复制的点。 [root@vm4 /backup/replSet27017]#cat seedSecondary.sh #!/bin/sh if [ "$#" -ne 4 ]; then echo "Usage: $0 MONGODB_PORT OPLOG_SIZE_GB RS_NAME PRIMARY_HOST:PRIMARY_PORT" exit 1 fi mongo --port ${1} --eval "var res=db.getSiblingDB('local').runCommand({ create: 'oplog.rs', capped: true, size: (${2} * 1024 * 1024 * 1024)}); if(!res.ok){throw res.errmsg;} else{db.getSiblingDB('local').oplog.rs.insert({ts : Timestamp((db.version().match(/^2\.[012]/) ? 1000 : 1) * 1563423143, 1), h : NumberLong('8796150802864664169'), t : NumberLong('113'), op : 'n', ns : '', o : { msg : 'seed from backup service' }});if (db.getSiblingDB('local').system.replset.count({'_id': '${3}'}) == 0) { db.getSiblingDB('local').system.replset.insert({'_id' : '${3}','version' : 1,'members' : [{'_id' : 0,'host' :'${4}'}],'settings' : {}});}}" 二、备份恢复演练 1、还原到副本集 MongoDB运行了一段时间之后,为了新加一个节点,就需要先将备份数据恢复到一个单节点,再将单节点加入到副本集里,下面将演示使用percona server备份的数据进行还原。1.1 得到全部物理备份 replSet27017:SECONDARY> db.runCommand({createBackup: 1, backupDir: "/backup/mongodb_20180722"}) 开始备份后立即开始往新集合里写数据: replSet27017:PRIMARY> for (i = 0; i < 10000; i++){ db.test5.save({'name':'hushi','num':i,date:new Date()}); } WriteResult({ "nInserted" : 1 }) 将备份传输到新的物理机:rsync -r /backup/mongodb_20180722 192.168.1.14:/backup/ 1.2 进行恢复为了加入到副本集,所以启动的时候直接用配置文件启动,将mg27017.conf和mongo.keyfile复制到本地,再将数据文件复制到配置文件设置的目录下。配置文件进行相应的修改,先将副本集相关的参数去掉启动./mongod -f /data1/mongodb27017/mg27017.conf查看恢复之后最后一条非空的oplog > db.oplog.rs.find({op:{$ne:'n'}}).sort({$natural:-1}).limit(1).pretty() { "ts" : Timestamp(1563777601, 5), "t" : NumberLong(123), "h" : NumberLong("-6583634829168454121"), "v" : 2, "op" : "i", "ns" : "config.system.sessions", "ui" : UUID("10b4d6ac-37df-4586-8a2d-83a3389d7406"), "wall" : ISODate("2019-07-22T06:40:01.172Z"), "o" : { "_id" : { "id" : UUID("9805a821-9a88-43bf-a85d-9a0b63b98632"), "uid" : BinData(0,"Y5mrDaxi8gv8RmdTsQ+1j7fmkr7JUsabhNmXAheU0fg=") }, "lastUse" : ISODate("2019-07-22T06:40:01.175Z"), "user" : { "name" : "root@admin" } } } 发现是系统库的,所以直接查找对test5集合的操作: > db.getSiblingDB('local').oplog.rs.find({op:{$ne:'n'},ns:'mms_test.test5'}).sort({$natural:-1}).limit(1).pretty() { "ts" : Timestamp(1563777479, 674), "t" : NumberLong(123), "h" : NumberLong("6274301431493104273"), "v" : 2, "op" : "i", "ns" : "mms_test.test5", "ui" : UUID("3fd00235-24ea-447a-96c5-2d79071ad9df"), "wall" : ISODate("2019-07-22T06:37:59.619Z"), "o" : { "_id" : ObjectId("5d3559c7dde424d0301c3d21"), "name" : "hushi", "num" : 41015, "date" : ISODate("2019-07-22T06:37:59.623Z") } } 1.3 增备备份因为oplog的特性,多跑一些没有关系,所以上述是直接找到了对test5集合操作的oplog点,现在去找到最新的点。主要要保证上述点和最新的点之间的oplog必须存在。先副本集里找到离现在较近的点:replSet27017:SECONDARY> db.oplog.rs.find({op:{$ne:'n'}}).sort({$natural:-1}).limit(1).pretty() { "ts" : Timestamp(1563780036, 337), "t" : NumberLong(123), "h" : NumberLong("-2687468098839248386"), "v" : 2, "op" : "i", "ns" : "admin.test10", "ui" : UUID("083637d7-6209-4d28-9b4d-529ba26e836c"), "wall" : ISODate("2019-07-22T07:20:36.370Z"), "o" : { "_id" : ObjectId("5d3563c4fc6d8027c7545934"), "name" : "hushi", "num" : 41881, "date" : ISODate("2019-07-22T07:20:36.373Z") } 按照上述的oplog点进行dump: ./mongodump -vv -h192.168.1.11:27017 -uroot -prootroot --authenticationDatabase admin -d local -c oplog.rs -o /backup --query='{ts:{$gte:Timestamp(1563777479, 674),$lt:Timestamp(1563780036, 337)}}' 2019-07-22T15:42:40.338+0800 done dumping local.oplog.rs (52140 documents) 2019-07-22T15:42:40.342+0800 dump phase III: the oplog 2019-07-22T15:42:40.342+0800 finishing dump 1.4 将增量进行恢复mv /backup/local/oplog.rs.bson rsync /backup/local/oplog.bson 192.168.1.14:/backup/local/恢复的时候报错: Failed: restore error: error applying oplog: applyOps: not authorized on admin to execute command { applyOps: [ { ts: Timestamp(1563777601, 1), h: 2702590434054582905, v: 2, op: "d", ns: "config.system.sessions", o: { _id: { id: UUID("9f7a5b0b-a1e1-407a-b9dd-7506a3220d9e"), uid: BinData(0, 6399AB0DAC62F20BFC466753B10FB58FB7E692BEC952C69B84D997021794D1F8) } }, o2: {} } ], $db: "admin" } 解决方法(在admin数据库中执行): db.createRole({role:'sysadmin',roles:[], privileges:[ {resource:{anyResource:true},actions:['anyAction']}]}) db.grantRolesToUser( "root" , [ { role: "sysadmin", db: "admin" } ]) 进行恢复 #./mongorestore -vv -h127.0.0.1:27017 -uroot -prootroot --authenticationDatabase admin --oplogReplay /backup/local/ 2019-07-22T16:11:03.901+0800 oplog 7.71MB 2019-07-22T16:11:06.401+0800 applied 51899 ops 2019-07-22T16:11:06.401+0800 oplog 9.13MB 2019-07-22T16:11:06.401+0800 done 数据已经进行了恢复: switched to db admin > db.test10.find().sort({$natural:-1}).limit(1).pretty() { "_id" : ObjectId("5d3563c4fc6d8027c7545933"), "name" : "hushi", "num" : 41880, "date" : ISODate("2019-07-22T07:20:36.373Z") } 如果将单节点以一个新的单节点副本集去启动,那就需要删除掉所有的oplog,再重新启动。那就是跟直接将节点加入副本集是一样的。 > db.getSiblingDB('local').oplog.rs.find({op:{$ne:'n'}}).sort({$natural:-1}).limit(1).pretty() { "ts" : Timestamp(1563777601, 5), "t" : NumberLong(123), "h" : NumberLong("-6583634829168454121"), "v" : 2, "op" : "i", "ns" : "config.system.sessions", "ui" : UUID("10b4d6ac-37df-4586-8a2d-83a3389d7406"), "wall" : ISODate("2019-07-22T06:40:01.172Z"), "o" : { "_id" : { "id" : UUID("9805a821-9a88-43bf-a85d-9a0b63b98632"), "uid" : BinData(0,"Y5mrDaxi8gv8RmdTsQ+1j7fmkr7JUsabhNmXAheU0fg=") }, "lastUse" : ISODate("2019-07-22T06:40:01.175Z"), "user" : { "name" : "root@admin" } } } 如果将单节点以一个新的单节点副本集去启动,那就需要删除掉所有的oplog,再重新启动。那就是跟直接将节点加入副本集是一样的。 1.5 加入到副本集 replSet27017:PRIMARY> rs.add({host: "192.168.1.14:27017", priority: 1, hidden: false}) { "ok" : 1, 加入之后,oplog记录也一样了: replSet27017:SECONDARY> db.getSiblingDB('local').oplog.rs.find({op:{$ne:'n'},ts:{$lte:Timestamp(1563780036, 337)}}).sort({$natural:-1}).limit(1).pretty() { "ts" : Timestamp(1563780036, 337), "t" : NumberLong(123), "h" : NumberLong("-2687468098839248386"), "v" : 2, "op" : "i", "ns" : "admin.test10", "ui" : UUID("083637d7-6209-4d28-9b4d-529ba26e836c"), "wall" : ISODate("2019-07-22T07:20:36.370Z"), "o" : { "_id" : ObjectId("5d3563c4fc6d8027c7545934"), "name" : "hushi", "num" : 41881, "date" : ISODate("2019-07-22T07:20:36.373Z") } } 2、恢复误删的单个集合 插入数据for (i = 0; i < 10000; i++){ db.collection1.save({'name':'hushi','num':i}); }collection1集合备份./mongodump -vv -h192.168.1.11:27017 -uroot -prootroot --authenticationDatabase admin -d db01 -c collection1-o /data/mongodb/backup再次插入数据(进行一些操作)for (i = 0; i < 1000; i++){ db.collection1.save({'name':'hushi','num':i,date:new Date()}); }误删db.collection1.drop()查找删除 db.oplog.rs.find({op:{$ne:'n'},o:{'drop':'collection1'}}).sort({ts:-1}).pretty().limit(5) { "ts" : Timestamp(1559803854, 1), "t" : NumberLong(44), "h" : NumberLong("-514875429754097077"), "v" : 2, "op" : "c", "ns" : "db01.$cmd", "ui" : UUID("b8fe3553-8249-4f18-b652-5bba86760d43"), "wall" : ISODate("2019-06-06T06:50:54.406Z"), "o" : { "drop" : "collection1" } } 备份oplog ./mongodump -vv -h192.168.1.11:27017 -uroot -prootroot --authenticationDatabase admin -d local -c oplog.rs -o /tmp restore的时候需要是oplog.bsonmv /tmp/local/oplog.rs.bson /data/mongodb/backup/oplog.bson 恢复collection1./mongorestore -v -h127.0.0.1:27018-d db01 -c collection1 /data/backup1/db01/collection1.bson查看已经恢复前1w插入记录 db.collection1.count() 10000 应用oplogmongorestore -vv-h127.0.0.1:27018--oplogReplay--oplogLimit=1559803854:1/data/backup1/再次查看插入记录 db.collection1.count() 11000 3、恢复误删的文档 文档误删除 replSet27017:PRIMARY> for (i = 0; i < 1000; i++){ db.test4.save({'name':'hushi','num':i,date:new Date()}); } replSet27017:PRIMARY> db.test4.remove({$and:[{num:{$gte:100,$lte:300}}]}) WriteResult({ "nRemoved" : 201 }) replSet27017:PRIMARY> for (i = 1000; i < 1500; i++){ db.test4.save({'name':'hushi','num':i,date:new Date()}); } WriteResult({ "nInserted" : 1 }) 找到删除开始时间点 replSet27017:PRIMARY> db.getSiblingDB('local').oplog.rs.find({op:{$ne:'n'},ns:'mms_test.test4'},{ts:1,op:1}).sort({$natural:-1}).limit(10).skip(695) { "ts" : Timestamp(1563431039, 6), "op" : "d" } { "ts" : Timestamp(1563431039, 5), "op" : "d" } { "ts" : Timestamp(1563431039, 4), "op" : "d" } { "ts" : Timestamp(1563431039, 3), "op" : "d" } { "ts" : Timestamp(1563431039, 2), "op" : "d" } { "ts" : Timestamp(1563431039, 1), "op" : "d" } { "ts" : Timestamp(1563430620, 502), "op" : "i" } { "ts" : Timestamp(1563430620, 501), "op" : "i" } { "ts" : Timestamp(1563430620, 500), "op" : "i" } { "ts" : Timestamp(1563430620, 499), "op" : "i" } 大于等于这个时间点,删除了201条数据 replSet27017:PRIMARY> db.getSiblingDB('local').oplog.rs.find({op:{$ne:'n'},ns:'mms_test.test4',op:'d',ts:{$gte:Timestamp(1563431039, 1)}}).sort({$natural:-1}).limit(1).count() 201 replSet27017:PRIMARY> db.getSiblingDB('local').oplog.rs.find({op:{$ne:'n'},ns:'mms_test.test4',op:'d',ts:{$gte:Timestamp(1563431039, 1)}}).sort({$natural:-1}).limit(1).pretty() { "ts" : Timestamp(1563431039, 201), "t" : NumberLong(113), "h" : NumberLong("-1345379834581505732"), "v" : 2, "op" : "d", "ns" : "mms_test.test4", "ui" : UUID("9a3dbae7-4f7c-465d-b420-1b7818531fc8"), "wall" : ISODate("2019-07-18T06:23:59.997Z"), "o" : { "_id" : ObjectId("5d300edb42389abced5f7bae") } } replSet27017:PRIMARY> db.getSiblingDB('local').oplog.rs.find({op:{$ne:'n'},ns:'mms_test.test4',op:'d',ts:{$gte:Timestamp(1563431039, 1)}}).sort({$natural:1}).limit(1).pretty() { "ts" : Timestamp(1563431039, 1), "t" : NumberLong(113), "h" : NumberLong("-4777761962883174315"), "v" : 2, "op" : "d", "ns" : "mms_test.test4", "ui" : UUID("9a3dbae7-4f7c-465d-b420-1b7818531fc8"), "wall" : ISODate("2019-07-18T06:23:59.997Z"), "o" : { "_id" : ObjectId("5d300edb42389abced5f7ae6") } } 这里最后试用了一下ongodb-backup-restore-util,如果使用mongorestore是一样的,但是需要先将oplog按照时间点进行dump下来,再去进行恢复。 #./mongodb-backup-restore-util --host 127.0.0.1 --port 27017 --rsId replSet27017 --groupId 5d2d88adf2a30bbee892ef0d --opStart 1563423143:1 --opEnd 1563430620:502 --oplogSourceAddr https://api-backup.us-east-1.mongodb.com --apiKey 5d2f0fbbff7a252987d03c00086f7a1040706ba4c6c634b8f4c09b9e [2019/07/18 19:13:55.843] [pit-restore.debug] [pit-restore/standalone-pit-restore.go:main:116] Creating restore [2019/07/18 19:14:05.406] [pit-restore.debug] [pit-restore/standalone-pit-restore.go:main:137] Successfully completed restore. [2019/07/18 19:14:05.406] [pit-restore.debug] [pit-restore/standalone-pit-restore.go:main:138] Successfully completed restore. [2019/07/18 19:14:05.406] [pit-restore.info] [restore/restore.go:Stop:121] Stopping Restore 已经进行了恢复 db.test4.find({$and:[{num:{$gte:100,$lte:300}}]}).count() 201 三、备份恢复方案 1、备份策略 1.1 MongoDB Cloud Manager的备份策略:The rate is based on your having 28 snapshots at steady state: The six-hour snapshots are kept for two days; The daily snapshots for one week, The weekly snapshots for one month, The monthly for one year. 这是官方提供的全备和全备保留的时间点。oplog是一直备份,秒级延迟。 1.2 全备 + oplog顺着这个思路,全备可以和增备分开,全备照需要,每6个小时或者每一天备份一次。然后oplog每秒或者每5秒或者每1分钟进行一次备份。全备可以使用percona server进行物理热备,oplog可以按照设定的时间间隔一直备份。再可以按将一些重要的文档使用mysqldump进行备份,这样万一有误操作可以快速恢复。 2、增备oplog 2.1 进行增备 #./mongodump -vv -h192.168.1.11:27017 -uroot -prootroot --authenticationDatabase admin -d local -c oplog.rs -o /backup --query='{ts:{$gte:Timestamp(1563703200, 1),$lt:Timestamp(1563703500, 1)}}' 这里是增备了5分钟的oplog内容将增备oplog改名:mv oplog.rs.bson oplog.bson.backup ./mongodump -vv -h192.168.1.11:27017 -uroot -prootroot --authenticationDatabase admin -d local -c oplog.rs -o /backup --query='{ts:{$gte:Timestamp(1563771600, 1),$lt:Timestamp(1563775200, 1)}}' 再次增备,将增备的oplog合到一个bson文件里cat oplog.rs.bson >>oplog.bson.backup 接下来继续增备,继续将增备都追加到一个文件里。可以将每一天的增备放到一个文件里。 3、验证备份 进行了备份之后肯定要进行相关的验证,验证分为两块,一个是备份文件恢复后完整性验证,一个是oplog增备是否成功验证。一个思路是每天将全备的文件和增备的文件恢复到一个单节点。3.1 验证全备全备建议使用物理热备,如果使用的是percona server,那么可以WiredTiger.backup文件的最后一条插入记录在恢复的节点上是否存在;如果没有插入记录,或者WiredTiger.backup文件没有内容,可以简单比较一下副本集的集合数据和恢复后的节点是否相同。同样如果使用的是mongodb cloud manager这样的不记录oplog的工具,也是比较一下集合数量。3.2 验证增备验证增备可以查看bson文件里最后一条插入的数据是什么,查看恢复后的文件是否有这条数据。

优秀的个人博客,低调大师

EMR学习笔记(1)HDFS

EMR HDFS Architecture 本文以非HA集群,2个worker的集群为例。 非HA集群,仅有一个Namenode实例,部署在Master节点。Namenode主要职责:-管理文件系统namespace,包括但不仅限于:开、关文件,文件改名,目录操作等。-管控客户端对文件的访问 EMR hadoop集群,每个Worker节点仅部署一个Datanode实例。Datanode主要职责:-管理所在节点挂载的存储-提供给客户端读写服务-block创建、删除以及replication 登录EMR集群实现基本运维 在较新的集群版本中(3.2 以上版本),所有的服务操作都可以通过集群的配置管理功能来完成。推荐优先使用 Web 页面的管理方式。 若您觉得在网页上的作业和执行计划无法满足您更加复杂的应用需求,您可以登录到 E-MapReduce 集群的主机上。找到集群的详情页,其中就有集群 master 机器的公网 IP 地址,您可以直接 SSH 登录到这台机器上,查看各种设置与状态。 登录 Master 主机步骤 使用如下命令 SSH 登录到 master 主机。请在集群详情页的主机信息栏中获取集群 master 机器的公网 IP。ssh root@ip.of.master 输入创建集群时设定的密码。 如何登录 Core 节点A:按照如下步骤: 首先在 Master 节点上切换到 Hadoop 账号:su hadoop 然后即可免密码 SSH 登录到对应的 Core 节点:ssh emr-worker-1 通过 sudo 可以获得 root 权限:sudo vi /etc/hosts 通过命令行方式启停服务进程操作用账号:hdfs NameNode (Master 节点) // 启动 /usr/lib/hadoop-current/sbin/hadoop-daemon.sh start namenode // 停止 /usr/lib/hadoop-current/sbin/hadoop-daemon.sh stop namenode DataNode (Core 节点) // 启动 /usr/lib/hadoop-current/sbin/hadoop-daemon.sh start datanode // 停止 /usr/lib/hadoop-current/sbin/hadoop-daemon.sh stop datanode 示例:登录实际emr集群演示停止datanode进程操作

优秀的个人博客,低调大师

RabbitMQ消息队列学习笔记

概述 初次使用AMQP的过程中,总是容易被AMQP支持的消息模型绕晕,这里结合官方的教程,对AMQP的消息模型做一个简要总结,供参考。目前官方给出了六种消息发送/接收模型,这里主要介绍前五种消息模型。 消息模型 1、Hello World 简单模式就是生产者将消息发送到队列、消费者从队列中获取消息。一条消息对应一个消费者。 示例代码说明: 测试使用的是阿里云的AMQP消息队列服务,具体的代码配置过程可以参考阿里云官方链接。 工具类 import AMQP.AliyunCredentialsProvider; import com.rabbitmq.client.Connection; import com.rabbitmq.client.ConnectionFactory; public class ConnectionUtil { pu

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

用户登录
用户注册