Sysbench 使用总结
Sysbench使用总结
实践环境
CentOS 7.8
Sysbench 1.0.20
下载地址:https://github.com/akopytov/sysbench/archive/refs/tags/1.0.20.tar.gz
用法介绍
sysbench [options]... [testname] [command]
具体说明:
testname
可选的内置测试类型名称、或者是和工具捆绑的
lua
脚本名称(不带后缀.lua
),形如oltp_read_only
,或者是指定lua
脚本的路径,形如sysbench-1.0.20/tests/include/oltp_legacy/oltp.lua
,可选内置测试名称如下:fileio
文件I/O测试cpu
CPU性能测试memory
内存测试threads
POSIX线程性能测试mutex
执行Mutext
性能测试(调度程序性能测试)说明:当
testname
指定为lua
脚本名称时,实际执行时,会到sysbench_installation_home/share/sysbench
目录下查找对应名称的脚本,找到后再执行脚本。可通过
sysbench <testname> help
查看每种测试支持的选项问题:如果
testname
为lua
脚本名称、lua
脚本路径时,咋知道该脚本支持的选项有哪些,选项参数默认值为多少呢?解答:这个就要看
testname
对应脚本引用的common.lua
脚本文件,该文件中定义的set_vars
函数定义了命令支持的选项,以及对应的默认值,具体参见下文。然后,分析待执行的脚本中用到了哪些选项。command
命令会被传递给内置测试名称或者由testname
指定的脚本,其定义了测试必须执行的动作。可用命令列表取决于特定的测试,有些测试也实现了自己的命令。以下为典型的测试命令的描述:prepare
测试前的准备操作,比如为fileio
测试创建必要的文件,或者为数据库测试基线填充测试数据库。run
运行由testname参数指定的测试。所有测试都支持该命令。cleanup
测试运行完成后,移除测试创建的临时数据,比如删除创建的表help
显示testname
使用帮助
options
可选项,常见选项许下常用一般命令行选项
--threads
需要创建的worker线程数量 默认值 1--events=N
设置期望执行的事件总数。0表示不限制 默认值 0--time=N
设置总执行时间,单位秒。0表示不限制。 默认值 10--forced-shutdown=STRING
超过--time
限制后,关闭程序之前需要等待的秒数,如果设置为off则表示不启用。 默认值 off--rate=N
平均事务速率。 0表示不限制。默认值 0
--report-interval=N
设置定期报告中间统计的时间间隔为N,单位为秒 。 0表示不设置。默认值 0注意:
- 如果运行程序命令时,如果当前总执行时间已经达到
--time
选项参数值(默认10秒),不管当前已执行事件总数是否达到--events
选项参数值,都会停止运行程序,所以如果需要为程序命令显示指定--events
选项时,需要合理的设置--time
选项参数值。 - 如果运行程序命令时,如果当前已执行事件总数已达到
--events
选项参数值,不管当前总执行时间是否达到--time
选项参数值,都会停止测试
常用日志选项
--verbosity=N
日志详细级别 {5 - debug, 0 - 仅critical messages} 默认值 3--percentile=N
延时统计(latency statistics)中,需要计算的百分比 (1-100)。设置为0表示禁用百分比值计算。 Use the special常用数据库选项
--db-driver=STRING
设置程序使用的数据库驱动。默认值 mysql常用mysql 选项:
--mysql-host=host
mysql服务主机地址 默认localhost
--mysql-port=3306
mysql服务端口 默认值 3306
--mysql-user=STRING
mysql用户名称 默认值 sbtest
--mysql-password=STRING
mysql密码,默认值 []
--mysql-db=STRING
mysql数据库名称 默认 sbtest- 如果运行程序命令时,如果当前总执行时间已经达到
应用实践
mysql数据库性能基准测试
创建数据库
CREATE DATABASE `sbtest` DEFAULT CHARACTER SET utf8;
注意:如果不事先创建数据库,则运行一下测试脚本时,会报错:FATAL: error 1049: Unknown database 'sbtest'
插入数据测试
运行压测准备命令
# sysbench --oltp-tables-count=5 --oltp_table_size=0 --mysql-host=10.118.80.88 --mysql-user=testacc --mysql-password=test1234 sysbench-1.0.20/tests/include/oltp_legacy/insert.lua prepare
说明:
1、执行以上命令后,会自动创建5张空表
2、sysbench-1.0.20/tests/include/oltp_legacy/insert.lua
是sysbench
工具压缩包中自带脚本,下文所用到的脚本皆非自定义脚本,不再赘述
运行插入数据测试
# sysbench --threads=80 --time=600 --events=50000000 --oltp-tables-count=5 --oltp_table_size=10000000 --mysql-host=10.118.80.88 --mysql-user=testacc --mysql-password=test1234 sysbench-1.0.20/tests/include/oltp_legacy/insert.lua run > result.txt
查看运行结果
略
混合操作测试
# sysbench --threads=300 --time=1200 --oltp-tables-count=5 --oltp_table_size=10000000 mysql-host=10.118.80.88 --mysql-user=testacc --mysql-password=test1234 sysbench-1.0.20/tests/include/oltp_legacy/oltp.lua run > result.txt
运行清理命令
# sysbench --oltp-tables-count=5 --mysql-host=10.118.80.88 --mysql-user=testacc --mysql-password=test1234 sysbench-1.0.20/tests/include/oltp_legacy/insert.lua cleanup
注意:执行prepare
和cleanup
命令时的--oltp-tables-count
选项参数值要保持一致
lua
脚本分析
sysbench-1.0.20/tests/include/oltp_legacy/oltp.lua
具体分析参见中文注释
pathtest = string.match(test, "(.*/)") # 首先,正则匹配当前测试名称(sysbench命令行提供的testname)
if pathtest then # 如果测试名称正则匹配 .*/
# 说明测试名称为脚本,形如sysbench-1.0.20/tests/include/oltp_legacy/oltp.lua,因为测试脚本和common.lua位于同一层级目录,所以,拼接脚本所在目录路径和"common.lua"得到common.lua文件路径,然后,加载文件
dofile(pathtest .. "common.lua")
else # 否则,加载工具捆绑的common脚本,即sysbench_installation_home/share/sysbench/common.lua
require("common")
end
function thread_init() # 线程初始化函数定义
set_vars() # 调用common中的set_vars函数设置变量
# 如果数据库驱动为mysql、attachsql,并且mysql表引擎为myisam
if (((db_driver == "mysql") or (db_driver == "attachsql")) and mysql_table_engine == "myisam") then
# 则走下述逻辑
local i
local tables = {}
# 根据命令行oltp_tables_count参数值,初始化tables数组元素为表名,格式形如sbtestN WRITE,其中N从1开始,最大值等于oltp_tables_count,即表数量
for i=1, oltp_tables_count do
tables[i] = string.format("sbtest%i WRITE", i)
end
begin_query = "LOCK TABLES " .. table.concat(tables, " ,")
commit_query = "UNLOCK TABLES"
else # 否则定义事务起始查询语句为 begin_query为BEGIN,结束查询语句为 COMMIT
begin_query = "BEGIN"
commit_query = "COMMIT"
end
end
# 定义函数 用于获取查询条件
function get_range_str()
local start = sb_rand(1, oltp_table_size) # 随机获取 [1, 单表记录总数] 范围内的整数,作为范围查询条件起始值
return string.format(" WHERE id BETWEEN %u AND %u",
start, start + oltp_range_size - 1) # 返回查询条件WHERE id BETWEEN start AND (start + 99) (oltp_range_size默认为100
end
定义待执行的“事件”函数
function event()
local rs # 查询返回结果
local i
local table_name
# 以下变量用于存放字段值和查询
local c_val
local pad_val
local query
table_name = "sbtest".. sb_rand_uniform(1, oltp_tables_count) # 随机获取表名,格式形如 sbtestN,其中N为从[1,表数量]范围内的随机整数
if not oltp_skip_trx then # 如果不跳过事务,
db_query(begin_query) # 则执行do_query(oltp_skip_trx默认为false,所以这里会执行do_query),即标记事务开始
end
if not oltp_write_only then # 如果not oltp_write_only为真(oltp_write_only默认为false)
# 则执行以下for循环(oltp_point_selects默认为10次,所以,会执行10次for循环查询,查询语句为:
# SELECT c FROM table_name WHERE id=id_value
# 说明:
# table_name 上述获取的随机表名,下同,不再赘述
# c 非索引列
# id 主键列
# id_value 目标id值,随机获取已存在记录ID
for i=1, oltp_point_selects do
rs = db_query("SELECT c FROM ".. table_name .." WHERE id=" ..
sb_rand(1, oltp_table_size))
end
if oltp_range_selects then # 如果oltp_range_selects为true,(oltp_range_selects默认为true)
# 执行按范围简单查询 1次(oltp_simple_ranges默认为1次,所以只会执行1次for循环查询)
# SQL语句为:
# SELECT c FROM table_name WHERE id BETWEEN id_value1 AND id_value2
# 说明:
# id_value1 随机获取已存在记录ID,下同,不再赘述
# id_value2 id_value1 + 99,下同,不再赘述
for i=1, oltp_simple_ranges do
rs = db_query("SELECT c FROM ".. table_name .. get_range_str())
end
# 执行 按范围sum查询 1次 (oltp_sum_ranges默认值为 1,所以只会执行1次for循环查询)
# SQL语句为:
# SELECT sum(c) FROM table_name WHERE id BETWEEN id_value1 AND id_value2
for i=1, oltp_sum_ranges do
rs = db_query("SELECT SUM(K) FROM ".. table_name .. get_range_str())
end
# 执行 按范围排序查询 1次 (oltp_order_ranges默认值为 1,所以只会执行1次for循环查询)
# SQL语句为:
# SELECT c FROM table_name WHERE id BETWEEN id_value1 AND id_value2 ORDER BY c
for i=1, oltp_order_ranges do
rs = db_query("SELECT c FROM ".. table_name .. get_range_str() ..
" ORDER BY c")
end
# 执行 DISTINCT 排序查询 1次 (oltp_distinct_ranges默认值为 1,所以只会执行1次for循环查询)
# SQL语句为:
# SELECT DISTINCT c FROM table_name WHERE id BETWEEN id_value1 AND id_value2 ORDER BY c
for i=1, oltp_distinct_ranges do
rs = db_query("SELECT DISTINCT c FROM ".. table_name .. get_range_str() ..
" ORDER BY c")
end
end
end
if not oltp_read_only then # not oltp_read_only为真(oltp_read_only默认为false)
# 执行 更新索引列字段操作 1次 (oltp_index_updates默认值为 1,所以只会执行1次for循环查询)
# SQL语句为:
# UPDATE table_name SET k=k+1 WHERE id=id_value
# 说明:
# k为索引列字段
for i=1, oltp_index_updates do
rs = db_query("UPDATE " .. table_name .. " SET k=k+1 WHERE id=" .. sb_rand(1, oltp_table_size))
end
# 执行 更新非索引列字段操作 1次 (oltp_index_updates默认值为 1,所以只会执行1次for循环查询)
# SQL语句为:
# UPDATE table_name SET c="c_val" WHERE id=id_value
# 说明:
# c_val 长度为119位字符的随机字符串
for i=1, oltp_non_index_updates do
c_val = sb_rand_str("###########-###########-###########-###########-###########-###########-###########-###########-###########-###########") # 长度为119位字符的随机字符串
query = "UPDATE " .. table_name .. " SET c='" .. c_val .. "' WHERE id=" .. sb_rand(1, oltp_table_size)
rs = db_query(query)
if rs then
print(query) # 打印查询结果
end
end
# 执行 删除指定记录操作 1次 (oltp_delete_inserts默认值为 1,所以只会执行1次for循环查询)
# SQL语句为:
# DELETE FROM table_name WHERE id=id_value1
for i=1, oltp_delete_inserts do
i = sb_rand(1, oltp_table_size)
rs = db_query("DELETE FROM " .. table_name .. " WHERE id=" .. i)
c_val = sb_rand_str([[
###########-###########-###########-###########-###########-###########-###########-###########-###########-###########]])
pad_val = sb_rand_str([[
###########-###########-###########-###########-###########]]) # 64位随机字符串
# 执行 插入数据操作 1次
# SQL语句为:
# INSERT INTO table_name(id, K, c, pad)VALUES(id_value, num, field_value1, field_value2 )
# 说明:
# num [1,表记录数] 范围内的随机整数
# field_value1 119位随机字符串
# field_value2 64位随机字符串
rs = db_query("INSERT INTO " .. table_name .. " (id, k, c, pad) VALUES " .. string.format("(%d, %d, '%s', '%s')",i, sb_rand(1, oltp_table_size) , c_val, pad_val))
end
end -- oltp_read_only
if not oltp_skip_trx then
db_query(commit_query)
end
end
sysbench-1.0.20/tests/include/oltp_legacy/common.lua
具体分析参见中文注释
-- Input parameters
-- oltp-tables-count - number of tables to create
-- oltp-secondary - use secondary key instead PRIMARY key for id column
--
--
# 定义插入函数
function create_insert(table_id)
local index_name
local i
local j
local query
if (oltp_secondary) then
index_name = "KEY xid"
else
index_name = "PRIMARY KEY"
end
if (pgsql_variant == 'redshift') then
auto_inc_type = "INTEGER IDENTITY(1,1)"
else
auto_inc_type = "SERIAL"
end
i = table_id
print("Creating table 'sbtest" .. i .. "'...")
# 根据不同驱动,执行对应建表语句,表名格式 sbtestN,其中N从1开始,最大值为oltp_tables_count
if ((db_driver == "mysql") or (db_driver == "attachsql")) then
query = [[
CREATE TABLE sbtest]] .. i .. [[ (
id INTEGER UNSIGNED NOT NULL ]] ..
((oltp_auto_inc and "AUTO_INCREMENT") or "") .. [[,
k INTEGER UNSIGNED DEFAULT '0' NOT NULL,
c CHAR(120) DEFAULT '' NOT NULL,
pad CHAR(60) DEFAULT '' NOT NULL,
]] .. index_name .. [[ (id)
) /*! ENGINE = ]] .. mysql_table_engine ..
" MAX_ROWS = " .. myisam_max_rows .. " */ " ..
(mysql_table_options or "")
elseif (db_driver == "pgsql") then
query = [[
CREATE TABLE sbtest]] .. i .. [[ (
id ]] .. auto_inc_type .. [[ NOT NULL,
k INTEGER DEFAULT '0' NOT NULL,
c CHAR(120) DEFAULT '' NOT NULL,
pad CHAR(60) DEFAULT '' NOT NULL,
]] .. index_name .. [[ (id)
) ]]
elseif (db_driver == "drizzle") then
query = [[
CREATE TABLE sbtest (
id INTEGER NOT NULL ]] .. ((oltp_auto_inc and "AUTO_INCREMENT") or "") .. [[,
k INTEGER DEFAULT '0' NOT NULL,
c CHAR(120) DEFAULT '' NOT NULL,
pad CHAR(60) DEFAULT '' NOT NULL,
]] .. index_name .. [[ (id)
) ]]
else
print("Unknown database driver: " .. db_driver)
return 1
end
db_query(query)
print("Inserting " .. oltp_table_size .. " records into 'sbtest" .. i .. "'")
if (oltp_auto_inc) then
db_bulk_insert_init("INSERT INTO sbtest" .. i .. "(k, c, pad) VALUES")
else
db_bulk_insert_init("INSERT INTO sbtest" .. i .. "(id, k, c, pad) VALUES")
end
local c_val
local pad_val
# for循环,往表插入数据,直到插入oltp_table_size条记录
for j = 1,oltp_table_size do
c_val = sb_rand_str([[
###########-###########-###########-###########-###########-###########-###########-###########-###########-###########]])
pad_val = sb_rand_str([[
###########-###########-###########-###########-###########]])
if (oltp_auto_inc) then
db_bulk_insert_next("(" .. sb_rand(1, oltp_table_size) .. ", '".. c_val .."', '" .. pad_val .. "')")
else
db_bulk_insert_next("("..j.."," .. sb_rand(1, oltp_table_size) .. ",'".. c_val .."', '" .. pad_val .. "' )")
end
end
db_bulk_insert_done()
if oltp_create_secondary then
print("Creating secondary indexes on 'sbtest" .. i .. "'...")
db_query("CREATE INDEX k_" .. i .. " on sbtest" .. i .. "(k)")
end
end
# 定义执行prepare命令时调用的函数
function prepare()
local query
local i
local j
set_vars() # 设置变量
db_connect() # 连接数据库
# for循环插入数据,循环次数为 oltp_tables_count,
for i = 1,oltp_tables_count do
create_insert(i)
end
return 0
end
# 定义执行clean命令时调用的函数
function cleanup()
local i
set_vars() # 调用set_vars函数,设置变量
for i = 1,oltp_tables_count do
print("Dropping table 'sbtest" .. i .. "'...")
db_query("DROP TABLE IF EXISTS sbtest".. i ) # 删除表sbtestN,其中N从1~ oltp_tables_count,即表数量
end
end
function set_vars()
# 以下非本地变量的默认值都为 nil
oltp_table_size = tonumber(oltp_table_size) or 10000 # 单表记录总数 默认值10000
oltp_range_size = tonumber(oltp_range_size) or 100 # between and 范围查询 默认值100
oltp_tables_count = tonumber(oltp_tables_count) or 1 # 表数量 默认值 1
oltp_point_selects = tonumber(oltp_point_selects) or 10 # 按点查询次数(where id=) 默认值 10
oltp_simple_ranges = tonumber(oltp_simple_ranges) or 1 # 简单查询次数 默认值 1
oltp_sum_ranges = tonumber(oltp_sum_ranges) or 1 # sum查询次数 默认值 1
oltp_order_ranges = tonumber(oltp_order_ranges) or 1 # order by排序查询次数 默认值 1
oltp_distinct_ranges = tonumber(oltp_distinct_ranges) or 1 # distinct范围查询次数 默认值 1
oltp_index_updates = tonumber(oltp_index_updates) or 1 # 更新索引列操作次数 默认值 1
oltp_non_index_updates = tonumber(oltp_non_index_updates) or 1 # 更新索引列字段操作次数 默认值 1
oltp_delete_inserts = tonumber(oltp_delete_inserts) or 1 # 执行删除记录操作次数 默认值 1
if (oltp_range_selects == 'off') then
oltp_range_selects = false
else
oltp_range_selects = true
end
if (oltp_auto_inc == 'off') then
oltp_auto_inc = false
else
oltp_auto_inc = true
end
if (oltp_read_only == 'on') then
oltp_read_only = true
else
oltp_read_only = false
end
if (oltp_write_only == 'on') then
oltp_write_only = true
else
oltp_write_only = false
end
if (oltp_read_only and oltp_write_only) then
error("--oltp-read-only and --oltp-write-only are mutually exclusive")
end
if (oltp_skip_trx == 'on') then
oltp_skip_trx = true
else
oltp_skip_trx = false
end
if (oltp_create_secondary == 'off') then
oltp_create_secondary = false
else
oltp_create_secondary = true
end
if (pgsql_variant == 'redshift') then
oltp_create_secondary = false
oltp_delete_inserts = 0
end
end
运行结果说明
混合操作压测结果为例
# cat result.txt
sysbench 1.0.20 (using bundled LuaJIT 2.1.0-beta2)
Running the test with following options:
Number of threads: 300
Initializing random number generator from current time
Initializing worker threads...
Threads started!
SQL statistics:
queries performed:
read: 34507228
write: 9859208
other: 4929604
total: 49296040
transactions: 2464802 (2053.74 per sec.)
queries: 49296040 (41074.74 per sec.)
ignored errors: 0 (0.00 per sec.)
reconnects: 0 (0.00 per sec.)
General statistics:
total time: 1200.1525s
total number of events: 2464802
Latency (ms):
min: 129.86
avg: 146.06
max: 806.70
95th percentile: 155.80
sum: 360014005.42
Threads fairness:
events (avg/stddev): 8216.0067/329.90
execution time (avg/stddev): 1200.0467/0.04
结果项说明:
SQL statistics:
queries performed: 执行的SQL查询:
read: 读请求次数
write: 写请求次数
other: 其它请求次数
total: 总请求次数
transactions: 执行的事务总数 (每秒事务数.)
queries: 执行的查询总次数 (每秒查询次数.)
ignored errors: 忽略错误数 (每秒忽略错误次数.)
reconnects: 数据库重连次数 (每秒重连次数.)
General statistics:
total time: 总运行时间,以秒为单位
total number of events: 总执行事件数
Latency (毫秒为单位):
min: 最小请求响应时间
avg: 平均请求响应时间
max: 最大请求响应时间
95th percentile: 95%的请求响应时间
sum: 总请求响应时间
Threads fairness:
events (avg/stddev): 执行的事件总数(平均每个线程执行的事件总数/标准差)
execution time (avg/stddev): 执行耗时(平均每个线程执行事件耗时/标准差)
参考连接
https://github.com/akopytov/sysbench#general-command-line-options
Sysbench 使用总结的更多相关文章
- sysbench 压力测试
200 ? "200px" : this.width)!important;} --> 介绍 sysbench是一个模块化.跨平台.多线程基准测试工具,主要用于测试不同系统参 ...
- sysbench的安装与使用(with MySQL)
sysbench是一款开源的多线程性能测试工具,可以执行CPU/内存/线程/IO/数据库等方面的性能测试. 项目主页: http://sysbench.sourceforge.net/ 安装文档htt ...
- sysbench 安装遇到的问题
sysbench 作为性能测试工具,提供了很多有用的参数,使用方法网络上一抓一把,这里记录下安装过程中遇到的问题已经解决办法 .tar.gz cd sysbench- ./autogen.sh ./c ...
- sysbench压力测试工具简介和使用(二)
sysbench压力测试工具使用: 2.1 测试数据库服务器的硬件配置信息如下: CPU: 24核心线程数,Intel(R) Xeon(R) CPU E5-2620 0 @ 2.00G ...
- IBM Power PC安装sysbench 执行mysql基准测试 --- sysbench安装
第一步:下载Sysbench http://dev.mysql.com/downloads/benchmarks.html 第二步:解压sysbench 第三步:执行安装步骤 1. ./autogen ...
- sysbench测试工具
sysbench简介 Sysbench是一个模块化的.跨平台.多线程基准测试工具,主要用于评估测试各种不同系统参数下的数据库负载情况.它主要包括以下几种方式的测试:cpu性能,磁盘io性能,线程调度性 ...
- 开源多线程性能测试工具-sysbench
导读 sysbench是一款开源的多线程性能测试工具,可以执行CPU/内存/线程/IO/数据库等方面的性能测试.数据库目前支持MySQL/Oracle/PostgreSQL.本文主要演示Mysql测试 ...
- sysbench压力测试工具简介和使用(一)
sysbench压力测试工具安装和参数介绍 一.sysbench压力测试工具简介: sysbench是一个开源的.模块化的.跨平台的多线程性能测试工具,可以用来进行CPU.内存.磁盘I/O.线程.数据 ...
- sysbench测试服务器性能
sysbench目前已经有0.5的版本,不过最普遍使用的依旧是0.4.12,所以接下来我们会以0.4.12这个版本作为测试 Step1:下载安装sysbench wget http://pkgs.fe ...
- 安装性能测试工具:sysbench和使用apache的ab
一.软件的用途,它主要包括以下几种方式的测试:1.cpu性能2.磁盘io性能3.调度程序性能4.内存分配及传输速度5.POSIX线程性能6.数据库性能(OLTP基准测试) 这个软件为什么找不到官网呢? ...
随机推荐
- 改造 Kubernetes 自定义调度器
原文出处:改造 Kubernetes 自定义调度器 | Jayden's Blog (jaydenchang.top) Overview Kubernetes 默认调度器在调度 Pod 时并不关心特殊 ...
- jquery 给表格添加或删除一行
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- NOIP模拟87(多校20)
前言 题目不难,但是个人感觉小细节有一些,然后有亿点卡常.. 感觉对于笛卡尔树的题目看不出算法,然后代码实现方面细节注意太少,常数有点大. 下次注意吧. T1 集合均值 解题思路 感觉应该是期望题里面 ...
- itest work 开源接口测试&敏捷测试管理平台 9.5.0 GA_u3,优化及修复关键 BUG
(一)itest work 简介 itest work (爱测试) 一站式工作站让测试变得简单.敏捷,"好用.好看,好敏捷" ,是itest wrok 追求的目标.itest w ...
- Cygwin安装及简单说明
1 简介 官方说明:Cygwin is a Linux-like environment for Windows. It consists of a DLL (cygwin1.dll), which ...
- 解决 Https 站点请求 Http 接口服务后报 the content must be served over HTTPS 错误的问题
问题分析 之前将自己所有的 Http 站点全部更新为 Https 站点,但是在请求后台接口服务的时候还是 Http 请求,导致部署之后,直接在控制台报 This request has been bl ...
- SD-WAN中二层组网与三层组网的区别
前言 随着企业网络需求的不断增长和变化,SD-WAN作为一种现代网络技术,为企业提供了更灵活.高效的网络解决方案.在SD-WAN中,二层组网和三层组网是两种常见的部署模型,它们有着各自的特点和适用场景 ...
- JavaScript 中判断 {}是空对象
Javascript 中判断空对象 简介:在 JavaScript 判断字符串是否是一个空字符串 可以 !"" 返回 true 来判断, 要是判断 {} 是否是空对象,也用 !{} ...
- php des加密用java解析不了 改个模式 加个IV php密钥/IV要求都是8位
php des加密用java解析不了 改个模式 加个IV php密钥/IV要求都是8位 php des加密用java解析不了 Wrong IV length: must be 8 bytes lon ...
- Java正则表达式语法及简单示例
import java.util.regex.Matcher; import java.util.regex.Pattern; public class TestMatcher { public st ...