简略

详细

RDMA

RDMA网络配置

硬/软件信息

RDMA驱动安装

验证RDMA连通性

NVMe Initiator 和 target 配置

target 端配置

initiator 端配置

配置成功状态

性能测试

遇到的问题

nvme-cli 用户文档

NVMe over RoCE应用场景

参考文档

nvme ssd和普通ssd区别

bandaoyu@uestc,本文持续更新,连接:http://t.csdn.cn/vaucH

简略

nvme ssd和普通ssd区别

ssd是固态硬盘,普通的ssd配的是SATA口(AHCI协议),nvme ssd配的是PCIe口(nvme传输协议)

  1. HDD 和 SSD 早期, SATA 接口(接口协议:AHCI )满足性能需求,瓶颈在硬盘端,闪存技术的飞速发展,性能瓶颈由下层(硬盘)转移至上层(接口和协议),SSD 急需要更高效的接口和协议,由此,NVMe(Non Volatile Memory Express)横空出世。
  2. RDMA 技术
  3. NVMe over Fabrics
  • SATA/SAS和 PCIe接口对比
AHCI(SATA/SAS) NVMe(PCIe)
背景 为HDD而设计 为SSD而设计
最大队列数量 1 64k
最大队列深度 32 64k
延迟 6ms 2.8ms
通信 与SATA控制器通信 直接与CPU通信

NVMe over Fabrics

NVMe over Fabrics 说白了就是把本地NVMe协议扩展成了网络的NVMe,原先的总线变成了RDMA等高速网络。扩展了原先NVME的协议:相比与普通的 NVMe 命令,NVMe over Fabrics 扩展了 NVMe 标准命令和数据传输方式,比如增加了互联命令,discover,connect、Property Get/Set、Authentication Send/Receive等。可以让 发起(读写)者--initiator 端发现并连接target 端(磁盘或带有磁盘的服务器)

initiator 端,又称为host/client端,initiator 配置前提:RDMA基础环境已搭建。通过NVMe 互联命令探测和连接target 端 NVMe SSD 即可。

nvme over pcie

nvme over tcp

nvme over fabric

nvme over rdma

nvme over roce

https://www.flashmemorysummit.com/English/Collaterals/Proceedings/2017/20170808_FA12_PartB.pdf

详细

原文:NVMe over RoCE 初探 https://zhuanlan.zhihu.com/p/345609031

常见的 SSD 主要分为 SATA 接口(接口协议: AHCI)、 PCIe接口(NVMe 协议Non Volatile Memory Express)。相比于最原始的 ATA 协议,AHCI 有 2 个特点,第 1 个支持热插拔,第 2 个支持 NCQ(Native Command Queueing)技术,NCQ 最大深度为 32,则使用 fio 进行性能测试时,其 iodepth不得超过 32;

在 HDD 和 SSD 早期,AHCI 控制器接口协议和 SATA 硬盘传输接口足够满足系统的性能需求,性能的瓶颈在硬盘端,随着闪存技术的飞速发展,系统的性能瓶颈由下层(硬盘)转移至上层(接口和协议),SSD 急需要更高效的接口和协议。在此背景下,NVMe横空出世。

NVMe 全称为 Non-Volatile Memory Express,是非易失性存储器标准,运行在PCIe 接口之上的协议标准。

协议的层级关系为:NVMe <---事务层 <--- 数据链路层 <--- 物理层,NVMe作为命令层和应用层协议位于最上层,下面 3 层均为 PCIe。

NVMe协议实际是一个应用层的协议,PCIe规范定义了传输层(事务层)、数据链路层和物理层。

NVMe协议通常情况下是跑在PCIe协议栈上的。

pcie是接口,nvme是协议。

笔记本上pcie接口都是M.2的物理形态,但是M.2固态硬盘不一定都用nvme协议,可能是传统sata硬盘所用的ahci协议。

现在已经有走PCIe通道的M.2接口了,就需要确认有没有NVMe协议相关驱动即可,可以进BIOS看一下,有没有NVMe相关的字眼,比如我的电脑,进到BIOS里面后,会看到如下:
链接:https://www.zhihu.com/question/263723989/answer/1203340571

下面将从 SATA和 PCIe 接口对比、 AHCI 和 NVMe速率对比、SSD 外形尺寸 3 方面对比 NVMe 和 AHCI的不同之处。

  • AHCI 和 PCIe 接口对比
AHCI(SATA/SAS) NVMe(PCIe)
背景 为HDD而设计 为SSD而设计
最大队列数量 1 64k
最大队列深度 32 64k
延迟 6ms 2.8ms
通信 与SATA控制器通信 直接与CPU通信
  • SATA 和 PCIe 速率对比

当前我们使用 Intel Purley 平台服务器,即 I/O 接口的速度分别 SATA 3.0 和 PCIe 3.0。预计2021 年中旬 Intel 量产Ice lake Xeon处理器,带来的变化之一是 I/O 由 PCIe 3.0 切换至 PCIe 4.0,服务器平台也将由 Purley 切换至 Whitley。

SATA 1.0 SATA 2.0 SATA 3.0
速率 150 MB/s 300 MB/s 600 MB/s
类型 理论单向速率(GT/s) 传输方式 实际单向速率(Gbps) 单向带宽receive or transmit
PCIe 1.0 2.5 8 bit/10 bit 2 250 MB/s
PCIe 2.0 5 8 bit/10 bit 4 500 MB/s
PCIe 3.0 8 128 bit/ 130 bit 7.87 985 MB/s(约等于 1GB/s)
PCIe 4.0 16 128 bit/ 130 bit 15.75 2016 MB/s(约等于 2GB/s)
  • SSD的外形尺寸

NVMe SSD外形接口形态有:PCIe card slot, M.2, and U.2,其中 U.2专为NVMe设计,有2.5英寸/3.5英寸标准尺寸固态硬盘驱动器。

  • 举个例子,S4510 1.92TB 和 P4610 1.6TB 参数对比
S4510 1.92TB P4610 1.6TB
光刻类型 64-Layer TLC 3D NAND <--
接口类型 SATA 3.0 6Gb/s PCIe 3.1 x4, NVMe
顺序读 (MB/s) 560 3200
顺序写 (MB/s) 510 2080
随机读(IOPS) 97k 643k
随机写(IOPS) 35.5k 199k
闲置功耗(W) 1.1 5
典型功耗(W) 3.2 14
硬件加密 AES 256 bit <--

从上图可以直观看出,P4610 NVMe SSD 性能顺序和随机读/写性能明显优于 S4510 SATA SSD,具体数据为:顺序读约 5.7 倍、顺序写 3.7 倍、随机读约 6.6 倍、随机写约 5.6 倍。

RDMA

RDMA(全称:Remote Direct Memory Access)是一种远程直接内存访问技术,在硬件中实现传输层协议,将内存/消息原语接口暴露至用户空间,通过绕过 CPU 和内核网络协议栈来实现网络的高吞吐和低延迟。如今大规模部署 RDMA 的方式主要有 Infiniband 和 RoCE,前者主要用于高性能领域,后者用于互联网公司数据中心较多,本文的实验环境使用 RoCE。无论哪一种 RDMA 实现方式,都向上提供了统一的操作接口,即 RDMA verbs。

实验设备拓扑图:

RDMA网络配置

硬/软件信息

- 硬件
服务器型号:联想SR650
CPU:Xeon Silver 4214R*2 @ 2.40GHz
内存:DDR4 2933MHz 32G*12
硬盘:Intel P4610 U.2/2.5寸 NVMe SSD 1.6T*4(数据盘),2.5寸 SATA SSD 240G*2(系统盘)
网卡:Mellanox CX4-2port 25Gb/s*2- 软件
OS:Debian 10.3
Kernel: 4.19.0-8-amd64 x86_64
nvme-cli版本:1.13.23.g274a
MCX4121A固件版本:14.28.1002 (LNV2420110034)
mlx5_core版本:5.2-1.0.4

RDMA驱动安装

驱动选择为:MLNX_OFED_LINUX-5.2-1.0.4.0-debian10.3-x86_64.tgz

MLNX_OFED driver

配置过程如下:

# 下载链接
https://www.mellanox.com/products/infiniband-drivers/linux/mlnx_ofed# 解压
tar xvf MLNX_OFED_LINUX-5.2-1.0.4.0-debian10.3-x86_64.tgz# 安装,增加参数 kernel 和 nvmf 支持
cd MLNX_OFED_LINUX-5.2-1.0.4.0-debian10.3-x86_64
./mlnxofedinstall  --add-kernel-support --with-nvmf# 安装日志如下:
Note: This program will create MLNX_OFED_LINUX TGZ for debian10.3 under /tmp/MLNX_OFED_LINUX-5.2-1.0.4.0-4.19.0-8-amd64 directory.
See log file /tmp/MLNX_OFED_LINUX-5.2-1.0.4.0-4.19.0-8-amd64/mlnx_iso.25161_logs/mlnx_ofed_iso.25161.log
....
Installation passed successfully
To load the new driver, run:
/etc/init.d/openibd restart
Note: In order to load the new nvme-rdma and nvmet-rdma modules, the nvme module must be reloaded.

验证RDMA连通性

背景:两台节点ip分别为:192.168.13.146, 192.168.13.147,使用 ib_send_bw 命令测试(需要指定 ib 设备名,本例中配置 mlx5_3 设备通信)。

# 开启服务端
ib_send_bw --ib-dev=mlx5_3************************************
* Waiting for client to connect... *
************************************---------------------------------------------------------------------------------------#bytes     #iterations    BW peak[MB/sec]    BW average[MB/sec]   MsgRate[Mpps]65536      1000             0.00               2761.97        0.044192
---------------------------------------------------------------------------------------# 开启客户端
ib_send_bw --ib-dev=mlx5_3 192.168.13.147
---------------------------------------------------------------------------------------#bytes     #iterations    BW peak[MB/sec]    BW average[MB/sec]   MsgRate[Mpps]65536      1000             2757.59            2757.57        0.044121
---------------------------------------------------------------------------------------

NVMe Initiator 和 target 配置

target端即磁盘阵列或其他装有磁盘的主机。通过iscsitarget工具将磁盘空间映射到网络上,initiator端就可以寻找发现并使用该磁盘。

Initiator(发起者) 和 target 连接方式如下图所示,左侧为initiator,其右为target。

在NVMe协议中,NVMe 控制器是与 initiator 进行沟通的实体。

通过确定 PCIe port 、NVMe controller 和NVMe namespace,initiator 端可以通过 discover 和 connect 互联命令发现 target 端 NVMe namespace 并将其连接至本地。

引用至《深入浅出SSD》

NVMe over Fabrics 协议定义了使用各种事务层协议来实现 NVMe 功能,其中包括 RDMA、FibreChannel等。

相比与普通的 NVMe 命令,NVMe over Fabrics 扩展了 NVMe 标准命令和数据传输方式,比如增加了互联命令,discover,connect、Property Get/Set、Authentication Send/Receive等。connect 命令携带 Host NQN、NVM Subsystem NQN 、PCIe port 和 Host identifier 信息可以连接到 target 端 NVMe 控制器。

本文中 NVMe over RoCE 调用关系如下图所示,内核 nvme_rdma 模块相当于胶水层,连接 rdma stack 和 nvme core接口,即 NVMe 队列接口可以对接 RDMA 队列接口,进而调用下层 rdma stack 中 verbs 传输接口。

NVMe over RoCE 调用关系

target 端配置

# NVMe target configuration
# Assuming the following:
# IP is 192.168.13.147/24
# link is up
# using ib device eth2
# modprobe nvme and rdma modulemodprobe nvmet
modprobe nvmet-rdma
modprobe nvme-rdma# 1、config nvme subsystem
mkdir /sys/kernel/config/nvmet/subsystems/nvme-subsystem-name
cd /sys/kernel/config/nvmet/subsystems/nvme-subsystem-name# 2、allow any host to be connected to this target
echo 1 > attr_allow_any_host# 3、create a namesapce,example: nsid=10
mkdir namespaces/10
cd namespaces/10# 4、set the path to the NVMe device
echo -n /dev/nvme0n1> device_path
echo 1 > enable# 5、create the following dir with an NVMe port
mkdir /sys/kernel/config/nvmet/ports/1
cd /sys/kernel/config/nvmet/ports/1# 6、set ip address to traddr
echo "192.168.13.147" > addr_traddr# 7、set rdma as a transport type,addr_trsvcid is unique.
echo rdma > addr_trtype
echo 4420 > addr_trsvcid# 8、set ipv4 as the Address family
echo ipv4 > addr_adrfam# 9、create a soft link
ln -s /sys/kernel/config/nvmet/subsystems/nvme-subsystem-name /sys/kernel/config/nvmet/ports/1/subsystems/nvme-subsystem-name# 10、Check dmesg to make sure that the NVMe target is listening on the port
dmesg -T| grep "enabling port"
[369910.403503] nvmet_rdma: enabling port 1 (192.168.13.147:4420)

initiator 端配置

initiator 端,又称为host/client端,initiator 配置前提:RDMA基础环境已搭建。通过NVMe 互联命令探测和连接target 端 NVMe SSD 即可。

# 探测 192.168.13.147 机器上 4420 端口 nvme ssd
nvme discover -t rdma -q nvme-subsystem-name -a 192.168.13.147 -s 4420# 连接 192.168.13.147 4420 端口 nvme ssd
nvme connect -t rdma -q nvme-subsystem-name -n nvme-subsystem-name  -a 192.168.13.147 -s 4420# 与target 端 nvme ssd 断开连接
nvme disconnect -n nvme-subsystem-name

配置成功状态

配置前 initiator 和 target 各有 4块 NVMe SSD,使用上述 initator 和 target 配置方法,将 target 上 4 块 NVMe SSD 挂载至 initator,配置后的现象是 initiator 会显示 8 块 NVMe SSD,target 仍然是 4 块。经验证: target 不可以操作被挂载至 initiator 端的 NVMe SSD。配置状态如下图所示:

配置前

配置后

性能测试

下面对比测试本地 NVMe SSD 和 NVMe over RoCE SSD之间的顺序/随机性能,单盘+ext4文件系统,结论是:通过性能数据表明,NVMe over RoCE方法顺序读性能下降约 14%,随机写和随机读性能分别下降约 6% 和 2%,顺序写性能无影响。

I/O类型 Local NVMe SSD NVMe over RoCE SSD
顺序写 (MB/s) 2035 2031
顺序读 (MB/s) 3374 2889
随机写 (IOPS) 51.6k 48.4k
随机读 (IOPS) 571k 557k

注:NVMe 裸盘测试性能正常,挂载文件系统后性能急剧下降,后续会在文件系统层面研究如何调优。

测试方法:将 NVMe SSD 全盘顺序写2遍后,使用 fio 测试工具

# 顺序写:
fio --iodepth=128 --numjobs=4 --size=1TB --norandommap --readwrite=write --bs=128k  --filename=/partition1/write.txt --runtime=1200 --time_based --ioengine=libaio --direct=1 --group_reporting --name=write# 顺序读:
fio --iodepth=128 --numjobs=4 --size=1TB --norandommap --readwrite=read --bs=128k  --filename=/partition1/write.txt --runtime=120 --time_based --ioengine=libaio --direct=1 --group_reporting --name=read# 随机写:
fio --iodepth=128 --numjobs=4 --size=1TB --norandommap --readwrite=randwrite --bs=4k --runtime=1200 --time_based --filename=/partition1/randwrite.txt --ioengine=libaio --direct=1 --group_reporting --name=rand_write# 随机读:
fio --iodepth=128 --numjobs=4 --size=1TB --norandommap --readwrite=randread --bs=4k --runtime=300 --time_based --filename=/partition1/randwrite.txt --ioengine=libaio --direct=1 --group_reporting --name=rand_read

target 中同 1 个子系统(例如:nvme-subsystem-name)可供多个 initiator 连接。target 子系统关联的硬盘为 /dev/nvme0n1,此时 initiator1 和 initiator2 同时连接 target nvme-subsystem-name,挂载分区后的效果是: initiator1 和 initiator2 均可对 /dev/nvme0n1分区正常读写,但不会同步,仅有等待 disconnect ,再次 connect 后才会进行数据同步。

遇到的问题

问题1:nvmet 模块无法加载的问题

# 导入nvmet内核模块
modprobe nvmet
dmesg | tail
[87679.872351] device-mapper: ioctl: 4.39.0-ioctl (2018-04-03) initialised: dm-devel@redhat.com
[87776.766628] nvmet: Unknown symbol nvme_find_pdev_from_bdev (err -2)
[87850.518208] nvmet: Unknown symbol nvme_find_pdev_from_bdev (err -2)
[88090.703738] nvmet: Unknown symbol nvme_find_pdev_from_bdev (err -2)
[88093.708573] nvmet: Unknown symbol nvme_find_pdev_from_bdev (err -2)# 解决方法:删除 nvme 模块后,重新加载 nvme 即可
rmmod nvme
modprobe nvme nvmet

问题2:在 initiation 端执行 nvme discover 命令时,遇到 Failed to write to /dev/nvme-fabrics: Invalid argument报错

# 通过 dmesg 发现如下日志,说明 hostnqn 参数没有指定。
[Sat Jan  9 23:00:19 2021] nvme_fabrics: unknown parameter or missing value 'hostnqn=' in ctrl creation request# 解决方法
nvme discover 添加 -q nvme-subsystem-name 参数

nvme-cli 用户文档

nvme 是 NVMe SSD和 NVMe oF 存储命令行管理工具,nvme安装包为 nvme-cli,它依赖Linux内核 IOCTL 系统调用,该调用连接用户层和NVMe驱动层,当用户执行 nvme commands 时,IOCTL 会将命令参数传递至 NVMe common 层,该层代码解析命令并执行命令,将命令封装至 capsule ,进而传递至 NVMe Submission 队列,Controller 处理后将 capsule 传递至 NVMe Completion 队列,应用从 Completion 队列取出 capsule,完成一次通信。

nvme 安装和常用命令

# 安装nvme-cli
apt-get install pkg-config uuid-runtime -y
git clone https://github.com/linux-nvme/nvme-cli.git
cd nvme-cli && make && make install# nvme 命令使用方式:
usage: nvme <command> [<device>] [<args>]
# 其中 device 要么是 NVMe 字符设备,例如 /dev/nvme0,要么是 NVMe 块设备,例如 /dev/nvm0n1。# 查看所有nvme块设备
nvme list# 查看命名空间结构
nvme id-ns /dev/nvme1n1# 创建命名空间,分为3个步骤:create-ns、attach-ns 和 reset;
# create-ns 命令中 -s -c 参数分别对应nsze、ncap,可以参考 nvme id-ns /dev/nvme1n1 输出结果
nvme create-ns -s 0xba4d4ab0 -c 0xba4d4ab0 -f 0 -d 0 -m 0 /dev/nvme0# 将命令空间1关联至控制器0
nvme attach-ns /dev/nvme0 -c 0 -n 1# 重置 /dev/nvme0,使得创建的命名空间以块设备形式显示在OS中
nvme reset /dev/nvme0# 查看 /dev/nvme0 拥有的命名空间
nvme list-ns /dev/nvme0# 删除 /dev/nvme0 第1个命令空间
nvme delete-ns /dev/nvme0 -n 1# 查看 /dev/nvme0 拥有的控制器
nvme list-ctrl /dev/nvme0

查看 NVMe SSD smartctl 信息

# 使用 smartctl 命令查看 nvme 盘信息,例如,device_name 为 /dev/nvme0n1
apt-get install smartmontools -y
smartctl -a -d nvme $device_name

NVMe over RoCE应用场景

1、刀片仅有 2 个盘位,可以通过 RoCE 连接 NVMe SSD 存储池。

当刀片存储容量不够用时,可以使用 RoCE 连接 NVMe SSD存储池。

2、读写分离场景,可以使用 NVMe over RDMA 搭建 NFS。

target 上 NVMe SSD 可以划分分区,格式化文件系统,写入数据。
target NVMe SSD以块设备形式挂载至 initiator后,仅需 mount 操作即可使用。前提是仅有读操作,各 initator 往同1块 NVMe SSD 上写数据时,各 initator 并不会同步数据。

3、NVMe SSD创建多个命名空间,通过 RoCE 供多个租户使用。

公有云/私有云场景,如下图所示,将 1 块大容量 NVMe SSD 划分为多个命名空间,虚拟化后提供给多个租户,可以充分发挥 NVMe SSD 的性能。 

创建多个命名空间

参考文档

1、Kingston, Understanding SSD Technology: NVMe, SATA, M.2

2、nvme-command user guide

3、what is a namespace ?

4、NVMe over RoCE Storage Fabrics for noobs

5、HowTo Configure NVMe over Fabrics

6、深入浅出SSD

nvme ssd和普通ssd区别

ssd是固态硬盘,普通的ssd配的是SATA口(AHCI协议),nvme ssd配的是PCIe口(nvme传输协议)

NVME是硬盘新的传输标准,下一代协议,比现代的AHCI传输协议更加高级。

NVME的优势有以下几点:

1.更低的延时。NVME精简了调用方式,执行命令时不需要读取寄存器,而AHCI每条命令则需要读取4次寄存器,一共会消耗8000次CPU循环,从而造成2.5微秒的延迟。

2.更高的传输性能。性能不错的SATA接口的SSD,在队列深度上都可以达到32,这也是AHCI所能做到的极限。更高端的PCIe SSD其队列深度可达128,甚至是256才能发挥出最高的IOPS性能。而NVME标准下,最大的队列深度可达64000。此外,NVME的队列数量也从AHCI的1提高到了64000。

3.更低的能耗控制。升级版的NVME在能耗方面肯定会进行优化处理,能耗降低了有助于设备的节能使用,同时也会减少控制元件的工作负荷。NVME加入了自动功耗状态切换和动态能耗管理功能,SSD在闲置的时候可以快速的控制在极低的水平,从而降低整体的能耗。

【协议】NVMe over RoCE 初探 SATA接口(AHCI协议)、PCIe 接口(NVMe 协议)相关推荐

  1. 【协议】NVMe over RoCE 初探 SATA、PCIe 接口和AHCI、NVMe 协议

    原文:NVMe over RoCE 初探 - 知乎 常见的 SSD 主要分为 SATA和 PCIe 接口,其接口协议对应着 AHCI.NVMe 协议.相比于最原始的 ATA 协议,AHCI 有 2 个 ...

  2. PCI、PCIE、NVME;ATA、SATA、AHCI及M.2接口简单辨别

    PCIe总线概述 随着现代处理器技术的发展,在互连领域中,使用高速差分总线替代并行总线是大势所趋.与单端并行信号相比,高速差分信号可以使用更高的时钟频率,从而使用更少的信号线,完成之前需要许多单端并行 ...

  3. 笔记本html接口是输入还是输出,笔记本mSATA接口和mini PCI-E接口之间的区别解析图...

    要说mSATA和mini PCI-E并非什么新接口,只是之前大多集成在系统产品中,很少接触到.而近期随着无线及固态硬盘的出现,引起大家关注. mSATA接口 作用:连接固态硬盘 mSATA接口在标配固 ...

  4. SSD中,SATA、m2、PCIE和NVME各有什么意义

  5. 基于PCIe的NVMe协议在FPGA中实现方法

    NVMe协议是工作在PCIE的最上层协议层的,故需要先搞清楚PCIE.本文基于Xilinx的UltraScale+,开发工具为Vivado2021.2.学习中以spec为主,其它资料辅助参考(重点介绍 ...

  6. SSD,PCI-E,NVMe,M.2分类详解

    SSD,PCI-E,NVMe,M.2分类详解 首先说一下目前固态硬盘常用的两个接口(与主板相连的接口形状)SATA3和M.2. (1)采用SATA3接口(目前机械硬盘采用的接口方式)的固态硬盘,在传输 ...

  7. AHCI协议、NVME协议、SATA总线、PCIe总线、SATA接口、PCIe接口、M.2接口

    内容来自 硬件茶谈 硬盘的SATA M.2 NGFF NVME是什么意思,详解硬盘的总线协议与接口 侵删. 一.协议 AHCI和NVME协议民用很多,而SCSI协议大多用在服务器上. 二.总线   总 ...

  8. SATA M.2 NGFF PCIE AHCI NVME SSD固态硬盘的接口、总线和协议区分

    总线.协议 说接口之前先说总线,民用产品的硬盘总线多为 SATA 和 PCIe. SATA 总线只能使用 AHCI 协议.NVME 对比 AHCI 的优势在于 低延时.低功耗,更适合固态硬盘. PCI ...

  9. NVMe、AHCI、PCIe、SATA、NGFF接口、协议小结

    这些接口.协议经常出现,搞的自己晕头转向,所以特意找资料总结一下,本文不涉及详细的接口标准及协议内容.在遇到这些名称的时候,能帮助区分它们的不同就好. 首先有三个总的分类,即 通讯协议.物理接口标准( ...

最新文章

  1. 北京市常用和便民电话
  2. Magicodes.IE之花式导出
  3. emacs .emacs_谁在乎Emacs?
  4. 【clickhouse】clickhouse 表引擎 之 AggregatingMergeTree
  5. 女朋友:你能给我讲讲单例模式吗?
  6. Linux下使用nohup部署java 后台程序
  7. 模糊局部信息c均值聚类算法(flicm)
  8. 使用PEG估值法简单选股(1)
  9. 结绳计数——最原始的备忘录
  10. php中strpos什么意思,PHP使用strpos()和strrpos()定位文本
  11. 【阿里云原生架构】二、云原生架构的原则和模式
  12. IDEA 中使用 Big Data Tools 连接大数据组件
  13. 线性代数之向量间线性关系
  14. 【胡搞的不能AC的题解,暴力搜索一发博弈问题】1995 三子棋 - 51Nod
  15. Mind the GAP: A Balanced Corpus of Gendered Ambiguous Pronouns--论文笔记
  16. “下周集中办公,你该如何防护?”一位资深HR的10个建议
  17. 汉诺塔的递归算法与解析
  18. Ant Design Vue LocaleProvider国际化组件zh_CN中文配置
  19. keka 1.2.7 中文版 macOS 压缩文件管理器
  20. AI大潮之下,“造物主”码农也要失业了?【智库2861】

热门文章

  1. 5板斧---分析短信、彩信收发异常
  2. elasticsearch 修改已存在的filed值 和 新增filed
  3. 考PMP真的有用吗?
  4. 基于html+css的购物网站前端页面【折扣社】前端网站
  5. python中shelf_在python 3中使用python 2 shelf
  6. WIFI 认证加密模式介绍 理解无线安全
  7. python判断是否构成三角形并计算面积
  8. 微信对接会员管理系统搭建体系
  9. Elasticsearch的路由(Routing)特性
  10. 搭建网站要多少钱?自助建站制作网站要花多少钱?