先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7
深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年最新软件测试全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上软件测试知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新
如果你需要这些资料,可以添加V获取:vip1024b (备注软件测试)
正文
UUID 的缺点和一个『好』ID 的标准
UUID的缺点:
为了得到一个全局唯一 ID,很自然地就会想到 UUID 算法。但是,UUID 算法有明显的缺点:
- UUID 太长了,通常以 36 长度的字符串表示,很多场景不适用。
- 非纯数字。UUID 中会出现 ABCDEF 这些十六进制的字母,因此,在数据库和代码中,自然就不能存储在整型字段或变量。因此,在数据库中以它作为主键,建立索引的代价比较大,性能有影响。
- 不安全。UUID 中会包含网卡的 MAC 地址。
一个『好』ID 的标准应该有哪些:
- 最好是由纯数字组成。
- 越短越好,最好能存进整型变量和数据库的整型字段中。
- 信息安全。另外,『ID 连续』并非好事情。
- 在不连续的情况下,最好是递增的。即便不是严格递增,至少也应该是趋势递增。
2)Twitter 的雪花算法(SnowFlake)
Snowflake 是 Twitter(美国推特公司)开源的分布式 ID 生成算法。最初 Twitter 把存储系统从 MySQL 迁移到 Cassandra(它是NoSQL数据库),因为Cassandra 没有顺序 ID 生成机制,所以 Twitter 开发了这样一套全局唯一 ID 生成服务。
SnowFlake 优点:
整体上按照时间自增排序,并且整个分布式系统内不会产生 ID 碰撞(由数据中心 ID 和机器 ID 作区分),并且效率较高。经测试,SnowFlake 每秒能够产生 26 万 ID 左右。
Snowflake 会生成一个 long 类型的数值,long是8个字节,一共是64位,Snowflake 对于 long 的各个位都有固定的规范:
位数 | 作用 |
---|---|
时间戳41位 | 当前时间戳与指定的时间戳之间的差值,即:(指定时间戳 - 当前时间戳)。 |
数据中心5位 | 配置文件或环境构成,比如使用ip地址生成。 |
实例(机器标志位)5位 | 同一数据中心,机器码设置。 |
12位毫秒内的计数器 | 1毫秒之内产生不同id |
- 最高位标识(1 位)
由于 long 基本类型在 Java 中是带符号的,最高位是符号位,正数是 0,负数是 1,因为 id 一般是正数,所以最高位是 0 。
- 毫秒级时间戳(41 位)
注意,41 位时间戳不是存储当前时间的时间戳,而是存储时间的差值(当前时间戳 - 开始时间戳) 得到的值,这里的的开始时间,一般是我们的 id 生成器开始使用的时间,由我们程序来指定的(如下面程序 IdGenerator 类的 startTime 属性)。
41 位的时间截,可以使用 69 年。
2的41次方 除以 (1000毫秒 * 60 * 60 * 24 * 365) = 69
- 数据机器位(10 位)
10-bit机器可以分别表示1024台机器,这 10 位的机器位实际上是由 5 位的 互联网数据中心(datacenterId) 和 5 位的工作机器id(workerId) 。这样就可以有32个互联网数据中心(机房)(2的5次方),每个互联网数据中心可以有32台工作机器 。即,总共允许存在 1024 台电脑各自计算 ID 。
每台电脑都由 data-center-id 和 worker-id 标识,逻辑上类似于联合主键的意思。
- 12位的自增序列号,用来记录同毫秒内产生的不同id,就是一毫秒内最多可以产生4096个id
毫秒内的计数,12为的自增序列号 支持每个节点每毫秒(同一机器,同一时间截)产生 4096(2的12次方) 个 ID 序号,这种分配方式可以保证在任何一个互联网数据中心的任何一台工作机器在任意毫秒内生成的ID都是不同的
面试常问:如果是并发量高,同一台机器一毫秒有5000个id,那么id会不会重复,不会,根据源码如果一毫秒内超过4096个id,则会阻塞到下一毫秒再生成
雪花ID优缺点
优点
1、生成速度快经测试,SnowFlake每秒能够产生26万ID左右。
2、生成id有序,雪花算法生成的id整体是递增的,但是不是连续的。
3、本地即可生成,无需消耗额外的资源,如zookeeper、redis等。
缺点
1、id长度比较长(大概18位)
2、id不连续,生成的id是无规则的。
3、如果机器时钟回拨,就会导致id生成失败。
4、不同机器的时钟不是完全一致的,导致全局的id并不是统一向上自增。
时钟回拨
- 人为原因,把系统环境的时间改了。
- 有时候不同的机器上需要同步时间,可能不同机器之间存在误差,那么可能会出现时间回拨问题。
Leaf——美团点评分布式ID生成系统 - 美团技术团队 (meituan.com)
uid-generator/README.zh_cn.md at master · baidu/uid-generator · GitHub
3.雪花id的工具类SnowFlakeUtil.java
cn.hutool hutool-all 5.8.11package com.tianju.springboot.util;
import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.net.NetUtil;
import cn.hutool.core.util.IdUtil;
import lombok.extern.slf4j.Slf4j;
import javax.annotation.PostConstruct;
/**
* 雪花id的工具类
*/
@Slf4j
public class SnowFlakeUtil {
private static long workerId = 0;
private static long datacenterId = 1;
private static Snowflake snowflake = IdUtil.getSnowflake(workerId,datacenterId);
@PostConstruct // 自动调用,在构造方法前做
public void init(){
try {
workerId = NetUtil.ipv4ToLong(NetUtil.getLocalhostStr());
log.info(“当前机器的workId:{}”,workerId);
}catch (Exception e){
log.error(“当前机器的workId获取失败”,e);
workerId = NetUtil.getLocalhostStr().hashCode();
}
}
public static synchronized long snowflakeId(){
return snowflake.nextId();
}
public static synchronized String snowflakeIdStr(){
return String.valueOf(snowflake.nextId());
}
public static void main(String[] args) {
System.out.println(SnowFlakeUtil.snowflakeIdStr());
}
}
4.生成验证码
流程:
- 生成4位的验证码;
- 产生唯一的id,作为验证码的key;
- 以key,value的形式存储到redis中;
- 前端显示验证码图片;
设置验证码的有效时间
// 3.redis中存储,key-value,设置有效时间为 60 s
stringRedisTemplate.opsForValue().set(key,code,60,TimeUnit.SECONDS);
package com.tianju.springboot.controller;
import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.LineCaptcha;
import com.tianju.springboot.dto.HttpRespSimple;
import com.tianju.springboot.util.SnowFlakeUtil;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
/**
* 雪花id的调用,返回一张图片
*/
@RestController
@RequestMapping(“/api/user/code”)
public class CodeDemoController {
@Resource
private StringRedisTemplate stringRedisTemplate;
@GetMapping(“/snowcode.jpg”)
public HttpRespSimple createCode(HttpServletResponse response) throws IOException {
// 1.产生验证码
LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(200, 100, 4, 10);
String code = lineCaptcha.getCode();
// 2.产生唯一的值,作为key,用雪花id作为唯一的key
String key = SnowFlakeUtil.snowflakeIdStr(); // 生成雪花id,string类型的
// 3.redis中存储,key-value,设置有效时间为 60 s
stringRedisTemplate.opsForValue().set(key,code,60,TimeUnit.SECONDS);
// 4.返回给浏览器cookie
response.addCookie(new Cookie(“vc”, key));
// 5.显示到前端
lineCaptcha.write(response.getOutputStream());
System.out.println(“>>>>>>>>>>>>验证码为:”+code);
return new HttpRespSimple(20001, “验证码创建成功”);
}
@GetMapping(“/inputcode”)
public HttpRespSimple inputCode(HttpServletRequest request){
for (Cookie cookie: request.getCookies()) {
if (cookie.getName().equals(“vc”)){
String key = cookie.getValue();
System.out.println(“从redis取出存入的验证码:”+stringRedisTemplate.opsForValue().get(key));
if (Objects.isNull(stringRedisTemplate.opsForValue().get(key))){
return new HttpRespSimple(40001, “验证码无效”);
}else {
return new HttpRespSimple(20002, “验证码成功”);
}
}
}
return new HttpRespSimple(20003, “验证码不存在”);
}
}
前端显示
![](/api/user/code/snowcode.jpg)
5.JMeter测试验证码生成
1)新建线程组
2)设置参数
3)添加取样器
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
需要这份系统化的资料的朋友,可以添加V获取:vip1024b (备注软件测试)
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
3)添加取样器
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
需要这份系统化的资料的朋友,可以添加V获取:vip1024b (备注软件测试)
[外链图片转存中…(img-TCH5OZxT-1713358200510)]
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!