- 描述Https的实现原理:
HTTPS是一种安全版本的HTTP,相对于HTTP协议(超文本传输协议),它使用加密技术来保护在网络上传输的数据。这种技术通常用于保护网站和浏览器之间的数据传输,以防止第三方监听或窃取数据。
HTTPS 的实现原理是基于一种称为 SSL/TLS 的加密协议。SSL/TLS 协议使用一种称为公钥加密的技术,它使用一对非对称加密密钥来加密数据。公钥是公开的,用于加密数据,而私钥是保密的,用于解密数据。 当一个用户想要访问一个 HTTPS 网站时,他的浏览器会向网站的服务器发出一个请求。服务器会响应该请求,并将公钥和证书发送回浏览器。证书是由可信的第三方签发的,包含了服务器的公钥和一些其他信息。浏览器会检查证书是否合法,如果合法就会使用证书中的公钥来与服务器协商生成一个会话密钥。这个会话密钥是由浏览器和服务器协商生成的,用于加密本次通信的所有数据。 - Redis有哪几种持久化方式,各有什么优缺点?
Redis的持久化方式主要有三种:
(1)RDB。它是redis的默认持久化方式,它的原理是在一定的时间间隔内将内存中的数据持久化到磁盘当中。
优点:其生成的紧凑压缩的二进制文件体积小,使用该文件恢复数据的速度非常快;
缺点:持久化操作每次运行都要执行fork操作创建子进程,这属于重量级操作,不宜频繁执行,因此RDB无法做到实时的持久化;
并且安全性相对较低,RDB是隔一段时间进行数据备份,在此期间如果发生了异常,可能导致数据的不完整性;
(2)AOF。它是以日志的形式记录服务器所处理的每一个写操作,在Redis服务器启动之初会读取该文件来重新构建数据库,以保证启动后数据库的数据是完整的;
优点:AOF持久化的数据安全性很高,用户可以将数据丢失的时间窗口限制在1s以内,即使发生故障也只会丢失1s的数据;
缺点:AOF文件的体积要比二进制文件的‘.rdb’文件大很多;并且恢复数据的速率要比RDB慢;
(3)RDB-AOF混合持久化。RDB-AOF混合持久化是Redis4.0开始引入的持久化方式,它是基于AOF的持久化方式构建的,可以通过配置文件的”aof-use-rdb-preamble yes“开启混合持久化;
用户可以获得RDB持久化和AOF持久化的优点,服务器既可以通过AOF文件包含的RDB数据来实现快速的数据恢复操作,又可以通过AOF包含的AOF文件来把丢失文件的时间窗口限定在1s以内; - 算法题:编写函数实现字符串翻转(可用任何熟悉的语言,但不要使用系统自带的翻转函数)例:给定字符串“abcdefg”,函数返回“gfedcba”
下面是用Java语言编写的反转字符串的相关代码,代码思路是先把字符串转化为字符数组,之后采用双指针法,用两个指针分别指向字符数组的开头和结尾,然后交换这两个指针所指的字符,再将两个指针同时向中间移动一位,重复这个过程,直到两个指针相遇。完成反转。
public class Main {
public static String reverseString(String s) {
char[] charArray = s.toCharArray();
int left = 0;
int right = charArray.length - 1;
while (left < right) {
char temp = charArray[left];
charArray[left] = charArray[right];
charArray[right] = temp;
left++;
right--;
}
return new String(charArray);
}
public static void main(String[] args) {
String str = reverseString(“abcdefg”);
System.out.println(str);
}
}
- 制造一个mysql死锁.
首先我们需要知道,MySQL死锁是由于多个事务同时访问数据库中的数据,并且持有对其他事务所持有的数据的锁,导致每个事务都无法继续执行的现象。
下面是相应的sql代码示例:
```sql
//创建两个表t1,t2
CREATE TABLE t1 (
id INT NOT NULL PRIMARY KEY,
val INT NOT NULL
);
CREATE TABLE t2 (
id INT NOT NULL PRIMARY KEY,
val INT NOT NULL
);
//表中插入数据
INSERT INTO t1 (id, val) VALUES (1, 10);
INSERT INTO t2 (id, val) VALUES (1, 20);
//开启第一个事务
START TRANSACTION;
//获取t1表的锁
SELECT * FROM t1 WHERE id = 1 FOR UPDATE;
//更新t1的val值
UPDATE t1 SET val = val + 1 WHERE id = 1;
//获取t2表中的锁
SELECT * FROM t2 WHERE id = 1 FOR UPDATE;
//更新t2表中的val值
UPDATE t2 SET val = val + 1 WHERE id = 1;
//提交事务
COMMIT;
//开始第二个事务
START TRANSACTION;
//获取t2的锁
SELECT * FROM t2 WHERE id = 1 FOR UPDATE;
//更新t2表中的val值
UPDATE t2 SET val = val + 1 WHERE id = 1;
//获取t1的锁
SELECT * FROM t1 WHERE id = 1 FOR UPDATE;
//更新t2表中的val值
UPDATE t1 SET val = val + 1 WHERE id = 1;
//提交事务
COMMIT;
由于在上述代码中,第一个事务中,我们先更新 t1 表,然后更新 t2 表。在第二个事务中,我们则先更新 t2 表,然后更新 t1 表。由于我们使用了不同的顺序来获取行锁,所以这两个事务会相互等待,导致死锁。
5. 项目设计:设计一个会员推广系统,每个用户每个月有工资,每个用户可以推广发展下线,推广人可以获取下线工资按一定比例分配的提成(最多5层下线),第一层: 10%,第二层: 8%,第三层:5%,第四层:3%,第五层: 1%。请设计相关数据表和计算某一个用户获得总提成的算法
首先设计用户表:
字段名 类型 说明
id int 用户ID,主键
name varchar 用户名
salary int 工资
parent_id int 父级id,用于表示发展下线关系,为空则表示为顶级用户
提成表:
字段名 类型 说明
id int 用户id
level int 下线等级
percentage int 提成比例,如 10% 表示为 10
amount int 提成金额(元)
计算某一个用户获得总提成的算法:(Java语言,递归实现)
// 用于存储用户信息的类
class User {
int userId;
String name;
int salary;
int parentId;
Map<Integer, User> children = new HashMap<>();
Commission commission;
public User(int userId, String name, int salary, int parentId) {
this.userId = userId;
this.name = name;
this.salary = salary;
this.parentId = parentId;
}
}
// 用于存储提成信息的类
class Commission {
int userId;
int level;
int percentage;
int amount;
public Commission(int userId, int level, int percentage, int amount) {
this.userId = userId;
this.level = level;
this.percentage = percentage;
this.amount = amount;
}
}
// 计算某一个用户的总提成
public int calculateTotalCommission(User user) {
// 定义变量用于存储总提成
int totalCommission = 0;
// 递归函数,计算指定用户的总提成
public void calculateCommission(User user) {
// 累加提成金额
totalCommission += user.commission.amount;
// 如果该用户还有下线,则递归调用本函数
for (User child : user.children.values()) {
calculateCommission(child);
}
}
// 调用递归函数
calculateCommission(user);
// 返回总提成
return totalCommission;
}