如何在centos上管理软件包

1. 使用YUM进行软件的管理

查看软件包的信息

1
yum info 包名

查看软件包的依赖列表

1
yum deplist 包名

卸载软件包

1
yum remove 包名

查看已安装的软件包

1
yum list installed

查看仓库内可用的软件包

1
yum list available

清除所有的包缓存

1
yum clear all

2. 使用RPM进行软件管理

查看已经安装的软件包

1
rpm -qa

查看某个已经被安装的软件包的信息

1
rpm -qi 包名

查看某个包的安装文件列表

1
rpm -ql 包名

查看某个rpm包的详细信息

1
rpm -qip 包名.rpm

查看某个rpm包中将要被安装的文件列表

1
rpm -qlp 包名.rpm

查看某个目录或者文件对应的包

1
rpm -qf 文件或者目录

查看某个已经安装的包的依赖

1
rpm -qR 包名

查看某个没有被安装的包的依赖项

1
rpm -qRp 包名.rpm

验证某个包的文件是否被正确安装

1
rpm -V 包名

java中常用的文件操作工具

使用的类库

apache的公共工具包

1
2
## build.gradle
implementation 'commons-io:commons-io:2.11.0'

文件和目录操作类

  1. FileUtils

    • [private] addCopyAttributes:如果原copy option中不存在复制选项,则在赋值选项中追加一个StandardCopyOption.COPY_ATTRIBUTES

java和c++的区别

java和c++的不同点

BASIS FOR COMPARISON C++ Java
Memory Management Managed by developers using pointers. Supports structures and union Controlled by the system, does not use pointers. Supports Threads and Interfaces
Inheritance Provide single and multiple inheritances both Does not support multiple inheritances. Uses the concept of Interface to achieve
Runtime error detection mechanism Programmer’s responsibility System’s responsibility
Libraries Comparatively available with low-level functionalities Provide a wide range of classes for various high-level services
Program Handling Methods and data can reside outside classes. The concept of a global file, namespace scopes available All methods and data reside in the class itself. Concept od Package is used.
Type Semantics Supports consistent support between primitive and object types Different from primitive and object types
Portability Platform dependent as source code must be recompiled for different platform. It uses the concept of bytecode which is platform-independent and can be used with platform-specific JVM.
Polymorphism Explicit for methods supports mixed hierarchies Automatic uses static and dynamic binding

参考文章:https://www.educba.com/c-plus-plus-vs-java/

C++中指针和引用的使用

指针和引用的区别

指针是一个持有某个变量内存地址的特殊变量,使用*号表示。

引用类似于指针,一般可以认为是持有某个值的变量的别名,它被用来关联被赋值给它的变量,使用&表示。

引用存储的是变量的地址。

语法层面的区别如下:

指针 引用
是否可以为null 可以指向一个null 不能为null,否则会报异常
声明方式 使用*号声明 使用&声明
是否可以级联 可以级联声明
int *ptr;
int **ptr1;
int x = 10;
int y = 20;
ptr = &x;
ptr1 = &ptr;
是否可以重新赋值 可以 一旦变量被赋值给引用变量,那么这个引用变量将不能重新被赋值
是否可以做算术运算 可以 不可以
S.No. Pointer Reference
1. Pointers in C++ can be assigned to NULL values. References in C++ can never be NULL else; it will throw an exception.
2. To dereference a variable in the case of pointers, (*) operator is used There is no need for referencing the variable; the variable name is simply used in case of reference in C++.
3. Pointers allow multiple levels of indirection, which means that pointer to pointer to pointer assigning and targeting is possible. For example: int *ptr, int **ptr1; int x= 10; int y= 20; ptr = &x; ptr1 = &ptr; No multiple levels of indirection are possible in the case of references. Only a single level is applicable in references. Implementing multiple levels in references in C++ throws a compiler error to the user. For example, int a = 13; int &ref = a; int &&ref1 = ref;
4. A pointer can be reassigned to point to another variable. But the variable needs to be of the same type of variable. For example: int *p; Int x, y; p = &x; p = &y; Once the variable is referred to by the reference variable, it cannot be reassigned to refer to another variable.
5. All the arithmetic operations like addition, subtraction, increment, etc., are possible in the case of pointers in C++. This is known as Pointer arithmetic. For example: int arr [5] = {10, 20, 30, 40, 50}; int p = arr; for (int i =0; i<5; i++) { cout << *p << endl; p++; } Arithmetic operations are not possible in the case of references. In C++, it will throw a compiler time error when it tries to do so. For example: int x = 10; int &ref = x; cout << ref++ << endl;
6. In the case of declaring a pointer in a C++ program, (*) operator is used before the pointer name. For example: int *ptr; In the case of reference, the reference variable is declared by using the (&) operator before the reference variable, which stands for the address. For example: Int a= 10; int &ref = a;
7. The pointer variable returns the value whose address it is pointing to. Value can be retrieved using the (*) operator. The reference variable returns the address of the address it is referring to. The address can be retrieved using the (&) operator.
8. The pointer variable in C++ has its own address in computer memory, and it also occupies space in the stack. The reference variable does not have its own memory address; instead, it only points to the variable and shares the same address as the original variable.

makefile在C++中的使用

Make工具

Make是unix上被用来简化为一个工程中的各个不同模块构建可执行程序的工具。在Makefile中有各种各样的规则来指定目标入口。make工具则读取所有的这些规则并依照行事。

例如,如果一个规则指定了某个依赖,那么make工具将在编译时包含这个依赖。make命令利用makefile来完成模块构建和文件清理的工作。

make的常用语法如下:

1
make target_label # target_label是在makefile中指定的目标

例如,如果我们想要执行清理文件的操作,那么我们可以这么做:

1
make clean # 注意,clean实际上是指定了rm作为执行命令

C++ Makefile

Makefile是一个由make命令来使用并用来构建目标的纯文本文件。一个Makefile也包含了一些源码级别的依赖信息以及构建顺序。

现在让我们看看Makefile的通用结构:

一个典型的Makefile通常以一个变量声明开头,后面紧跟着一串用来构建指定目标的目标入口。这些目标可能是.o或者是其他的可执行文件,比如说C或者C++或者java.class文件。

我们还可以有一串被目标标识(target label)所指定并被用来执行一系列命令的目标入口。

因此一个通用的makefile大致如下:

1
2
3
4
# comment
target: dependency1 dependency2 ... dependencyn
command
# 注意,command前面的tab缩进对于make来说是必要的
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 指定编译器,g++代表C++编译器,gcc代表C编译器
CC = g++
# 编译器flags
# -g表示需要添加debug信息到可执行文件中
# -Wall表示打开大多数编译器警告
CFLAGS = -g -Wall
#
TARGET = main

all: $(TARGET)
$(TARGET): $(TARGET).cpp
$(CC) $(CFLAGS) -o $(TARGET) $(TARGET).cpp
clean:
$(RM) $(TARGET)

Make和Makefile的例子

假设我们的工程有如下几个文件:

  • Main.cpp:主程序
  • Point.h:point类的头文件
  • Point.cpp:Point类的实现类
  • Square.h:square的头文件
  • Square.cpp:square类的实现类

对于上面的几个文件,我们需要将这些文件各自编译并生成.o文件,然后将它们link成一个叫做main的可执行文件。

接下来我们将各自编译这些文件:

  • g++ -c main.cpp:生成main.o
  • g++ -c point.cpp:生成point.o
  • g++ -c square.cpp:生成square.o

接下来,我们需要将这些.o文件link成一个可执行文件:

1
g++ -o main main.o point.o square.o

接下来,我们需要确定当某个文件发生变更时需要重新编译和重新生成的其他关联文件。下图描述了这种依赖关系。

image-20211230234102091

在上面的依赖图中,我们可以看到main位于根部,而main又包含了对象文件main.opoint.osquare.o,它们分别由各自的cpp文件编译生成。

所有的cpp实现都使用了它们自己的头文件,而main.cpp又引用了point.hsquare.h

接下来point.cpp引用了point.hsquare.cpp引用了square.hpoint.h

如果我们的工程中只有少数几个文件,那么我们可以不用关系它们之间的依赖关系,但是,实际项目中,我们可能会有成百上千个文件,如果我们每次修改完一个文件之后都要手动编译和生成所有文件,那无疑是令人崩溃的。因此,我们需要使用make工具来帮我们简化这个流程。

注意,必须使用Makefile作为文件名,不区分大小写,且放在源代码的根目录。

1
2
3
4
5
CC = g++
CFLAGS = -wall -g
# 确定依赖关系
main: main.o Point.o Square.o
$(CC) $(CFLAGS) -o main main.o Point.o Square.o

上面的命令实际上等价于我们在终端中执行

g++ -wall -g -o main main.o point.o square.o

接下来我们需要生成对象文件:main.o、point.o、square.o

1
2
3
4
main.o: main.cpp point.h square.h
$(CC) $(CFLAGS) -c main.cpp
Point.o: Point.h
Square.o: Square.h Point.h

Makefile的优点

  • 对于大项目,可以让我们以系统性和更有效的方式呈现项目;
  • 可以让源代码更加有效和易读,并利于debug;
  • Makefile可以自动编译那些被修改过的文件,因此当发生文件变更时我们不需要手动重新生成整个项目。
  • Makefile允许我们一次编译多个文件,因此我们只需要一个步骤就可以完成整个项目的编译。

postgresql常用查询场景

1. 计算数组类型的元素之和

首先创建包含数组类型字段的表

1
2
3
4
CREATE TABLE sal_emp (
name text,
pay_by_quarter integer[4]
);

其中pay_by_quarter表示每个季度的工资数组,数组长度为4。

需求:求指定季度区间内的工资总和。

插入测试数据

1
2
3
4
INSERT INTO sal_emp
VALUES ('Bill',
'{10000, 10000, 10000, 10000}'
)

由于postgresql本身支持按照索引取值,还支持按照索引范围取值,所以,很自然想到使用区间值来实现求和的首尾季度,但如何求和呢?

1
select pay_by_quarter[1:4] from sal_emp;

查询结果如下:

1
2
3
pay_by_quarter           |
-------------------------+
[10000,10000,10000,10000]|

如何将这4个数字累加起来呢,你可能想到使用sum函数来求和,但很遗憾,sum并不支持数组类型的求和。那么,我们可不可以将数组内的数字拆分成4条数据呢,当然可以。使用unnest函数可以帮我们做到这一点。

所以最后的sql变成了这样

1
2
3
4
5
6
7
select 
sum(t.arr)
from (
select
unnest(pay_by_quarter[1:4]) arr
from sal_emp
) t

执行结果如下:

1
2
3
sum  |
-----+
40000|

正是我们想要的求和之后的结果。

什么是jwt

什么是JWT

JWT(Json Web Token)以JSON的格式传输网络安全认证消息,以一种轻量级的消息传输格式来确保服务端的安全。而被传输的JSON信息可以被认证和信任,因为它拥有可信的数字签名。

客户端只需要使用凭证在服务器端认证一次,认证成功之后,服务端会给客户端返回一个JWT,客户端未来的请求都可以使用这个JWT来通过服务端的认证,并且不需要再次发送认证信息,比如说用户名和密码。

image-20211218220701216

需要注意的是,JWT中的payload对每个人都是可见的,因此我们不应该放任何敏感信息比如说密码在其中。我们可以加密payload数据,这样可以让它更加安全。然而我们可以确保没有人可以篡改payload中的信息。

IT老齐的架构课程之缓存

使用缓存的目的

提升性能

缓存分类

  • 客户端

    主要对浏览器的静态资源进行缓存,通过在浏览器端设置Expires(过期时间点)或者Cache-Control(时间段)来告诉浏览器将资源缓存到客户端本地,从而减少多次请求同一个静态资源带来的带宽和响应时效上的损耗。

  • 应用层

    • 主要表现形式为CDN(Content Delivery Network),可以有效解决带宽集中占用以及数据分发的问题。
    • 通过Nginx实现负载均衡,将静态资源存储在Nginx服务器上,并开启压缩功能;
  • 服务层

    • 进程内缓存:比如Mybatis的一二级缓存,或者Spring框架中的@EnableCache注解。
    • 进程外缓存:典型的使用redis作为分布式缓存技术。
  • 数据层

分布式缓存引入的问题

数据一致性

如何保证数据一致性

引入消息队列的主动推送功能,推送变更消息

什么情况下适用多级缓存架构

  1. 缓存数据稳定
  2. 可能产生高并发场景,应用启动时进行预热处理,访问前将热点数据先缓存,减少后端压力
  3. 一定程度上允许数据不一致不重要的信息更新处理方式:T+1,ETL日中处理。