jdk14

jdk14 instanceof 模式匹配 JDK 14的新特性:instanceof模式匹配 JDK14在2020年的3月正式发布了。可惜的是正式特性只包含了最新的Switch表达式,而Records,patterns,text blocks仍然是预览特性。 本文要讲的就是JDK14的一个预览特性instanceof的pattern matching。 也就是说在instanceof中可以使用模式匹配了。 怎么理解呢? 我们先举个历史版本中使用instanceof的例子。 假如我们是动物园的管理员,动物园里面有Girraffe和Hippo两种动物。 @Data public class Girraffe { private String name; } @Data public class Hippo { private String name; } public class TestZoo { private final static Logger logger = LoggerFactory.getLogger(TestZoo.class); public static void main(String[] args) { Girraffe g = new Girraffe(); g.setName("gg"); testZooOld(g); testZooNew(g); Cat c = new Cat(); c.setName("pipi"); testZooOld(c); testZooNew(c); } public static void testZooOld(Object animal) { if (animal instanceof Girraffe) { Girraffe girraffe = (Girraffe) animal; logger.info("girraffe name is {}", girraffe.getName()); } else if (animal instanceof Hippo) { Hippo hippo = (Hippo) animal; logger.info("hippo name is {}", hippo.getName()); }else{ logger.info("test zoo old, 对不起,该动物不是地球上的生物!"); } } public static void testZooNew(Object animal){ if(animal instanceof Girraffe girraffe){ logger.info("name is {}",girraffe.getName()); }else if(animal instanceof Hippo hippo){ logger.info("name is {}",hippo.getName()); }else{ logger.info("test zoo new, 对不起,该动物不是地球上的生物!"); } } } ...

1 min · 143 words · -

jdk16

jdk16 新语言特性 JEP 394,适用于 instanceof 的模式匹配 模式匹配 (Pattern Matching) 最早在 Java 14 中作为预览特性引入,在 Java 15 中还是预览特性。模式匹配通过对 instacneof 运算符进行模式匹配来增强 Java 语言。 模式匹配使程序中的通用逻辑 (即从对象中有条件地提取组件) 得以更简洁、更安全地表示。 wiloon.com/jdk14 JEP 395,记录 记录 (Records) 在 Java 14 和 Java 15 中作为预览特性引入。它提供了一种紧凑的语法来声明类,这些类是浅层不可变数据的透明持有者。这将大大简化这些类,并提高代码的可读性和可维护性。

1 min · 35 words · -

JTAG

“JTAG” JTAG JTAG (Joint Test Action Group,联合测试行动小组) 是一种国际标准测试协议,主要用于芯片内部测试。现在多数的高级器件都支持JTAG协议,如ARM、DSP、FPGA器件等。标准的JTAG接口是4线: TMS、 TCK、TDI、TDO,分别为模式选择、时钟、数据输入和数据输出线。 JTAG最初是用来对芯片进行测试的,基本原理是在器件内部定义一个TAP (Test Access Port,测试访问口) ,通过专用的JTAG测试工具对进行内部节点进行测试。JTAG测试允许多个器件通过JTAG接口串联在一起,形成一个JTAG链,能实现对各个器件分别测试。现在,JTAG接口还常用于实现在线编程 (ISP,In-System Programmable) ,对FLASH等器件进行编程。 JTAG编程方式是在线编程,传统生产流程中先对芯片进行预编程实现再装到板上因此而改变,简化的流程为先固定器件到电路板上,再用JTAG编程,从而大大加快工程进度。JTAG接口可对PSD芯片内部的所有部件进行编程。 简单地说,JTAG的工作原理可以归结为: 在器件内部定义一个TAP (TestAccessPort,测试访问口) ,通过专用的JTAG测试工具对内部节点进行测试和调试。 边界扫描 边界扫描 (Boundary-Scan) 即在芯片的每个输入输出管脚上都增加一个移位寄存器单元 (Boundary-Scan Register Cell) ,因为这些移位寄存器单元分布在芯片的边界上,所以被称为边界扫描寄存器。在JTAG 调试中,边界扫描是一个很重要的概念,当需要调试芯片时,这些寄存器将芯片与外围电路隔离,实现对芯片输入输出信号的观察和控制: 对于输入管脚,可以通过与之相连的边界扫描寄存器单元把数据加载到该管脚中;对于输出管脚,可以通过与之相连的边界扫描寄存器"捕获" (CAPTURE) 该管脚上的输出信号;正常运行状态下,这些边界扫描寄存器单元对芯片是透明的,所以正常的运行不会受到影响。另外,芯片输入输出管脚上的边界扫描 (移位) 寄存器单元可以相互连接起来,在芯片的周围形成一个边界扫描链 (Boundary-Scan Chain) ,它可以串行的输入和输出,通过相应的时钟信号和控制信号,实现对处在调试状态下的芯片的输入和输出状态的观察和控制。 在CPU外围,处理器内部包含了JTAG的硬件实现,并且向外界提供接口,也就是上面所说的TMS、TCK、TDI、TDO四个引脚。 这里的CPU: 是指运算处理单元,只包含了内部寄存器以及运算单元等基本部件。 这里的处理器: 是指CPU 扩展芯片,不是SoC。 说明: 更多关于CPU和处理器之间的关系,请参考文章《CPU MPU MCU SOC SOPC关系及区别》。 JTAG原理 边界扫描链 JTAG如何用于芯片测试呢?其中用到的最主要部件就是边界扫描链。命名为边界扫描链,是由于它位置处于处理器的边界上。 我们知道CPU是通过引脚与外围交流的,所有的数据都会通过引脚输入或者输出,而JTAG就是通过监控引脚的信号达到芯片测试的目的。而边界扫描链就是在引脚上的一个部件。如下图: 边界扫描链位置 边界扫描链位置 通过边界扫描链,当有信号输入的时候,边界扫描链就能获取信号,当CPU要输出信号的时候,边界扫描链也能获取要输出的信号。另外,也可以通过边界扫描链来直接向外部输出信号。 无论是信号的抓取还是输出,都需要有接口来保存这些信号,TDI 跟 TDO 就是做这样一些工作的。如图: JTAG TDI TDO示意图 JTAG TDI TDO示意图 本来边界扫描链保存着引脚上的信号,当通过TDI引脚输入我们自己的信号的时候,会发生沿上面红线方向的移位操作, ...

1 min · 142 words · -

jvm

jvm JVM是Java Virtual Machine (Java虚拟机)的缩写 常用jvm 目前市面上普遍使用的JVM大致有三种 Sun公司的HotSpot——绝大多数java开发者都用的是这款,绝对的主力 Oracle公司的JRockit——这款主要用于金融和军事 IBM公司的J9 VM——这款是IBM硬件绑定的,用户也很少 IBM 开源了它开发的 J9 Java 虚拟机 (JVM),并将其贡献给了 Eclipse 基金会,重命名为 Eclipse OpenJ9。J9 是一个高性能可伸缩的 Java 虚拟机,是许多 IBM 企业级软件产品的核心,OpenJ9 可作为 Hotspot 的替代者用于 OpenJDK Java虚拟机四大组成部分 执行引擎(解释器和即时编译器) 类加载器 运行时数据区 垃圾回收器 执行引擎 Execution Engine Java虚拟机的执行引擎主要是用来执行Java字节码。JVM的执行引擎执行字节码通过两种解释器执行的:字节码解释器与模板解释器,运行过程中,可能会触发即时编译 (JIT),涉及到几种即时编译器,下面分别进行介绍。 执行引擎是Java虛拟机核心的组成部分之一。 虚拟机是一个相对于“物理机”的概念,这两种机器都有代码执行能力,其区别是物理机的执行引擎是直接建立在处理器、缓存、指令集和操作系统层面上的,而虚拟机的执行引擎则是由软件自行实现的,因此可以不受物理条件制约地定制指令集与执行引擎的结构体系,能够执行那些不被硬件直接支持的指令集格式。 JVM的主要任务是负责装载字节码到其内部,但字节码并不能够直接运行在操作系统之上,因为字节码指令并非等价于本地机器指令,它内部包含的仅仅只是一些能够被JVM所识别的字节码指令、符号表,以及其他辅助信息。 如果想要让一个Java程序运行起来,执行引擎(Execution Engine)的任务就是将字节码指令解释/编译为对应平台上的本地机器指令才可以。简单来说,JVM中的执行引擎充当了将高级语言翻译为机器语言的译者。 解释器分类 在Java的发展历史里,一共有两套解释执行器,即古老的字节码解释器、现在普遍使用的模板解释器。 字节码解释器:在执行时通过纯软件代码模拟字节码的执行,效率非常低下。 模板解释器:将每一条字节码和一个模板函数相关联,模板函数中直接产生这条字节码执行时的本地机器代码,从而很大程度上提高了解释器的性能。 在HotSpot VM中,解释器主要由Interpreter模块和Code模块构成。 Interpreter模块:实现了解释器的核心功能 Code模块:用于管理HotSpotVM在运行时生成的本地机器指令 JIT编译器(Just In Time Compiler) 就是虚拟机将源代码直接编译成和本地机器平台相关的汇编语言,通过汇编生成机器代码。 现代虚拟机为了提高执行效率,会使用即时编译技术将方法编译成本地机器代码后再执行 Hotspot JIT编译器生成的是汇编代码,保存在方法区的JIT缓存区 本地机器代码不等于机器码,不同平台虚拟机翻译成本地的能识别的指令集,或者说是汇编语言。指令集由不同的架构构成,如:x86指令集 为什么还需要解释器 有些开发人员会感觉到诧异,既然HotSpot VM中已经内置JIT编译器了,那么为什么还需要再使用解释器来“拖累”程序的执行性能呢?比如JRockit VM内部就不包含解释器,字节码全部都依靠即时编译器编译后执行。 首先明确: 当程序启动后,解释器可以马上发挥作用,省去编译的时间,立即执行。编译器要想发挥作用,把代码编译成本地代码,需要一定的执行时间。但编译为本地代码后,执行效率高。 所以: 尽管JRockitVM中程序的执行性能会非常高效,但程序在启动时必然需要花费更长的时间来进行编译。对于服务端应用来说,启动时间并非是关注重点,但对于那些看中启动时间的应用场景而言,或许就需要采用解释器与即时编译器并存的架构来换取一一个平衡点。在此模式下,当Java虛拟器启动时,解释器可以首先发挥作用,而不必等待即时编译器全 部编译完成后再执行,这样可以省去许多不必要的编译时间。随着时间的推移,编译器发挥作用,把越来越多的代码编译成本地代码,获得更高的执行效率。同时,解释执行在编译器进行激进优化不成立的时候,作为编译器的“逃生门” 当虚拟机启动的时候,解释器可以首先发挥作用,而不必等待即时编译器全部编译完成再执行,这样可以省去许多不必要的编译时间。并且随着程序运行时间的推移,即时编译器逐渐发挥作用,根据热点探测功能,将有价值的字节码编译为汇编语言,以换取更高的程序执行效率。 ...

7 min · 1412 words · -

jwt spring security

“jwt spring security” POST http://localhost:9333/api/users/sign-up content-type: application/json {“userName”:“123456”,“fullName”:“shuangkou”,“password”:“123456”} https://example.com/comments/1 POST https://example.com/comments HTTP/1.1 content-type: application/json { “name”: “sample”, “time”: “Wed, 21 Oct 2015 18:27:50 GMT” } https://www.jianshu.com/p/0c54788c94f3 https://github.com/Snailclimb/spring-security-jwt-guide

1 min · 27 words · -

Legendary

“Legendary” https://github.com/derrod/legendary https://github.com/doitsujin/dxvk/wiki/Common-issues legendary auth legendary list-games legendary launch Kinglet legendary list-installed –check-updates legendary launch Kinglet

1 min · 16 words · -

lombok

“lombok” lombok注解介绍 lombok注解文档 lombok官网下载 lombok是一个可以帮助我们简化java代码编写的工具类,尤其是简化javabean的编写,即通过采用注解的方式,消除代码中的构造方法,getter/setter等代码,使我们写的类更加简洁,当然,这带来的副作用就是不易阅读…不过,还是能看得懂吧,废话不多说,先看一下lombok支持的一些常见的注解。 @NonNull @Cleanup @Getter/@Setter @ToString @EqualsAndHashCode @NoArgsConstructor/@RequiredArgsConstructor /@AllArgsConstructor @Data @Value @SneakyThrows @Synchronized @Log

1 min · 17 words · -

Mustache语法

“Mustache语法” Mustache是一个logic-less (轻逻辑) 模板解析引擎, 它是为了使用户界面与业务数据 (内容) 分离而产生的, 它可以生成特定格式的文档,通常是标准的HTML文档。 比如小程序的wxml中的代码 {{userInfo.nickName}},这里的{{ }}就是Mustache的语法。 Mustache的模板语法很简单,就那么几个 {{keyName}} {{{keyName}}} {{#keyName}} {{/keyName}} {{^keyName}} {{/keyName}} {{.}} {{!comments}} {{>partials}}

1 min · 21 words · -

MySQL 显示行号,以及分组排序

“MySQL 显示行号,以及分组排序” CREATE TABLE my_tb ( id int(11) NOT NULL AUTO_INCREMENT, parent_code varchar(255) DEFAULT NULL, code varchar(255) DEFAULT NULL, PRIMARY KEY (id) ) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8; INSERT INTO `my_tb` ( `parent_code`, `code`) VALUES ('01', '001'); INSERT INTO `my_tb` ( `parent_code`, `code`) VALUES ('01', '002'); INSERT INTO `my_tb` ( `parent_code`, `code`) VALUES ('02', '001'); INSERT INTO `my_tb` ( `parent_code`, `code`) VALUES ('01', '003'); INSERT INTO `my_tb` ( `parent_code`, `code`) VALUES ('02', '002'); INSERT INTO `my_tb` ( `parent_code`, `code`) VALUES ('03', '001'); INSERT INTO `my_tb` ( `parent_code`, `code`) VALUES ('04', '001'); -- 生成 行号 select @r:=@r+1 as row_num , a.* from my_tb a ,(select @r:=0) b -- 生成 分组排序号 select @group_row:=CASE when @parent_code=a.parent_code then @group_row+1 else 1 end as groupRow, @parent_code:=a.parent_code as parent_code, a.code from my_tb a ,( select @group_row:=1, @parent_code:='') as b ORDER BY a.parent_code , a.code 查询结果 "groupRow" "parent_code" "code" "1" "01" "001" "2" "01" "002" "3" "01" "003" "1" "02" "001" "2" "02" "002" "1" "03" "001" "1" "04" "001" https://blog.csdn.net/kxjrzyk/article/details/58588000

1 min · 163 words · -

MySQL自定义变量

“MySQL自定义变量” MySQL自定义变量的使用 用户自定义变量是一个容易被遗忘的MySQL特性,但是如果能用的好,发挥其潜力,在某些场景可以写出非常高效的查询语句。在查询中混合使用过程化和关系化逻辑的时候,自定义变量可能会非常有用。单纯的关系查询将所有的东西都当成无序的数据集合,并且一次性操作它们。MySQL则采用了更加程序化的处理方式。MySQL的这种方式有它的弱点,但如果能够熟练地掌握,则会发现其强大之处,而用户自定义变量也可以给这种方式带来很大的帮助 用户自定义变量是一个用来存储内容的临时容器,在连接MySQL的整个过程中都存在,可以使用下面的SET和SELECT语句来定义它们: SET @ONE := 1; SELECT @ONE; MySQL> SET @min_actor := (SELECT MIN(actor_id) FROM sakila.actor); MySQL> SET @last_week := CURRENT_DATE - INTERVAL 1 WEEK; 然后可以在任何可以使用表达式的地方使用这些自定义变量: SELECT … WHERE col <= @last_week; 在了解自定义变量的强大之前,我们先来看看它自身的一些属性和限制,看看在哪些场景下我们不能使用用户自定义变量: 使用自定义变量的查询,无法使用查询缓存 不能再使用常量或者标识符的地方使用自定义变量,例如表名、列名和LIMIT子句中。 用户自定义变量的生命周期是在一个连接中有效,所以不能用它们来做连接间的通信。 如果使用连接池或者持久化连接,自定义变量可能让看起来毫无关系的代码发生交互。 自定义变量的类型是一个动态类型。 MySQL优化器在某些场景下可能会将这些变量优化掉,这可能导致代码不按预想的方式运行。 赋值的顺序和赋值的时间点并不总是固定的,这依赖于优化器的决定。 赋值符号 :=的优先级非常低,所以需要注意,赋值表达式应该使用明确的括号。 使用未定义变量不会产生任何语法错误,如果没有意识到这一点,非常容易犯错。 https://www.jianshu.com/p/357a02fb2d64

1 min · 46 words · -

nacos

“nacos” distro协议介绍 distro协议网上的资料比较少,因为它是阿里"自创的协议",通过源码总结一下distro协议的关键点: distro协议是为了注册中心而创造出的协议; 客户端与服务端有两个重要的交互,服务注册与心跳发送; 客户端以服务为维度向服务端注册,注册后每隔一段时间向服务端发送一次心跳,心跳包需要带上注册服务的全部信息,在客户端看来,服务端节点对等,所以请求的节点是随机的; 客户端请求失败则换一个节点重新发送请求; 服务端节点都存储所有数据,但每个节点只负责其中一部分服务,在接收到客户端的"写" (注册、心跳、下线等) 请求后,服务端节点判断请求的服务是否为自己负责,如果是,则处理,否则交由负责的节点处理; 每个服务端节点主动发送健康检查到其他节点,响应的节点被该节点视为健康节点; 服务端在接收到客户端的服务心跳后,如果该服务不存在,则将该心跳请求当做注册请求来处理; 服务端如果长时间未收到客户端心跳,则下线该服务; 负责的节点在接收到服务注册、服务心跳等写请求后将数据写入后即返回,后台异步地将数据同步给其他节点; 节点在收到读请求后直接从本机获取后返回,无论数据是否为最新。 https://juejin.im/post/6844904167924826119 https://developer.aliyun.com/article/723938 https://mp.weixin.qq.com/s?__biz=MzI5NjE2MDQwNg==&mid=2247483740&idx=1&sn=e1117bbe107b2e257fcf93cfe04b6218&chksm=ec49dca5db3e55b3305e955972278991e856371693d401f65b26ab055e2b236e6b12efe33753&token=169335499&lang=zh_CN&scene=21#wechat_redirect https://juejin.im/post/6844904167924826119 https://blog.csdn.net/fly910905/article/details/100023415 https://my.oschina.net/u/867417/blog/1865971

1 min · 21 words · -

nats

“nats” https://nats.io/ podman podman run -d –name nats -p 4222:4222 -v /etc/localtime:/etc/localtime:ro nats https://zhuanlan.zhihu.com/p/40871363 nats 是一个开源的,云原生的消息系统。Apcera,百度,西门子,VMware,HTC 和爱立信等公司都有在使用。 核心基于EventMachine开发,原理是基于消息发布订阅机制,每台服务器上的每个模块会根据自己的消息类别向MessageBus发布多个消息主题,而同时也向自己需要交互的模块,按照需要的主题订阅消息。能够达到每秒8-11百万个消息,整个程序很小只有3M Docker image,它不支持持久化消息,如果你离线,你就不能获得消息。使用nats streaming可以做到持久化,缓存等功能。 NATS server nats提供了一个go编写的轻量级服务器。发行版包括二进制和docker镜像 NATS clients nats官方提供的客户端有Go,Node,Ruby,Java,C,C#,NGINX等。 NATS 设计目标 核心原则是性能,可伸缩和易用性。 高效 始终在线和可用 非常轻巧 支持多种质量的服务 支持各种消息传递模型和使用场景 NATS 使用场景 nats是一个简单且强大的消息系统,为支持现代云原生架构设计。由于可伸缩性的复杂性,nats旨在容易使用和实现,且能提供多种质量的服务。 一些适用nats的场景有: 高吞吐量的消息分散 —— 少数的生产者需要将数据发送给很多的消费者。 寻址和发现 —— 将数据发送给特定的应用实例,设备或者用户,也可用于发现并连接到基础架构中的实例,设备或用户。 命令和控制 (控制面板) —— 向程序或设备发送指令,并从程序/设备中接收状态,如SCADA,卫星遥感,物联网等。 负载均衡 —— 主要应用于程序会生成大量的请求,且可动态伸缩程序实例。 N路可扩展性 —— 通信基础架构能够充分利用go的高效并发/调度机制,以增强水平和垂直的扩展性。 位置透明 —— 程序在各个地理位置上分布者大量实例,且你无法了解到程序之间的端点配置详情,及他们所生产或消费的数据。 容错 使用nats-streaming的附加场景有: 从特定时间或顺序消费 持久性 有保证的消息投递 https://docs.nats.io/ https://github.com/nats-io/nats-server https://gcoolinfo.medium.com/comparing-nats-nats-streaming-and-nats-jetstream-ec2d9f426dc8

1 min · 66 words · -

nvme

“nvme” https://zhuanlan.zhihu.com/p/135297463

1 min · 2 words · -

redis vm

“redis vm” 重点提示: Redis 的虚拟内存(VM) 目前不被提倡使用,Redis 2.4将是有虚拟内存特性的最新版本 (但它同样提示不鼓励使用虚拟内存) 。我们发现使用虚拟内存会有一些不足和问题。对于Redis的未来,至少目前在不考虑支持比RAM更大的数据库时,我们希望能提供最好的内存数据库 (持久化仍然在磁盘上) 。我们随后的成果将关注提供脚本,集群以及更好的持久化方面。 虚拟内存 Redis 虚拟内存这一特性将首次出现在Redis 2.0的一个稳定发布版中。目前Git上Redis 不稳定分支的虚拟内存 (从现在起称之为VM) 已经可以使用,并且经试验证明足够稳定。 简介 Redis遵循 key-value模型。同时key和value通常都存储在内存中。然而有时这并不是一个最好的选择,所以在设计过程中我们要求key必须存储在内存中 (为了保证快速查找) ,而value在很少使用时,可以从内存被交换出至磁盘上。 实际应用中,如果内存中有一个10万条记录的key值数据集,而只有10%被经常使用,那么开启虚拟内存的Redis将把与较少使用的key相对应的value转移至磁盘上。当客户端请求获取这些value时,他们被将从swap 文件中读回,并载入到内存中。 何时使用虚拟内存 在确定使用VM之前,请首先确认是否真的需要使用这一特性。Redis是一个磁盘备份,内存型数据库。使用Redis 的正确方法通常是使用足够大的RAM去装载所有数据。然而,有些场景下是无法做到这样的: 数据访问不均匀。只有很少部分的key被大量访问,而每一个key又有大量的数据要放入内存。 在不考虑数据读取方式以及value存储空间大小的前提下,仅由于没有足够的空间将所有数据放入内存。这种场景下,Redis可以被配置为在内存中存储key,在磁盘中存储value。此时key的查询操作较快,而value的读取则相对较慢。 谨记Redis的key是不做swap操作的,所以如果你的内存有大量的key和少量的value时,那么VM并不能解决你的问题。 然而当由于value占用空间较大 (如占用空间较多的strings以及含有大量元素的lists, sets 或者 hashes) 导致内存不足时,那么VM无疑是一个很好的选择。 有时你可以通过哈希表将相关的数据归组到一个key的相应字段,从而将“大量key与小存储的value”的问题转化为“少量key与大存储的value”的问题。例如你可以为每一个对象设置一个单独的key,并用哈希表的多个字段代表对象的不同属性,而非为对象的每一个属性设置一个单独的key。 VM 配置 VM的配置相对简单,可以根据需求设置最佳参数。通过编辑redis.conf来开启并配置VM。首先开启VM: vm-enabled yes 很多配置项可以改变VM的行为。事实上,为了获取最佳性能,你常常需要对配置做微调,而非使用默认参数。 vm-max-memory设置 vm-max-memory 指 Redis 在将value交换至磁盘 (进行swap操作) 之前有多大内存可使用。 通常,如果未达到内存上限,则不需要进行磁盘交换,Redis将所有对象放在内存中操作。然而一旦到达上限,将会有大量的对象被交换出内存至磁盘,以释放内存空间,直到低于限制。 交换过程 (swap操作) 中,首先被交换的对象是那些有着较大“年龄” (指未被访问的时长) 的对象,同时一个对象的“交换能力” (”swappability”) 与它在内存中大小的对数成正 (swappability = age*log(size_in_memory)) 。当两个对象有着相同的“年龄”时,占用空间较大的对象将会首先被交换出去。 提醒: 由于key不能被交换出内存,所以当仅由于key占用空间较多而达到内存上限时, Redis是不能通过改变 vm-max-memory 来解决问题的。 ...

2 min · 314 words · -

redis, memcache

“redis, memcache” Redis 和 Memcached 都是基于内存的数据存储系统。Memcached是高性能分布式内存缓存服务,其本质上就是一个内存key-value数据库。Redis是一个开源的key-value存储系统。与Memcached类似,Redis将大部分数据存储在内存中,支持的数据类型包括: 字符串、哈希表、链表、集合、有序集合以及基于这些数据类型的相关操作。那么,Memcached与Redis有什么区别呢? 数据操作不同, Redis支持的数据类型要丰富得多 与Memcached仅支持简单的key-value结构的数据记录不同,Redis支持的数据类型要丰富得多。 Memcached基本只支持简单的key-value存储,不支持枚举,不支持持久化和复制等功能。 Redis支持服务器端的数据操作相比Memcached来说,拥有更多的数据结构和并支持更丰富的数据操作,支持list、set、sorted set、hash等众多数据结构,还同时提供了持久化和复制等功能。而通常在Memcached里,使用者需要将数据拿到客户端来进行类似的修改再set回去,这大大增加了网络IO的次数和数据体积。在Redis中,这些复杂的操作通常和一般的GET/SET一样高效。所以,如果需要缓存能够支持更复杂的结构和操作, Redis会是更好的选择。 内存管理机制不同 在Redis中,并不是所有的数据都一直存储在内存中的。这是和Memcached相比一个最大的区别。当物理内存用完时,Redis可以将一些很久没用到的value交换到磁盘。Redis只会缓存所有的key的信息,如果Redis发现内存的使用量超过了某一个阀值,将触发swap的操作,Redis根据“swappability = age*log(size_in_memory)”计算出哪些key对应的value需要swap到磁盘。然后再将这些key对应的value持久化到磁盘中,同时在内存中清除。这种特性使得Redis可以保持超过其机器本身内存大小的数据。 而Memcached默认使用Slab Allocation机制管理内存,其主要思想是按照预先规定的大小,将分配的内存分割成特定长度的块以存储相应长度的key-value数据记录,以完全解决内存碎片问题。 从内存利用率来讲,使用简单的key-value存储的话,Memcached的内存利用率更高。而如果Redis采用hash结构来做key-value存储,由于其组合式的压缩,其内存利用率会高于Memcached。 性能不同 由于Redis只使用单核,而Memcached可以使用多核,所以平均每一个核上Redis在存储小数据时比Memcached性能更高。而在100k以上的数据中,Memcached性能要高于Redis,虽然Redis也在存储大数据的性能上进行了优化,但是比起Memcached,还是稍有逊色。 集群管理不同 Memcached是全内存的数据缓冲系统,Redis虽然支持数据的持久化,但是全内存毕竟才是其高性能的本质。作为基于内存的存储系统来说,机器物理内存的大小就是系统能够容纳的最大数据量。如果需要处理的数据量超过了单台机器的物理内存大小,就需要构建分布式集群来扩展存储能力。 Memcached本身并不支持分布式,因此只能在客户端通过像一致性哈希这样的分布式算法来实现Memcached的分布式存储。相较于Memcached只能采用客户端实现分布式存储,Redis更偏向于在服务器端构建分布式存储。 持久性 redis支持数据落地持久化存储,可以将内存中的数据保持在磁盘中,重启的时候可以再次加载进行使用。 memcache不支持数据持久存储 小结: Redis和Memcached哪个更好? Redis更多场景是作为Memcached的替代者来使用,当需要除key-value之外的更多数据类型支持或存储的数据不能被剔除时,使用Redis更合适。如果只做缓存的话,Memcached已经足够应付绝大部分的需求,Redis 的出现只是提供了一个更加好的选择。总的来说,根据使用者自身的需求去选择才是最合适的。 It’s not uncommon to hear Redis compared to memcached, which is a very high- performance, key-value cache server. Like memcached, Redis can also store a mapping of keys to values and can even achieve similar performance levels as memcached. But the similarities end quickly—Redis supports the writing of its data to disk automatically in two different ways, and can store data in four structures in addition to plain string keys as memcached does. These and other differences allow Redis to solve a wider range of problems, and allow Redis to be used either as a primary database or as an auxiliary data- base with other storage systems. ...

1 min · 161 words · -

SCTP GRE

SCTP sctp和tcp的区别 作为一个传输层协议,SCTP兼有TCP及UDP两者的特点。SCTP可以称为是TCP的改进协议,但他们之间仍然存在着较大的差别。首先SCTP和TCP之间的最大区别是SCTP的连接可以是多宿主连接的,TCP则一般是单地址连接的。在进行SCTP建立连接时,双方均可声明若干IP地址(IPv4,Ipv6或主机名)通知对方本端所有的地址。若当前连接失效,则协议可切换到另一个地址,而不需要重新建立连接。 其次SCTP是基于消息流,而TCP则是基于字节流。所谓基于消息流,是指发送数据和应答数据的最小单位是消息包(chunk)。一个SCTP连接(Association)同时可以支持多个流(stream),每个流包含一系列用户所需的消息数据(chunk)。而TCP则只能支持一个流。在网络安全方面,SCTP增加了防止恶意攻击的措施。不同于TCP连接采用的三次握手机制,SCTP连接采用四次握手机制,有效的防止了类似于SYN Flooding的防范拒绝服务攻击。SCTP主要的贡献是对多重联外线路的支持,一个端点可以由多于一个IP地址组成,使得传输可在主机间或网卡间做到透明的网络容错备援。 https://www.cnblogs.com/elleniou/p/3342140.html GRE 通用路由封装协议GRE 提供了将一种协议报文封装在另一种协议报文中的机制,是一种三层隧道封装技术;可以对IPv4协议的数据报文进行再封装,使这些被封装的数据报文能够在另一个网络层协议(如IPv4)中传输;报文通过GRE隧道透明的传输,可以解决外网主动访问内网的问题;GRE可以封装组播数据和路由选择协议,结合IP Sec使用,从而保证语音、视频等组播业务的安全。 GRE实现机制简单,对隧道两端的设备负担小;GRE隧道可以有效利用了原有的网络架构,降低成本;GRE隧道扩展了跳数受限网络协议的工作范围,支持企业灵活设计网络拓扑;GRE隧道支持MPLS LDP,使用GRE隧道承载MPLS LDP报文,建立LDP LSP,实现MPLS骨干网的互通;GRE隧道将不连续的子网连接起来,用于组建VPN,实现企业总部和分支间安全的连接。 https://zhuanlan.zhihu.com/p/103214510

1 min · 15 words · -

spring security

“spring security” spring security pom.xml <dependency> <!-- 由于我使用的spring boot所以我是引入spring-boot-starter-security而且我使用了spring io所以不需要填写依赖的版本号 --> <groupId>org.springframework.boot</groupId> spring-boot-starter-security</artifactId> </dependency> .authorizeRequests() 通过 authorizeRequests() 方法来开始请求权限配置。 authorizeRequests()方法有多个子节点,每个macher按照他们的声明顺序执行 可以在authorizeRequests() 后定义多个antMatchers()配置器来控制不同的url接受不同权限的用户访问,而其中 permitAll() 方法是运行所有权限用户包含匿名用户访问。 而hasRole(“权限”)则是允许这个url给与参数中相等的权限访问。 access(“hasRole(‘权限’) and hasRole(‘权限’)”) 是指允许访问这个url必须同时拥有参数中多个身份权限才可以访问。 hasAnyRole(“ADMIN”, “DBA”)是指允许访问这个url必须同时拥有参数中多个身份权限中的一个就可以访问该url。 .anyRequest().authenticated() 对http所有的请求必须通过授权认证才可以访问。 and()是返回一个securityBuilder对象,formLogin()和httpBasic()是授权的两种方式。 .csrf().disable(); //取消csrf防护 .sessionManagement() // 定制我们自己的 session 策略 .sessionCreationPolicy(SessionCreationPolicy.STATELESS); // 调整为让 Spring Security 不创建和使用 session HttpSecurity 提供的 exceptionHandling() 方法用来提供异常处理。该方法构造出 ExceptionHandlingConfigurer 异常处理配置类。该配置类提供了两个实用接口: AuthenticationEntryPoint 该类用来统一处理 AuthenticationException 异常 AccessDeniedHandler 该类用来统一处理 AccessDeniedException 异常 我们只要实现并配置这两个异常处理类即可实现对 Spring Security 认证授权相关的异常进行统一的自定义处理。 作者: 码农小胖哥 链接: https://juejin.cn/post/6844903988895154184 来源: 掘金 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 ...

1 min · 126 words · -

STM32F407VG, STM32F407VGT6

“STM32F407VG, STM32F407VGT6” STM32F407VGT6 SMT32: 产品系列: 基于ARM的32位处理器 F: 产品类型: 通用类型 407: 产品子系列: … V: 引脚数: 100脚 G: 闪存容量: 1M T: 封装: LQFP 6: 温度范围: -40 ~ 85度 https://www.st.com/zh/microcontrollers-microprocessors/stm32f407-417.html Cortex™-M4内核 (具有浮点单元) 168 MHz 意法半导体90 nm工艺和ART加速器 2个USB OTG (其中一个支持HS) 音频: 专用音频PLL和2个全双工I²S 通信接口多达15个 (包括6个速度高达11.25 Mb/s的USART、3个速度高达45 Mb/s的SPI、3个I²C、2个CAN和1个SDIO) 模拟: 2个12位DAC、3个速度为2.4 MSPS或7.2 MSPS (交错模式) 的12位ADC 定时器多达17个: 频率高达168 MHz的16和32位定时器 可以利用支持Compact Flash、SRAM、PSRAM、NOR和NAND存储器的灵活静态存储器控制器轻松扩展存储容量 基于模拟电子技术的真随机数发生器 STM32F417还整合了加密/HASH处理器,为AES 128、192、256、3DES和HASH (MD5、SHA-1) 实现了硬件加速。 集成: STM32F417x系列具有512KB (仅限于WLCSP90封装) 1MB Flash和192KB SRAM,采用尺寸小至4 x 4.2 mm的64144引脚封装。 STM32F407/417产品系列具有512KB1MB Flash和192KB SRAM,采用尺寸小至10 x 10 mm的100 176引脚封装。

1 min · 74 words · -

thundering herd, 惊群效应

“thundering herd, 惊群效应” 惊群效应是什么 惊群效应 (thundering herd) 是指多进程 (多线程) 在同时阻塞等待同一个事件的时候 (休眠状态) ,如果等待的这个事件发生,那么他就会唤醒等待的所有进程 (或者线程) ,但是最终却只能有一个进程 (线程) 获得这个时间的“控制权”,对该事件进行处理,而其他进程 (线程) 获取“控制权”失败,只能重新进入休眠状态,这种现象和性能浪费就叫做惊群效应。 惊群效应消耗了什么 Linux 内核对用户进程 (线程) 频繁地做无效的调度、上下文切换等使系统性能大打折扣。上下文切换 (context switch) 过高会导致 CPU 像个搬运工,频繁地在寄存器和运行队列之间奔波,更多的时间花在了进程 (线程) 切换,而不是在真正工作的进程 (线程) 上面。直接的消耗包括 CPU 寄存器要保存和加载 (例如程序计数器) 、系统调度器的代码需要执行。间接的消耗在于多核 cache 之间的共享数据。 为了确保只有一个进程 (线程) 得到资源,需要对资源操作进行加锁保护,加大了系统的开销。目前一些常见的服务器软件有的是通过锁机制解决的,比如 Nginx (它的锁机制是默认开启的,可以关闭) ;还有些认为惊群对系统性能影响不大,没有去处理,比如 Lighttpd。 https://www.cnblogs.com/Anker/p/7071849.html https://zhuanlan.zhihu.com/p/51251700 https://zhuanlan.zhihu.com/p/65843741

1 min · 48 words · -

TLB

“TLB” TLB是translation lookaside buffer的简称。首先,我们知道MMU的作用是把虚拟地址转换成物理地址。虚拟地址和物理地址的映射关系存储在页表中,而现在页表又是分级的。64位系统一般都是3~5级。常见的配置是4级页表,就以4级页表为例说明。分别是PGD、PUD、PMD、PTE四级页表。在硬件上会有一个叫做页表基地址寄存器,它存储PGD页表的首地址。MMU就是根据页表基地址寄存器从PGD页表一路查到PTE,最终找到物理地址(PTE页表中存储物理地址)。这就像在地图上显示你的家在哪一样,我为了找到你家的地址,先确定你是中国,再确定你是某个省,继续往下某个市,最后找到你家是一样的原理。一级一级找下去。这个过程你也看到了,非常繁琐。如果第一次查到你家的具体位置,我如果记下来你的姓名和你家的地址。下次查找时,是不是只需要跟我说你的姓名是什么,我就直接能够告诉你地址,而不需要一级一级查找。四级页表查找过程需要四次内存访问。延时可想而知,非常影响性能。页表查找过程的示例如下图所示。以后有机会详细展开,这里了解下即可。 TLB Translation Look-aside Buffer 地址变换高速缓存 地址转换后备缓冲器 学习理解TLB (Translation Look-aside Buffer) 地址变换高速缓存 前言: 本文学习思路是: 存在缘由 –> 存在好处 –> 定义性质 –> 具体分析 存在缘由: 由于地址映射 (从虚拟地址转换成物理地址) 需要的开销开大。 转换过程如下: 第一次访问内存是访问页表,取出虚拟页对应的物理页。 第二次访问内存是访问实际内存地址。 为了提高效率,现代CPU都包含了一个特殊Cache来跟踪最近使用过的地址变换,这个就是TLB。 明显好处: 如果有了TLB,那么地址转换变成如下过程: 第一次访问TLB,得到虚拟页对应的物理页 第二次访问的是内存,访问实际地址。 这样就省去了一次访问内存的时间,大大提高了效率。 概念概括: TLB英文全称: Translation Look-aside Buffer TLB中文全称: 地址变换高速缓存 TLB中文简称: 快表 TLB实际性质: 它是一种cache TLB的每一项中包含 有效位(valid)。现在的计算机基本都是使用虚拟存储器,简单来说就是假如你要打开一个很大的程序,它不会把所有的文件都加载进内存。当需要用的内容不在内存上时,它再去硬盘上找并加载到内存。故,有效位的作用就是,假如是0,就代表该页不在内存中,需要去硬盘中找。 引用位(reference)。由于TLB中的项数是一定的,所以当有新的TLB项需要进来但是又满了的话,如果根据LRU算法,就将最近最少使用的项替换成新的项。故需要引用位。同时要注意的是,页表中也有引用位。 脏位(dirty)。现在的计算机基本都是使用虚拟存储器,简单来说就是假如你要打开一个很大的程序,它不会把所有的文件都加载进内存。当需要用的内容不在内存上时,它再去硬盘上找并加载到内存。故脏位的作用就是,当内存上的某个块需要被新的块替换时,它需要根据脏位判断这个块之前有没有被修改过,如果被修改过,先把这个块更新到硬盘再替换,否则就直接替换。 物理页号。 过程描述如下: 首先,先去TLB中根据标志Tag寻找,假如找到了并且有效位是1,说明TLB命中了,那么直接就可以从TLB中获取该虚拟页号对应的物理页号。假如有效位是0,说明该页不在内存中,这时候就发生缺页异常,CPU需要先去外存中将该页调入内存并将页表和TLB更新。 假如在TLB中没有找到,那么就去页表 (Page Table) 中寻找 (以虚拟页号为索引) ,假如找到了并且有效位是1,那么就可以取出对应的物理页号。假如有效位是0,说明该页不在内存中,这时候就发生缺页异常,CPU需要先去外存中将该页调入内存并将页表和TLB更新。 假如在页表中没有找到,也是缺页。同意会执行上述的缺页处理。 (不管从哪获取到物理页号,都可以根据规则组拼成实际物理地址,然后就可以访存去数据啦) 引用位、脏位何时更新? 页表和TLB都有这两个标志位。如果是TLB命中,那么引用位就会被置1,当TLB或页表满时,就会根据该引用位选择适合的替换位置。如果TLB命中且这个访存操作是个写操作,那么脏位就会被置1,表明该页被修改过,当该页要从内存中移除时会先执行将该页写会外存的操作,保证数据被正确修改。 当TLB的某一项要被替换时,它的引用位和脏位都会被更新会页表。 补充: ...

2 min · 404 words · -