引出
1.驗(yàn)證碼:如何生成一個(gè)唯一的ID;
2.UUID和雪花ID,雪花ID遞增趨勢(shì),純數(shù)字;
3.驗(yàn)證碼應(yīng)用,生成驗(yàn)證碼,過(guò)期時(shí)間,存redis,前端顯示;
4.JMeter高并發(fā)測(cè)試,官網(wǎng)下載,漢語(yǔ)設(shè)置;
5.JMeter的使用方法;文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-601621.html
Redis的項(xiàng)目應(yīng)用(一):驗(yàn)證碼
凡是和搶相關(guān)的,redis+MQ
1.整體流程
2.雪花ID
1)UUID(Universally Unique Identifier,通用唯一識(shí)別碼)
UUID(Universally Unique Identifier,通用唯一識(shí)別碼)是按照開放軟件基金會(huì)(OSF)制定的標(biāo)準(zhǔn)計(jì)算,用到了以太網(wǎng)卡地址、納秒級(jí)時(shí)間、芯片 ID 碼和許多可能的數(shù)字。
UUID 是由一組 32 位數(shù)組成,由16 進(jìn)制數(shù)字所構(gòu)成,是故 UUID 理論上的總數(shù)為16的32次方。這個(gè)總數(shù)是多大呢?打個(gè)比方,如果每納秒產(chǎn)生 1 百萬(wàn)個(gè) UUID,要花 100 億年才會(huì)將所有 UUID 用完。
UUID 通常以連字號(hào)分隔的五組來(lái)顯示,形式為 8-4-4-4-12
,總共有 36 個(gè)字符(即 32 個(gè)英數(shù)字母和 4 個(gè)連字號(hào))。例如: 123e4567-e89b-12d3-a456-426655440000 。
JDK 從 1.5 開始在 java.util 包下提供了一個(gè) UUID 類用來(lái)生成 UUID:
UUID uuid = UUID.randomUUID();
String uuidStr1 = uuid.toString();
String uuidStr2 = uuidStr1.replaceAll("-","");
UUID 的缺點(diǎn)和一個(gè)『好』ID 的標(biāo)準(zhǔn)
UUID的缺點(diǎn):
為了得到一個(gè)全局唯一 ID,很自然地就會(huì)想到 UUID 算法。但是,UUID 算法有明顯的缺點(diǎn):
-
UUID 太長(zhǎng)了,通常以 36 長(zhǎng)度的字符串表示,很多場(chǎng)景不適用。
-
非純數(shù)字。UUID 中會(huì)出現(xiàn) ABCDEF 這些十六進(jìn)制的字母,因此,在數(shù)據(jù)庫(kù)和代碼中,自然就不能存儲(chǔ)在整型字段或變量。因此,在數(shù)據(jù)庫(kù)中以它作為主鍵,建立索引的代價(jià)比較大,性能有影響。
-
不安全。UUID 中會(huì)包含網(wǎng)卡的 MAC 地址。
一個(gè)『好』ID 的標(biāo)準(zhǔn)應(yīng)該有哪些:
-
最好是由純數(shù)字組成。
-
越短越好,最好能存進(jìn)整型變量和數(shù)據(jù)庫(kù)的整型字段中。
-
信息安全。另外,『ID 連續(xù)』并非好事情。
-
在不連續(xù)的情況下,最好是遞增的。即便不是嚴(yán)格遞增,至少也應(yīng)該是趨勢(shì)遞增。
2)Twitter 的雪花算法(SnowFlake)
Snowflake 是 Twitter(美國(guó)推特公司)開源的分布式 ID 生成算法。最初 Twitter 把存儲(chǔ)系統(tǒng)從 MySQL 遷移到 Cassandra(它是NoSQL數(shù)據(jù)庫(kù)),因?yàn)镃assandra 沒(méi)有順序 ID 生成機(jī)制,所以 Twitter 開發(fā)了這樣一套全局唯一 ID 生成服務(wù)。
SnowFlake 優(yōu)點(diǎn):
整體上按照時(shí)間自增排序,并且整個(gè)分布式系統(tǒng)內(nèi)不會(huì)產(chǎn)生 ID 碰撞(由數(shù)據(jù)中心 ID 和機(jī)器 ID 作區(qū)分),并且效率較高。經(jīng)測(cè)試,SnowFlake 每秒能夠產(chǎn)生 26 萬(wàn) ID 左右。
Snowflake 會(huì)生成一個(gè) long 類型的數(shù)值,long是8個(gè)字節(jié),一共是64位,Snowflake 對(duì)于 long 的各個(gè)位都有固定的規(guī)范:
位數(shù) | 作用 |
---|---|
時(shí)間戳41位 | 當(dāng)前時(shí)間戳與指定的時(shí)間戳之間的差值,即:(指定時(shí)間戳 - 當(dāng)前時(shí)間戳)。 |
數(shù)據(jù)中心5位 | 配置文件或環(huán)境構(gòu)成,比如使用ip地址生成。 |
實(shí)例(機(jī)器標(biāo)志位)5位 | 同一數(shù)據(jù)中心,機(jī)器碼設(shè)置。 |
12位毫秒內(nèi)的計(jì)數(shù)器 | 1毫秒之內(nèi)產(chǎn)生不同id |
-
最高位標(biāo)識(shí)(1 位)
由于 long 基本類型在 Java 中是帶符號(hào)的,最高位是符號(hào)位,正數(shù)是 0,負(fù)數(shù)是 1,因?yàn)?id 一般是正數(shù),所以最高位是 0 。
-
毫秒級(jí)時(shí)間戳(41 位)
注意,41 位時(shí)間戳不是存儲(chǔ)當(dāng)前時(shí)間的時(shí)間戳,而是存儲(chǔ)時(shí)間的差值(當(dāng)前時(shí)間戳 - 開始時(shí)間戳) 得到的值,這里的的開始時(shí)間,一般是我們的 id 生成器開始使用的時(shí)間,由我們程序來(lái)指定的(如下面程序 IdGenerator 類的 startTime 屬性)。
41 位的時(shí)間截,可以使用 69 年。
2的41次方 除以 (1000毫秒 * 60 * 60 * 24 * 365) = 69
-
數(shù)據(jù)機(jī)器位(10 位)
10-bit機(jī)器可以分別表示1024臺(tái)機(jī)器,這 10 位的機(jī)器位實(shí)際上是由 5 位的 互聯(lián)網(wǎng)數(shù)據(jù)中心(datacenterId) 和 5 位的工作機(jī)器id(workerId) 。這樣就可以有32個(gè)互聯(lián)網(wǎng)數(shù)據(jù)中心(機(jī)房)(2的5次方),每個(gè)互聯(lián)網(wǎng)數(shù)據(jù)中心可以有32臺(tái)工作機(jī)器 。即,總共允許存在 1024 臺(tái)電腦各自計(jì)算 ID 。
每臺(tái)電腦都由 data-center-id 和 worker-id 標(biāo)識(shí),邏輯上類似于聯(lián)合主鍵的意思。
-
12位的自增序列號(hào),用來(lái)記錄同毫秒內(nèi)產(chǎn)生的不同id,就是一毫秒內(nèi)最多可以產(chǎn)生4096個(gè)id
毫秒內(nèi)的計(jì)數(shù),12為的自增序列號(hào) 支持每個(gè)節(jié)點(diǎn)每毫秒(同一機(jī)器,同一時(shí)間截)產(chǎn)生 4096(2的12次方) 個(gè) ID 序號(hào),這種分配方式可以保證在任何一個(gè)互聯(lián)網(wǎng)數(shù)據(jù)中心的任何一臺(tái)工作機(jī)器在任意毫秒內(nèi)生成的ID都是不同的
面試常問(wèn):如果是并發(fā)量高,同一臺(tái)機(jī)器一毫秒有5000個(gè)id,那么id會(huì)不會(huì)重復(fù),不會(huì),根據(jù)源碼如果一毫秒內(nèi)超過(guò)4096個(gè)id,則會(huì)阻塞到下一毫秒再生成
雪花ID優(yōu)缺點(diǎn)
優(yōu)點(diǎn)
1、生成速度快經(jīng)測(cè)試,SnowFlake每秒能夠產(chǎn)生26萬(wàn)ID左右。
2、生成id有序,雪花算法生成的id整體是遞增的,但是不是連續(xù)的。
3、本地即可生成,無(wú)需消耗額外的資源,如zookeeper、redis等。
缺點(diǎn)
1、id長(zhǎng)度比較長(zhǎng)(大概18位)
2、id不連續(xù),生成的id是無(wú)規(guī)則的。
3、如果機(jī)器時(shí)鐘回?fù)?,就?huì)導(dǎo)致id生成失敗。
4、不同機(jī)器的時(shí)鐘不是完全一致的,導(dǎo)致全局的id并不是統(tǒng)一向上自增。
時(shí)鐘回?fù)?/h4>
- 人為原因,把系統(tǒng)環(huán)境的時(shí)間改了。
- 有時(shí)候不同的機(jī)器上需要同步時(shí)間,可能不同機(jī)器之間存在誤差,那么可能會(huì)出現(xiàn)時(shí)間回?fù)軉?wèn)題。
- 人為原因,把系統(tǒng)環(huán)境的時(shí)間改了。
- 有時(shí)候不同的機(jī)器上需要同步時(shí)間,可能不同機(jī)器之間存在誤差,那么可能會(huì)出現(xiàn)時(shí)間回?fù)軉?wèn)題。
Leaf——美團(tuán)點(diǎn)評(píng)分布式ID生成系統(tǒng) - 美團(tuán)技術(shù)團(tuán)隊(duì) (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 // 自動(dòng)調(diào)用,在構(gòu)造方法前做
public void init(){
try {
workerId = NetUtil.ipv4ToLong(NetUtil.getLocalhostStr());
log.info("當(dāng)前機(jī)器的workId:{}",workerId);
}catch (Exception e){
log.error("當(dāng)前機(jī)器的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.生成驗(yàn)證碼
流程:
- 生成4位的驗(yàn)證碼;
- 產(chǎn)生唯一的id,作為驗(yàn)證碼的key;
- 以key,value的形式存儲(chǔ)到redis中;
- 前端顯示驗(yàn)證碼圖片;
設(shè)置驗(yàn)證碼的有效時(shí)間
// 3.redis中存儲(chǔ),key-value,設(shè)置有效時(shí)間為 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的調(diào)用,返回一張圖片
*/
@RestController
@RequestMapping("/api/user/code")
public class CodeDemoController {
@Resource
private StringRedisTemplate stringRedisTemplate;
@GetMapping("/snowcode.jpg")
public HttpRespSimple createCode(HttpServletResponse response) throws IOException {
// 1.產(chǎn)生驗(yàn)證碼
LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(200, 100, 4, 10);
String code = lineCaptcha.getCode();
// 2.產(chǎn)生唯一的值,作為key,用雪花id作為唯一的key
String key = SnowFlakeUtil.snowflakeIdStr(); // 生成雪花id,string類型的
// 3.redis中存儲(chǔ),key-value,設(shè)置有效時(shí)間為 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(">>>>>>>>>>>>驗(yàn)證碼為:"+code);
return new HttpRespSimple(20001, "驗(yàn)證碼創(chuàng)建成功");
}
@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取出存入的驗(yàn)證碼:"+stringRedisTemplate.opsForValue().get(key));
if (Objects.isNull(stringRedisTemplate.opsForValue().get(key))){
return new HttpRespSimple(40001, "驗(yàn)證碼無(wú)效");
}else {
return new HttpRespSimple(20002, "驗(yàn)證碼成功");
}
}
}
return new HttpRespSimple(20003, "驗(yàn)證碼不存在");
}
}
前端顯示
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>驗(yàn)證碼</title>
</head>
<body>
<!--http://localhost:9090/api/user/code/snowcode.jpg-->
<img src="/api/user/code/snowcode.jpg">
</body>
</html>
5.JMeter測(cè)試驗(yàn)證碼生成
1)新建線程組
2)設(shè)置參數(shù)
3)添加取樣器
4)設(shè)置參數(shù):協(xié)議,ip,端口,請(qǐng)求方式,路徑
5)添加查看結(jié)果樹
6)啟動(dòng)+查看結(jié)果
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.官網(wǎng)下載
2.下載后解壓
3.漢語(yǔ)設(shè)置
JMeter的使用方法
1.新建線程組
2.設(shè)置參數(shù)
3.添加取樣器
4.設(shè)置參數(shù):協(xié)議,ip,端口,請(qǐng)求方式,路徑
5.添加查看結(jié)果樹
6.啟動(dòng)+查看結(jié)果
文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-601621.html
總結(jié)
1.驗(yàn)證碼:如何生成一個(gè)唯一的ID;
2.UUID和雪花ID,雪花ID遞增趨勢(shì),純數(shù)字;
3.驗(yàn)證碼應(yīng)用,生成驗(yàn)證碼,過(guò)期時(shí)間,存redis,前端顯示;
4.JMeter高并發(fā)測(cè)試,官網(wǎng)下載,漢語(yǔ)設(shè)置;
5.JMeter的使用方法;
到了這里,關(guān)于Redis應(yīng)用(2)——Redis的項(xiàng)目應(yīng)用(一):驗(yàn)證碼 ---> UUID到雪花ID & JMeter高并發(fā)測(cè)試 & 下載安裝使用的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!