Springboot项目的接口防刷
创建一个注解,通过注解控制接口请求次数
1 | @Retention(RetentionPolicy.RUNTIME) |
拦截器处理注解信息
1 | @Component |
注册拦截器
1 | @Configuration |
使用
1 | @AccessControl(seconds = 60,maxCount = 1) |
深入理解Volatile关键字及其实现原理
volatile通常被比喻成”轻量级的synchronized”,是Java中提供的另一种解决可见性和有序性问题的方案。
volatile的原理
可见性实现
为了提高处理器的执行速度,在处理器和内存之间增加了多级缓存来提升。但是由于引入了多级缓存,就存在缓存数据不一致问题。在多处理器下,为了保证各个处理器的缓存是一致的,就会实现缓存一致性协议。
缓存一致性协议:每个处理器通过嗅探在总线上传播的数据来检查自己缓存的值是不是过期了,当处理器发现自己缓存行对应的内存地址被修改,就会将当前处理器的缓存行设置成无效状态,当处理器要对这个数据进行修改操作的时候,会强制重新从系统内存里把数据读到处理器缓存里。
对于volatile变量,当对volatile变量进行写操作的时候,JVM会向处理器发送一条lock前缀的指令,将这个缓存中的变量回写到系统主存中。而其他处理器的缓存由于遵守了缓存一致性协议,也会把这个变量的值从主存加载到自己的缓存中。这就保证了一个volatile在并发编程中,其值在多个缓存中是可见的。
每个线程的工作内存是CPU寄存器和高速缓存的抽象。
两条线程Thread-A与Threab-B同时操作主存中的一个volatile变量i时,Thread-A写了变量i,那么:
Thread-A发出LOCK#指令 发出的LOCK#指令锁总线(或锁缓存行),同时让Thread-B高速缓存中的缓存行内容失效。
Thread-A向主存回写最新修改的i Thread-B读取变量i,那么:
Thread-B发现对应地址的缓存行被锁了,等待锁的释放,缓存一致性协议会保证它读取到最新的值
由此可以看出,volatile关键字的读和普通变量的读取相比基本没差别,差别主要还是在变量的写操作上。
有序性
Happen-before
JSR 133中对Happen-before的定义:如果a happen-before b,则a所做的任何操作对b是可见的。
happen-before规则:
同一个线程中的,前面的操作 happen-before 后续的操作。(即单线程内按代码顺序执行。但是,在不影响在单线程环境执行结果的前提下,编译器和处理器可以进行重排序,这是合法的。换句话说,这一是规则无法保证编译重排和指令重排)。
监视器上的解锁操作 happen-before 其后续的加锁操作。(Synchronized 规则)
对volatile变量的写操作 happen-before 后续的读操作。(volatile 规则)
线程的start() 方法 happen-before 该线程所有的后续操作。(线程启动规则)
线程所有的操作 happen-before 其他线程在该线程上调用 join 返回成功后的操作。
如果 a happen-before b,b happen-before c,则a happen-before c(传递性)。
有序性即程序执行的顺序按照代码的先后顺序执行。
除了引入了时间片以外,由于处理器优化和指令重排等,CPU还可能对输入代码进行乱序执行,这就是可能存在有序性问题。
而volatile除了可以保证数据的可见性之外,还有一个强大的功能,那就是他可以禁止指令重排优化等。
普通的变量仅仅会保证在该方法的执行过程中所依赖的赋值结果的地方都能获得正确的结果,而不能保证变量的赋值操作的顺序与程序代码中的执行顺序一致。
volatile可以禁止指令重排,这就保证了代码的程序会严格按照代码的先后顺序执行。这就保证了有序性。被volatile修饰的变量的操作,会严格按照代码顺序执行。
volatile与synchronized的区别
- (1)使用上的区别:Volatile只能修饰变量,synchronized只能修饰方法和语句块
- (2)对原子性的保证:synchronized可以保证原子性,Volatile不能保证原子性
- (3)对可见性的保证:都可以保证可见性,但实现原理不同,Volatile对变量加了lock,synchronized使用monitorEnter和monitorexit monitor JVM
- (4)对有序性的保证:Volatile能保证有序,synchronized可以保证有序性,但是代价(重量级)并发退化到串行
- (5)synchronized引起阻塞,Volatile不会引起阻塞
使用vscode搭建个人笔记环境
下载安装vscode
安装插件
中文包
Chinese (Simplified) Language Pack for Visual Studio Code
Markdown显示插件
类似于github的模板:Markdown Preview Github Styling
Markdown编辑插件
Markdown Shortcuts
图床插件
picgo
配置:
1 | Pic Bed: Current |
文件头插件
vscode-fileheader
配置:
1 | Fileheader: Author |
使用
在git上新建一个保存图片的库,按照上面的配置picgo,后 图片复制后 Ctrl+Alt+U即可上传到仓库,并且生成markdown的信息。
在git新建笔记库,在vscode代码库中 拉取后,就可以编写,加入库,推送等等操作。
预览html文档的插件
HBase介绍安装与操作
介绍
- HBase是Apache Hadoop的数据库,能够对大型数据提供随机、实时的读写访问,是Google的BigTable的开源实现。
- HBase的目标是存储并处理大型的数据,更具体地说仅用普通的硬件配置,能够处理成千上万的行和列所组成的大型数据库。
- HBase是一个开源的、分布式的、多版本的、面向列的存储模型。可以直接使用本地文件系统,也可使用Hadoop的HDFS文件存储系统。
为了提高数据的可靠性和系统的健壮性,并且发挥HBase处理大型数据的能力,还是使用HDFS作为文件存储系统更佳。
另外,HBase存储的是松散型数据,具体来说,HBase存储的数据介于映射(key/value)和关系型数据之间。如下图所示,HBase存储的数据从逻辑上看就是一张很大的表,并且它的数据列可以根据需要动态增加。每一个cell中的数据又可以有多个版本(通过时间戳来区别),从下图来看,HBase还具有 “ 向下提供存储,向上提供运算 “ 的特点。
逻辑结构
逻辑上,HBase的数据模型和关系型数据库类似,有表,有行列。但是从底层物理存储结构k-v来看,它更像一个多维度map。
物理存储结构
数据模型
Name Space
命名空间,类似于关系型数据库的 DatabBase 概念,每个命名空间下有多个表。HBase有两个自带的命名空间,分别是 hbase 和 default,hbase 中存放的是 HBase 内置的表,default 表是用户默认使用的命名空间。
Region
类似于关系型数据库的表概念。不同的是,HBase 定义表时只需要声明列族即可,不需要声明具体的列。往 HBase 写入数据时,字段可以动态、按需指定。因此,和关系型数据库相比,HBase 能够轻松应对字段变更的场景。
Row
HBase表中的每行数据都由一个 RowKey 和多个 Column(列)组成,数据是按照 RowKey的字典顺序存储的,并且查询数据时只能根据 RowKey 进行检索。
Column
HBase 中的每个列都由 Column Family(列族)和 Column Qualifier(列限定符)进行限定,例如 info:name,info:age。建表时,只需指明列族,而列限定符无需预先定义。
Time Stamp
用于标识数据的不同版本(version),每条数据写入时,如果不指定时间戳,系统会自动为其加上该字段,其值为写入 HBase 的时间。
Cell
由{rowkey, column Family:column Qualifier, time Stamp} 唯一确定的单元。cell 中的数据是没有类型的,全部是字节码形式存贮。
HBase体系架构
HBase的服务器体系结构遵从简单的主从服务器架构,它由HRegion Server群和HBase Master服务器构成。HBase Master负责管理所有的HRegion Server,而HBase中的所有RegionServer都是通过ZooKeeper来协调,并处理HBase服务器运行期间可能遇到的错误。
HBase Master Server本身并不存储HBase中的任何数据,HBase逻辑上的表可能会被划分成多个Region,然后存储到HRegion Server群中。HBase Master Server中存储的是从数据到HRegion Server的映射。HBase体系结构如下图所示:
Client
HBase Client使用HBase的RPC机制与HMaster和HRegionServer进行通信,对于管理类操作,Client与HMaster进行RPC;对于数据读写类操作,Client与HRegionServer进行RPC。
Zookeeper
Zookeeper Quorum中除了存储了ROOT表的地址和HMaster的地址,HRegionServer也会把自己以Ephemeral方式注册到 Zookeeper中,使得HMaster可以随时感知到各个HRegionServer的健康状态。此外,Zookeeper也避免了HMaster的单点问题。
HMaster
- 管理用户对表的操作:create, delete, alter;
- 管理HRegion Server的负载均衡,调整Region分布;
- 在Region Split后,负责新Region的分配;
- 在HRegion Server停机后,负责失效HRegion Server 上的Regions迁移。
HDFS
HDFS 为 HBase 提供最终的底层数据存储服务,同时为 HBase 提供高可用的支持。Region
当表的大小超过设置值的时候,HBase会自动地将表划分为不同的区域,每个区域包含所有行的一个子集。对用户来说,每个表是一堆数据的集合,靠主键来区分。从物理上来说,一张表被拆分成了多块,每一块就是一个Region。一个Region会保存一个表里面某段连续的数据,从开始主键到结束主键,一张完整的表格是保存在多个Region上面。
HRegionServer
Region 的管理者,主要作用:对于数据的操作:get, put, delete;对于 Region 的操作:splitRegion、compactRegion。
- 所有的数据库数据一般是保存在Hadoop HDFS分布式文件系统上面,用户通过一系列HRegion Server获取这些数据,一台机器上面一般只运行一个HRegion Server,且每一个区段的HRegion也只会被一个HRegion Server维护。
- HRegion Server主要负责响应用户I/O请求,向HDFS文件系统中读写数据,是HBase中最核心的模块。
- HRegion Server内部管理了一系列HRegion对象,每个HRegion对应了Table中的一个Region,Region中由多个Store组成。每个Store对应了Table中的一个Column Family的存储,可以看出每个Column Family其实就是一个集中的存储单元,因此最好将具备共同IO特性的column放在一个Column Family中,这样最高效。
HStore(StoreFile)
- HBase存储的核心。由MemStore和StoreFile组成。。
- MemStore是Sorted Memory Buffer
Client写入 -> 存入MemStore,一直到MemStore满 -> Flush成一个StoreFile,直至增长到一定阈值 -> 触发Compact合并操作 -> 多个StoreFile合并成一个StoreFile,同时进行版本合并和数据删除 -> 当StoreFiles Compact后,逐步形成越来越大的StoreFile -> 单个StoreFile大小超过一定阈值后,触发Split操作,把当前Region Split成2个Region,Region会下线,新Split出的2个孩子Region会被HMaster分配到相应的HRegionServer上,使得原先1个Region的压力得以分流到2个Region上。
所以,HBase只是增加数据,有所得更新和删除操作,都是在Compact阶段做的,所以,用户写操作只需要进入到内存即可立即返回,从而保证I/O高性能。
- HFile是底层的实现。
MemStore
写缓存,由于 HFile 中的数据要求是有序的,所以数据是先存储在 MemStore 中,排好序后,等到达刷写时机才会刷写到 HFile,每次刷写都会形成一个新的 HFile。Hlog
在分布式系统环境中,无法避免系统出错或者宕机,因此一旦HRegion Server意外退出,MemStore中的内存数据将会丢失,这就需要引入HLog了。每个HRegion Server中都有一个HLog对象。
每个HRegionServer中都会有一个HLog对象,HLog是一个实现Write Ahead Log的类,每次用户操作写入Memstore的同时,也会写一份数据到HLog文件,HLog文件定期会滚动出新,并删除旧的文件(已持久化到StoreFile中的数据)。当HRegionServer意外终止后,HMaster会通过Zookeeper感知,HMaster首先处理遗留的HLog文件,将不同region的log数据拆分,分别放到相应region目录下,然后再将失效的region重新分配,领取到这些region的HRegionServer在Load Region的过程中,会发现有历史HLog需要处理,因此会Replay HLog中的数据到MemStore中,然后flush到StoreFiles,完成数据恢复。
Hbase的存储格式
HBase中的所有数据文件都存储在Hadoop HDFS文件系统上为例,主要包括上述提出的两种文件类型:
1 | HFile, HBase中KeyValue数据的存储格式,HFile是Hadoop的二进制格式文件,实际上StoreFile就是对HFile做了轻量级包装,即StoreFile底层就是HFile。 |
- Hbase的存储格式(HFile)*
1 | HFile文件不定长,长度固定的块只有两个:Trailer和FileInfo |
1 | KeyLength和ValueLength:两个固定的长度,分别代表Key和Value的长度 |
- Hbase的存储格式(HLog File)*
HLog文件就是一个普通的Hadoop Sequence File,Sequence File 的Key是HLogKey对象,HLogKey中记录了写入数据的归属信息,除了table和region名字外,同时还包括 sequence number和timestamp,timestamp是“写入时间”,sequence number的起始值为0,或者是最近一次存入文件系统中sequence number。
HLog Sequece File的Value是HBase的KeyValue对象,即对应HFile中的KeyValue
ROOT表和META表
用户表的Regions元数据被存储在.META.表中,随着Region的增多,.META.表中的数据也会增大,并分裂成多个Regions。为了定位.META.表中各个Regions的位置,把.META.表中所有Regions的元数据保存在-ROOT-表中,最后由ZooKeeper记录-ROOT-表的位置信息。所有客户端访问用户数据前,需要首先访问ZooKeeper获得-ROOT-的位置,然后访问-ROOT-表获得.META.表的位置,最后根据.META.表中的信息确定用户数据存放的位置,如下图所示。
ROOT 表永远不会被分割,它只有一个Region,这样可以保证最多需要三次跳转就可以定位任意一个Region。为了加快访问速度,.META.表的Regions全部保存在内存中。客户端会将查询过的位置信息缓存起来,且缓存不会主动失效。如果客户端根据缓存信息还访问不到数据,则询问只有相关.META.表的Region服务器,试图获取数据的位置,如果还是失败,则询问-ROOT-表相关的.META.表在哪里。最后,如果前面的信息全部失效,则通过ZooKeeper重新定位Region的信息。所以如果客户端上的缓存全部是失效,则需要进行6次网络来回,才能定位到正确的Region。
MapReduce On HBase
在HBase系统上运行批处理运算,最方便和实用的模型依然是MapReduce,如下图:
HBase Table和Region的关系,比较类似HDFS File和Block的关系,HBase提供了配套的TableInputFormat和TableOutputFormat API,可以方便的将HBase Table作为Hadoop MapReduce的Source和Sink,对于MapReduce Job应用开发人员来说,基本不需要关注HBase系统自身的细节。
写流程
1 | 1)Client 先访问 zookeeper,获取 hbase:meta 表位于哪个 Region Server。 |
MemStore Flush
MemStore 刷写时机:
1.当某个 memstroe 的大小达到了 hbase.hregion.memstore.flush.size(默认值 128M), 其所在 region 的所有 memstore 都会刷写。
** 当 memstore 的大小达到了hbase.hregion.memstore.flush.size(默认值 128M) ✖ hbase.hregion.memstore.block.multiplier(默认值 4)时 **,会阻止继续往该 memstore 写数据。
2.当 region server 中 memstore 的总大小达到** java_heapsize✖hbase.regionserver.global.memstore.size(默认值 0.4)✖hbase.regionserver.global.memstore.size.lower.limit(默认值 0.95) **,region 会按照其所有 memstore 的大小顺序(由大到小)依次进行刷写。
直到 region server中所有 memstore 的总大小减小到上述值以下。 当 region server 中 memstore 的总大小达到java_heapsize✖hbase.regionserver.global.memstore.size(默认值 0.4)时,会阻止继续往所有的 memstore 写数据。
- 到达自动刷写的时间,也会触发 memstore flush。自动刷新的时间间隔由该属性进行配置 hbase.regionserver.optionalcacheflushinterval(默认 1 小时)。
4.当 WAL 文件的数量超过 hbase.regionserver.max.logs,region 会按照时间顺序依次进行刷写,直到 WAL 文件数量减小到 hbase.regionserver.max.log 以下(该属性名已经废弃,现无需手动设置,最大值为 32)。
读流程
1 | 1)Client 先访问 zookeeper,获取 hbase:meta 表位于哪个 Region Server。 |
StoreFile Compaction
由于memstore每次刷写都会生成一个新的HFile,且同一个字段的不同版本(timestamp)和不同类型(Put/Delete)有可能会分布在不同的 HFile 中,因此查询时需要遍历所有的 HFile。为了减少 HFile 的个数,以及清理掉过期和删除的数据,会进行 StoreFile Compaction。
Compaction 分为两种,分别是 Minor Compaction 和 Major Compaction。Minor Compaction会将临近的若干个较小的 HFile 合并成一个较大的 HFile,但不会清理过期和删除的数据。
Major Compaction 会将一个 Store 下的所有的 HFile 合并成一个大 HFile,并且会清理掉过期和删除的数据
Region Split
默认情况下,每个 Table 起初只有一个 Region,随着数据的不断写入,Region 会自动进行拆分。刚拆分时,两个子 Region 都位于当前的 Region Server,但处于负载均衡的考虑,HMaster 有可能会将某个 Region 转移给其他的 Region Server。
Region Split 时机:
1 | 1.当1个region中的某个Store下所有StoreFile的总大小超过hbase.hregion.max.filesize, 该 Region 就会进行拆分(0.94 版本之前)。 |
安装
1、docker安装
1 | docker run -d -h docker-hbase \ |
启动成功,访问web界面。
进入容器可以看到hbase正常
1 | [root@VM_0_3_centos ~]# docker exec -it 6a /bin/bash |
2、集群搭建
3、常用操作命令
1 | 查看集群状态status |
附录:Hbase默认端口
Hadoop安装和配置及使用介绍
由于Hadoop是基于Java开发,所以首选在Linux上安装好Java环境。
1、Hadoop的下载安装
下载包到/usr/local
解压:tar -zxvf /usr/local/hadoop-3.1.2.tar.gz -C /usr/local
添加环境变量vim /etc/profile
1 | export HADOOP_HOME=/usr/local/hadoop-3.1.2 |
source /etc/profile
执行测试:hadoop version
2、目录结构
1 | bin目录:存放对Hadoop相关服务(HDFS,YARN)进行操作的脚本 |
Hadoop运行模式包括:本地模式、伪分布式模式以及完全分布式模式。
3、本地运行模式(单机模式)
3.1、官方Grep案例
1 | 创建在hadoop-2.7.2文件下面创建一个input文件夹 |
3.2、官方WordCount案例 *
统计单词数
1 | 建立输入目录和文件,并且写入测试内容 |
3、伪分布式运行模式
3.1、启动HDFS并运行MapReduce程序
** 配置集群 **
配置:hadoop-env.sh
1 | vim etc/hadoop/hadoop-env.sh |
配置:core-site.xml
1 | [root@VM_0_3_centos hadoop-3.1.2]# vim etc/hadoop/core-site.xml |
HDFS core-site.xml 参数配置
1 | – fs.default.name |
配置:hdfs-site.xml
1 | vim etc/hadoop/hdfs-site.xml |
HDFS hdfs-site.xml 参数配置
1 | – dfs.name.dir |
** 启动集群 **
1 | 格式化NameNode(第一次启动时格式化) |
web端查看HDFS文件系统:http://152.*****:9870/dfshealth.html#tab-overview 老版本端口是50070
查看Log日志 /usr/local/hadoop-3.1.2/logs
** 操作集群 **
在HDFS文件系统上创建一个input文件夹
1 | [root@VM_0_3_centos hadoop-3.1.2]# bin/hdfs dfs -mkdir -p /user/root/input |
将测试文件内容上传到文件系统上
1 | [root@VM_0_3_centos hadoop-3.1.2]# bin/hdfs dfs -put wcinput/wc.input /user/root/input/ |
查看上传的文件是否正确
1 | [root@VM_0_3_centos hadoop-3.1.2]# bin/hdfs dfs -ls /user/root/input/ |
1 | [root@VM_0_3_centos hadoop-3.1.2]# bin/hdfs dfs -cat /user/root/ input/wc.input |
运行MapReduce程序
1 | [root@VM_0_3_centos hadoop-3.1.2]# bin/hadoop jar share/hadoop/mapreduce/hadoop-mapreduce-examples-3.1.2.jar wordcount /user/root/input/ /user/root/output |
查看输出结果
1 | [root@VM_0_3_centos hadoop-3.1.2]# bin/hdfs dfs -cat /user/root/output/* |
将测试文件内容下载到本地
1 | [root@VM_0_3_centos hadoop-3.1.2]# hdfs dfs -get /user/root/output/* ./wcoutput/ |
本地文件存在,先删除在下载
1 | [root@VM_0_3_centos hadoop-3.1.2]# rm -rf ./wcoutput/* |
查看本地结果
1 | [root@VM_0_3_centos hadoop-3.1.2]# cat ./wcoutput/* |
删除输出结果
1 | hdfs dfs -rm -r /user/root/output |
3.2、启动YARN并运行MapReduce程序
配置集群
配置环境
1 | [root@VM_0_3_centos hadoop-3.1.2]# vim etc/hadoop/yarn-env.sh |
配置yarn-site.xml
1 | <!-- Reducer获取数据的方式 --> |
配置:mapred-site.xml
1 | [root@VM_0_3_centos hadoop]# vim mapred-site.xml |
启动集群
启动前必须保证NameNode和DataNode已经启动
1 | [root@VM_0_3_centos hadoop-3.1.2]# sbin/yarn-daemon.sh start resourcemanager |
集群操作
YARN的浏览器查看:http://152.....56:8088/cluster
删除文件系统上的output文件
1 | [root@VM_0_3_centos hadoop-3.1.2]# bin/hdfs dfs -rm -R /user/root/output |
执行MapReduce程序
1 | bin/hadoop jar share/hadoop/mapreduce/hadoop-mapreduce-examples-3.1.2.jar wordcount /user/root/input/ /user/root/output |
查看运行结果可以通过浏览器查看。
1 |
3.3、配置历史服务器
为了查看程序的历史运行情况,需要配置一下历史服务器。
配置mapred-site.xml
1 | vim mapred-site.xml |
启动历史服务器
sbin/mr-jobhistory-daemon.sh start historyserver
查看JobHistory
3.4、配置日志的聚集
应用运行完成以后,将程序运行日志信息上传到HDFS系统上。方便的查看到程序运行详情,方便开发调试。
注意:开启日志聚集功能,需要重新启动NodeManager 、ResourceManager和HistoryManager。
配置yarn-site.xml
1 | [atguigu@hadoop101 hadoop]$ vi yarn-site.xml |
重启NodeManager 、ResourceManager和HistoryManager
1 | [root@VM_0_3_centos hadoop-3.1.2]# sbin/yarn-daemon.sh stop resourcemanager |
删除HDFS上已经存在的输出文件
1 | [root@VM_0_3_centos hadoop-3.1.2]# bin/hdfs dfs -rm -R /user/root/output |
执行WordCount程序
1 | [root@VM_0_3_centos hadoop-3.1.2]# hadoop jar share/hadoop/mapreduce/hadoop-mapreduce-examples-3.1.2.jar wordcount /user/root/input /user/root/output |
查看日志
3.5、配置文件说明
Hadoop配置文件分两类:默认配置文件和自定义配置文件,只有用户想修改某一默认配置值时,才需要修改自定义配置文件,更改相应属性值。
默认配置文件:
1 | 默认文件 在Hadoop的jar包中的位置 |
自定义配置文件:core-site.xml、hdfs-site.xml、yarn-site.xml、mapred-site.xml
4、完全分布式运行模式
centos 设置systemctl自启服务文件
方式一
建立服务文件
vim /usr/lib/systemd/system/mongodb.service
1 | [Unit] |
文件内容解释
Description:描述服务
After:描述服务类别
[Service]服务运行参数的设置
Type=forking是后台运行的形式
ExecStart为服务的具体运行命令
ExecReload为重启命令
ExecStop为停止命令
PrivateTmp=True表示给服务分配独立的临时空间
注意:启动、重启、停止命令全部要求使用绝对路径
[Install]服务安装的相关设置,可设置为多用户
设置开机自启动
任意目录下执行
systemctl enable xxx.service
其他命令
启动服务
systemctl start xxxx.service
设置开机自启动
systemctl enable xxxx.service
停止开机自启动
systemctl disable xxxx.service
查看服务当前状态
systemctl status xxx.service
重新启动服务
systemctl restart xxx.service
查看所有已启动的服务
systemctl list-units –type=service
CentOS7.0中systemctl启动关闭服务的用法
systemctl是主要的工具,它融合之前service和chkconfig的功能于一体。可以使用它永久性或只在当前会话中启用/禁用服务。
systemctl可以列出正在运行的服务状态
systemd-cgls以树形列出正在运行的进程,它可以递归显示控制组内容。
1 | 启动/关闭、启用/禁用服务: |
说明:启用服务就是在当前“runlevel”的配置文件目录/etc/systemd/system/multi-user.target.wants/里,建立/usr/lib/systemd/system里面对应服务配置文件的软链接;禁用服务就是删除此软链接
方式二
先在/etc/rc.d/init.d下新建文件 mongod
1 | #!/bin/sh |
授权 等操作:
chmod +x /etc/rc.d/init.d/mongod
chkconfig –add mongod
chkconfig –level 345 mongod on
chkconfig –list mongod
service mongod start
之后就可以开始使用service mongod start|stop|restart 管理mongodb服务了。
Hexo搭建
Hexo搭建
解决重定向问题:
npm i hexo-generator-cname –save
NodeJS内存不足 node –max-old-space-size=8192 –optimize-for-size –max-executable-size=8192 –max_old_space_size=8192 –optimize_for_size –max_executable_size=8192 node_modules/karma/bin/karma start –single-run –max_new_space_size=8192 –prod –aot
Redis 管道技术
管道
Redis是一种基于客户端-服务端模型以及请求/响应协议的TCP服务。这意味着通常情况下一个请求会遵循以下步骤:
- 客户端向服务端发送一个查询请求,并监听Socket返回,通常是以阻塞模式,等待服务端响应。
- 服务端处理命令,并将结果返回给客户端。
Redis 管道技术可以在服务端未响应时,客户端可以继续向服务端发送请求,并最终一次性读取所有服务端的响应。
管道技术最显著的优势是提高了 redis 服务的性能。
pipeline的思想
1 | 如果client执行一些相互之间无关的命令或者不需要获取命令的返回值,那么redis允许你连续发送多条命令,而不需要等待前面命令执行完毕。 |
Redis的管道可以在大量数据需要一次性操作完成的时候,使用Pipeline进行批处理,将一大队的操作合并成一次操作,可以减少链路层的时间消耗。
1 | Pipeline pipe = jedis.pipelined(); // 先创建一个pipeline的链接对象 |
SCAN、SSCAN、HSCAN、ZSCAN
SCAN、SSCAN、HSCAN、ZSCAN 4 个命令,分别用于集合、哈希键及有序集等。
1 | SCAN:命令用于迭代当前数据库中的数据库键。 |
SCAN cursor [MATCH pattern] [COUNT count]
当需要模糊查询或者大批量时候,keys * 进行查询 key 的时候会进行堵塞,导致 redis 整体不可用,因为redis是单线程,而使用 scan 命令则不会。
scan 游标 MATCH <返回和给定模式相匹配的元素> count 每次迭代所返回的元素数量 SCAN 命令是增量的循环,每次调用只会返回一小部分的元素。
在 Redis 中的具体用法如下:
1 | scan 0 match xttblog.com* count 5 |
SCAN 命令对应的 Jedis
1 | Jedis jedis = pool.getResource(); |
其他操作类似。https://www.xttblog.com/?p=3635
注意:SCAN 命令不能保证每次返回的值都是有序的,同一个 key 有可能返回多次,不做区分,需要应用程序去处理。
一个批量删除的例子。
1 | //key有模糊匹配*,查找到对应的去删除,启动一个线程去查找。通过游标的方式,用管道技术操作。 |
jvm深入-内存交互
每一个线程有一个工作内存。工作内存和主存独立。工作内存存放主存中变量的值的拷贝。
当数据从主内存复制到工作存储时,必须出现两个动作:第一,由主内存执行的读(read)操作;第二,由工作内存执行的相应的load操作;当数据从工作内存拷贝到主内存时,也出现两个操作:第一个,由工作内存执行的存储(store)操作;第二,由主内存执行的相应的写(write)操作。
每一个操作都是原子的,即执行期间不会被中断
对于普通变量,一个线程中更新的值,不能马上反应在其他变量中。如果需要在其他线程中立即可见,需要使用volatile关键字作为标识。
1、可见性:一个线程修改了变量,其他线程可以立即知道
保证可见性的方法:
- volatile
- synchronized (unlock之前,写变量值回主存)
- final(一旦初始化完成,其他线程就可见)
2、有序性:本线程内,操作都是有序的;线程外观察,操作都是无序的。
3、指令重排:
指令重排:破坏了线程间的有序性:
指令重排:保证有序性的方法:
指令重排的基本原则:
程序顺序原则:一个线程内保证语义的串行性
volatile规则:volatile变量的写,先发生于读
锁规则:解锁(unlock)必然发生在随后的加锁(lock)前
传递性:A先于B,B先于C 那么A必然先于C
线程的start方法先于它的每一个动作
线程的所有操作先于线程的终结(Thread.join())
线程的中断(interrupt())先于被中断线程的代码
对象的构造函数执行结束先于finalize()方法