Redis应用(2)——Redis的项目应用(一):验证码 ---> UUID到雪花ID JMeter高并发测试 下载安装使用

news2024/11/24 7:37:50

目录

  • 引出
  • Redis的项目应用(一):验证码
    • 1.整体流程
    • 2.雪花ID
      • 1)UUID(Universally Unique Identifier,通用唯一识别码)
      • 2)Twitter 的雪花算法(SnowFlake)
    • 雪花ID优缺点
      • 优点
      • 缺点
      • 时钟回拨
    • 3.雪花id的工具类SnowFlakeUtil.java
    • 4.生成验证码
      • 前端显示
    • 5.JMeter测试验证码生成
  • JMeter
    • 什么是JMeter?
    • JMeter安装配置
      • 1.官网下载
      • 2.下载后解压
      • 3.汉语设置
  • JMeter的使用方法
    • 1.新建线程组
    • 2.设置参数
    • 3.添加取样器
    • 4.设置参数:协议,ip,端口,请求方式,路径
    • 5.添加查看结果树
    • 6.启动+查看结果
  • 总结

引出


1.验证码:如何生成一个唯一的ID;
2.UUID和雪花ID,雪花ID递增趋势,纯数字;
3.验证码应用,生成验证码,过期时间,存redis,前端显示;
4.JMeter高并发测试,官网下载,汉语设置;
5.JMeter的使用方法;

Redis的项目应用(一):验证码

凡是和抢相关的,redis+MQ

1.整体流程

在这里插入图片描述

2.雪花ID

1)UUID(Universally Unique Identifier,通用唯一识别码)

UUID(Universally Unique Identifier,通用唯一识别码)是按照开放软件基金会(OSF)制定的标准计算,用到了以太网卡地址、纳秒级时间、芯片 ID 码和许多可能的数字。

UUID 是由一组 32 位数组成,由16 进制数字所构成,是故 UUID 理论上的总数为16的32次方。这个总数是多大呢?打个比方,如果每纳秒产生 1 百万个 UUID,要花 100 亿年才会将所有 UUID 用完。

UUID 通常以连字号分隔的五组来显示,形式为 8-4-4-4-12,总共有 36 个字符(即 32 个英数字母和 4 个连字号)。例如: 123e4567-e89b-12d3-a456-426655440000

JDK 从 1.5 开始在 java.util 包下提供了一个 UUID 类用来生成 UUID:

UUID uuid = UUID.randomUUID();
String uuidStr1 = uuid.toString();
String uuidStr2 = uuidStr1.replaceAll("-","");

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并不是统一向上自增。

时钟回拨

  1. 人为原因,把系统环境的时间改了。
  2. 有时候不同的机器上需要同步时间,可能不同机器之间存在误差,那么可能会出现时间回拨问题。

Leaf——美团点评分布式ID生成系统 - 美团技术团队 (meituan.com)

uid-generator/README.zh_cn.md at master · baidu/uid-generator · GitHub

3.雪花id的工具类SnowFlakeUtil.java

<!--        雪花id-->
        <!--    工具包-->
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.8.11</version>
        </dependency>
package 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, "验证码不存在");
    }
}

在这里插入图片描述

前端显示

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>验证码</title>
</head>
<body>
<!--http://localhost:9090/api/user/code/snowcode.jpg-->
<img src="/api/user/code/snowcode.jpg">

</body>
</html>

5.JMeter测试验证码生成

1)新建线程组

在这里插入图片描述

2)设置参数

在这里插入图片描述

3)添加取样器

在这里插入图片描述

4)设置参数:协议,ip,端口,请求方式,路径

在这里插入图片描述

5)添加查看结果树

在这里插入图片描述

6)启动+查看结果

在这里插入图片描述

在这里插入图片描述

JMeter

在这里插入图片描述

什么是JMeter?

Apache JMeter™

The Apache JMeter™ application is open source software, a 100% pure Java application designed to load test functional behavior and measure performance(接口性能),It was originally designed for testing Web Applications but has since expanded to other test functions.

JMeter安装配置

1.官网下载

在这里插入图片描述

2.下载后解压

在这里插入图片描述

3.汉语设置

在这里插入图片描述

JMeter的使用方法

在这里插入图片描述

1.新建线程组

在这里插入图片描述

2.设置参数

在这里插入图片描述

3.添加取样器

在这里插入图片描述

4.设置参数:协议,ip,端口,请求方式,路径

在这里插入图片描述

5.添加查看结果树

在这里插入图片描述

6.启动+查看结果

在这里插入图片描述


总结

1.验证码:如何生成一个唯一的ID;
2.UUID和雪花ID,雪花ID递增趋势,纯数字;
3.验证码应用,生成验证码,过期时间,存redis,前端显示;
4.JMeter高并发测试,官网下载,汉语设置;
5.JMeter的使用方法;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/781141.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Jenkins常用管理功能配置 - 插件管理

Jenkins插件介绍 Jenkins是一个流行的开源持续集成/持续交付(CI/CD)工具&#xff0c;它有大量的插件来扩展其功能。这些插件可以用于构建、测试、部署和监控软件项目。下面是一些常用的Jenkins插件及其简单介绍和使用方法&#xff1a; 1. Git插件&#xff1a;允许Jenkins从Gi…

网络概念,《TCP/IP五层网络模型》与《数据的网络传输---“封装”与“分用”过程》

文章目录 概念协议协议分层TCP/IP五层网络模型数据的网络传输---“封装”与“分用”“封装”与“分用” 的过程 接收过程 概念 局域网&#xff1a;把一些设备通过交换机/路由器连接起来。 广域网&#xff1a;把更多的局域网也相互连接称为广域网。 交换机&#xff1a;交换机是…

采用桥接模式使虚拟机\笔记本\linux台式机互通

目录 一、环境&#xff1a;二、连接模式1. 桥接模式2. 主机共享模式3. NAT模式 三、配置1. 笔记本WIFI网络配置2. VM配置3.虚拟机配置3.1. 先看网络信息&#xff0c;确定修改ens333.2. 修改ens333.3. 重启网络 四、测试五、错误解决5.1 现象5.2 解决办法5.3 结果 一、环境&…

Spring中Bean的作用域和Spring生命周期

从前面的文章中我们看出Spring是用来存储和读取Bean的&#xff0c;因此Spring中Bean是最核心的资源&#xff0c;所以我们将对Bean进行深入的理解。 Bean的作用域 现在有一个公共的Bean&#xff0c;提供给了两个用户去使用&#xff0c;但是在使用过程中&#xff0c;用户一修改…

Android Studio 修改AVD模拟器文件默认存储路径

AndroidStudio默认的模拟器文件路径为&#xff1a;C:\Users\用户名\.android\avd路径&#xff0c;通常windows系统上&#xff0c;C盘不是太大&#xff0c;而avd文件却不小&#xff0c;通常几个GB&#xff0c;所以有必要将avd路径换到一个非系统盘。 更换方法如下&#xff1a;H…

LeetCode:6. N 字形变换

&#x1f34e;道阻且长&#xff0c;行则将至。&#x1f353; &#x1f33b;算法&#xff0c;不如说它是一种思考方式&#x1f340; 算法专栏&#xff1a; &#x1f449;&#x1f3fb;123 题解目录 一、&#x1f331;[6. N 字形变换](https://leetcode.cn/problems/zigzag-conv…

5.3 Bootstrap 模态框(Modal)插件

文章目录 Bootstrap 模态框&#xff08;Modal&#xff09;插件用法选项方法事件 Bootstrap 模态框&#xff08;Modal&#xff09;插件 模态框&#xff08;Modal&#xff09;是覆盖在父窗体上的子窗体。通常&#xff0c;目的是显示来自一个单独的源的内容&#xff0c;可以在不离…

C语言:杨氏矩阵中查找某数(时间复杂度小于O(N))

题目&#xff1a; 有一个数字矩阵&#xff08;二维数组&#xff09;&#xff0c; 矩阵的每行从左到右是递增的&#xff0c;矩阵从上到下是递增的&#xff0c; 请编写程序在这样的矩阵中查找某个数字是否存在&#xff0c; 要求&#xff1a;时间复杂度小于O(N)。 思路&#xff1…

Linux中docker的基本操作

文章目录 一、docker概述1.1 什么是docker1.2 Docker与虚拟机的特性区别1.3 容器在内核中支持2种重要技术1.4 docker的核心概念 二、安装docker三、Docker 镜像操作四、Docker 容器操作 一、docker概述 1.1 什么是docker 是一个开源的应用容器引擎&#xff0c;基于go语言开发…

Spring Web MVC 详解(1)

目录 一、介绍 MVC 二、Spring MVC 的三个基本功能 1.1 连接功能 1.2 Spring MVC 的创建和使用 1.3 RequestMappig 介绍 1.4 Spring MVC 实现用户和 Spring 程序的连接 1.5 GetMapping 和 PostMaping 注解 1.6 Get 和 Post请求注解的多种写法 2.1 获取请求中参数的功…

Redis的内存回收与内存淘汰策略

对于redis这样的内存型数据库而言&#xff0c;如何删除已过期的数据以及如何在内存满时回收内存是一项很重要的工作。 常见的redis内存回收的工作主要分为两个方面&#xff1a; 清理过期的key在内存不足时回收到足够的内存用以存储新的key 清理过期的key 我们很少在redis中…

直接插入排序、希尔排序、直接选择排序、堆排序、冒泡排序——“数据结构与算法”

各位CSDN的uu们你们好呀&#xff0c;今天小雅兰的内容是数据结构与算法啦&#xff0c;是排序&#xff01;&#xff01;&#xff01;下面&#xff0c;让我们进入七大排序的世界吧&#xff01;&#xff01;&#xff01; 排序的概念及其运用 排序的概念 排序&#xff1a;所谓排序…

算法提高-动态规划-斜率优化DP

斜率优化DP AcWing 300. 任务安排1AcWing 301. 任务安排2AcWing 302. 任务安排3AcWing 303. 运输小猫 AcWing 300. 任务安排1 #include <iostream> #include <cstring>typedef long long LL;using namespace std;const int N 5e3 10;int st[N], sc[N]; LL f[N];…

全志F1C200S嵌入式驱动开发(基于usb otg的spi-nor镜像烧入)

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】 前面既然已经搞定了spi-nor驱动,那么下一步考虑的就是怎么从spi-nor flash上面加载uboot、kernel和rootfs。目前spi-nor就是一块白片,上面肯定什么都没有,那么这个时候,我们要做…

贤鱼的刷题日常-P3375 【模板】KMP 字符串匹配

&#x1f3c6;今日学习目标&#xff1a; &#x1f340;例题讲解P3375 【模板】KMP 字符串匹配 ✅创作者&#xff1a;贤鱼 ⏰预计时间&#xff1a;25分钟 &#x1f389;个人主页&#xff1a;贤鱼的个人主页 &#x1f525;专栏系列&#xff1a;c &#x1f341;贤鱼的个人社区&…

(css)清除el-table背景色

(css)清除el-table背景色 效果&#xff1a; <el-table:data"gridData":header-cell-style"{text-align:center,color: #fff}":cell-style"{text-align:center,color: #fff }" ><el-table-column type"index" label"序号…

linux下 UART串口相关

RS232的串口设备在linux 上会被识别为 /dev/ttyS* 或者 ttymxc* 一、串口简介 操作串口我们一般通过以下指令&#xff1a; 1、查看串口波特率等信息&#xff1a; stty -F /dev/ttyS0 -a #ttyS0为要查看的串口 2、设置串口参数&#xff1a; stty -F /dev/ttyS0 ispeed 115…

Qt实现双控制柄的Slider

目标 实现带有左右两个控制柄的滑动条&#xff1b;控件可设定最小值和最大值&#xff1b;控件可设定控制柄的最小距离&#xff1b; 效果演示 思路 1. 标准的Slider控件只有一个Handle&#xff0c;所以想要通过改造QSlider来实现两个Handle是非常困难的&#xff0c;“自绘”…

SpringBoot+jasypt-spring-boot-starter实现配置文件明文加密

1.使用环境 springboot:2.1.4.RELEASE JDK:8 jasypt-spring-boot-starter:3.0.2 2.引入依赖 !-- 配置文件加密 --> <dependency><groupId>com.github.ulisesbocchio</groupId><artifactId>jasypt-spring-boot-starter</artifactId><ver…

rust学习-智能指针

适用场景 有一个在编译时未知大小的类型&#xff0c;想在需要确切大小的上下文使用该类型值 示例1 无意义的例子&#xff1a;将一个单独的值存放在堆上并不是很有意义&#xff0c;b更应该放到栈上 fn main() {let b Box::new(5);// box 在 main 的末尾离开作用域时&#x…