TCP三次握手四次挥手、Http协议解答
1. TCP 三次握手和四次挥手简单示意图:
客户端-发送带有SYN标志的数据包 一次握手-服务端
服务端-发送带有SYN/ACK标志的数据包 二次握手-客户端
客户端-发送带有ACK标志的数据包 三次握手-服务端
SYN(Synchronize Sequence Numbers)同步序列编号,是TCP/IP建立连接时使用的握手信号。在客户端和服务端之间建立正常的TCP网络连接时,客户端首先发出一个SYN信息,服务端使用SYN-ACK应答表示接收到了这个消息,最后客户端再以ACK(Acknowledgement)消息响应。这样在客户端和服务端之间才能建立起可靠的TCP连接。
1.1. 三次握手的原因
三次握手的目的是建立可靠的通信信道,让发送方和接收方确定自己与对方的发送和接收是正常的
第一次握手:Client什么都不能确认;Server确定了自己接收正常,对方发送正常
第二次握手:Client确认了自己发送、接收正常,对方发送、接收也正常;Server确认了自己接收正常,对方发送正常
第三次握手:Client确认了自己发送、接收正常, ...
Java8函数式编程接口
函数式接口
将方法作为参数传递
lamba表达式
将数学函数抽象成接口对象
Consumer:消费型接口
抽象方法:void accept(T t) 接收一个参数进行消费,但无需返回结果
12Consumer c1 = (x) -> System.out.println(x); //单个入参和方法可简写 c1 = System.out::printlnc1.accept("hello world") //实现 打印hello world
默认方法:andThen(Consumer<? super T> after) 先执行调用andThen的accept方法,再执行andThen方法中参数after的accept方法
123Consumer c1 = (x) -> System.out.println("c1" + x);Consumer c2 = (x) -> System.out.println("c2" + x);c1.andThen(c2).accept("go&qu ...
更新Redis缓存,再更新数据库;还是更新数据库再更新Redis
在大型系统中,为了抗住高并发,减少数据库压力。都会引入缓存机制,一旦加多了一层缓存。就必须要处理缓存数据与数据库不一致的问题。
更新缓存和数据的机制处理策略如下:
Cache aside 旁路缓存
Read/Write through 抽象缓存层
Write behind 延迟写入
常见普通读/写请求流程
情况一:先更新数据库,再更新缓存
如果同时有两个写请求更新同一数据,每个写请求都是先更新数据库再更新缓存,在并发场景下可能会出现数据不一致
写请求1 更新数据库,将库存从100减一,写入数据库99
写请求2 更新数据库,将库存从99减一,写入数据库98
写请求2 更新缓存,set 98
写请求1 更新缓存,set 99
情况二:先删除缓存,再更新数据库
如果同时有一个读请求和一个写请求并发场景下,写请求是先删除缓存再更新数据库,可能造成数据不一致
写请求 清除缓存
读请求 查询缓存为空,查询数据库;返回库存100,再Set缓存100
写请求 更新数据库为99
情况三:先更新数据库,在删除缓存
如果同时有一个读请求和一个写请求并发场景下,写请求 ...
Redis高可用集群
分布式架构设计的核心思想
高性能:读写分离、分片集群
高可用:数据持久化、多副本、故障自动转移
易扩展:分片集群、横向扩展
分布式共识:哨兵,领导者选举
负载均衡:数据分片、数据路由
单机版Redis
业务 -> Redis -> MySQL
这个架构非常简单,你的业务应用可以把 Redis 当做缓存来使用,从 MySQL 中查询数据,然后写入到 Redis 中,之后业务应用再从 Redis 中读取这些数据,由于 Redis 的数据都存储在内存中,所以这个速度飞快。
但是,突然有一天,你的 Redis 因为某些原因宕机了,这时你的所有业务流量,都会打到后端 MySQL 上,这会导致你的 MySQL 压力剧增,严重的话甚至会压垮 MySQL。
数据持久化,解决重启丢失问题
RDB:
只持久化某一时刻的数据快照 到磁盘上(创建一个子进程来执行)
采用二进制+数据压缩的方式写磁盘,这样文件体积小,数据恢复速度也快
AOF:
每一次写操作都持久到磁盘(主线程写内存,根据策略可以配置由主线程还是子线程进行数据持久化)
记录的是每一次的写命令,数据最全,文件体积大、数 ...
Python语句介绍及函数定义和参数类型
语句if
if 语句的判断条件可以用>(大于)、<(小于)、==(等于)、>=(大于等于)、<=(小于等于)来表示其关系。非零数值、非空字符串、非空 list 等,判断为 True,否则为 False
1234567891011if x > 0: print('正数')else: print('零或负数')if s : print('有值')>>> s = 0 无输出>>> s = 1 有值
if 语句多个判断条件的形式12345678if 判断条件1: 执行语句1……elif 判断条件2: 执行语句2……elif 判断条件3: 执行语句3……else: 执行语句4……
if 语句多个条件同时判断结合 or 和 and 来使用
12345if age > 0 and age < 18 print('未成年')if age < 18 or ag ...
Python数据类型及转换包括集合
整数包括正整数、负整数和零,是没有小数点的数字。
Python 可以处理任意大小的整数,例如:1,100,-8080,0,等等。
浮点数指带小数的数字
需要注意精度丢失问题
因为计算机对浮点数的表达本身是不精确的。保存在计算机中的是二进制数,二进制对有些数字不能准确表达,只能非常接近这个数。
字符串字符串英文 string ,是 python 中随处可见的数据类型,字符串的识别也非常的简单,就是用「引号」括起来的。
引号包括单引号 ' ' ,双引号 " " 和 三引号 ''' ''' ,比如 'abc' ,"123" 等等。
转义字符:
比如单引号,你可以使用 \' 来表示,双引号可以使用 \" 来表示。
注意,这里的是反斜杠 \, 不是斜杆 / 。
字符串编码问题通常在文件开头写上这两行:
12#!/usr/bin/env python3# -*- coding: utf-8 -*-
第一行注释是为了告诉 Linux/OS X 系统, ...
Python代码规范大全
一、简明概述1、编码
如无特殊情况, 文件一律使用 UTF-8 编码
如无特殊情况, 文件头部必须加入#-*-coding:utf-8-*-标识
2、代码格式2.1、缩进
统一使用 4 个空格进行缩进
2.2、行宽每行代码尽量不超过 80 个字符(在特殊情况下可以略微超过 80 ,但最长不得超过 120)
理由:
这在查看 side-by-side 的 diff 时很有帮助
方便在控制台下查看代码
太长可能是设计有缺陷
2.3、引号简单说,自然语言使用双引号,机器标示使用单引号,因此 代码里 多数应该使用 单引号
自然语言 使用双引号 "..."例如错误信息;很多情况还是 unicode,使用u"你好世界"
机器标识 使用单引号 '...'例如 dict 里的 key
正则表达式 使用原生的双引号 r"..."
文档字符串 (docstring) 使用三个双引号 """......"""
2.4、空行
模块级函数和类定义之间空两行;
类成员 ...
正则表达式
正则表达式用于字符串的判断、匹配。用一组规则来定义字符串是否符合要求
精确匹配
\d 匹配一个数字
\w 匹配一个字母或者数字
\s 匹配一个空格(也包括Tab等空白符), \s+表示至少一个空格
. 匹配任意字符
* 表示任意个字符(包括0个)
+ 表示至少一个字符
? 表示0个或1个字符
{n} 表示n个字符
{n,m} 表示n-m个字符
A|B 匹配A或者B 所以(P|p)ython匹配Python或python 也可以写成P|python
^ 表示行的开头,^\d 表示必须以数字开头
$ 表示行的结束,\d$ 表示必须以数字结尾
[] 表示范围 () 表示或者
[a-z] 表示从字母a到z
(a|b) 表示a或者b
字符
数量
位置
\d 匹配数字
* 0个或者更多
^ 一行的开头
\w 匹配字符(数字、字母)
+ 至少一个字符
$ 一行的结尾
\s 匹配一个空格(也包括Tab等空白符)
? 0个或者1个字符
\b 单词“结界”
\S 匹配非空格(包括Tab等空 ...
Javaagent介绍及使用示例
javaagent介绍及使用Javaagent是从JDK1.5开始引入的,agent的意思是代理,它实际上是个包含premain方法的jar包。要被监控的程序执行时需要在java启动参数中增加-javaagent参数,指定要加载的javaagent包。premain方法先于main方法执行,可以在类加载之前修改类定义,从而实现很多功能。
当Javaagent正确被加载,premain方法会自动被调用,并且会获取到Instrumentation对象的一个引用。通过Instrumentation这个对象,可以实现很多功能,比如修改类路径、获取已经加载的类、获取对象大小等等。其中最常用的是通过addTransformer方法添加类转化器,动态修改类定义,从而实现无侵入的应用监控。
从JDK1.6开始,提供了agentmain方法,提供了动态修改运行中的已经被加载的类的途径。一般通过VirtualMachine的attach(pid)方法获得VirtualMachine实例,随后调用loadagent方法将Javaagent的jar包加载到目标JVM中。
总结:Javaagent 只要作用在 ...
数据结构随笔
数组(Array)数组(Array)由相同类型的元素(Element)组成,并且使用一块连续的内存来存储。可以直接用索引(index)计算出该元素对应的存储地址特点是:提供了随机访问 并且容量有限
1234假设数组长度为n访问:O(1) 访问特定位置的元素插入:O(n) 最坏的情况,插入在数组首位,需要移动整个数组元素删除:O(n) 最坏的情况,删数组开头元素,需将后面的元素整个前移
链表(LinkedList)虽然是一种线性表,但是并不会按线性的顺序存储数据,使用的不是连续的内存空间来存储数据链表的删除和插入操作的复杂度为O(1),因为只需要知道目标元素的上一个元素位置即可,但是在查找的时候复杂度为O(n)
使用链表结构可以克服数组需要预知大小的缺点。链表可以充分利用计算机内存空间,进行灵活内存管理。但是链表不是节省空间,相对于数组会占用更多空间,因为每个节点还要存储指向其他节点的指针。除此以外,链表不具有数组随机读取的优点
链表分类
单链表
双向链表
循环链表
双向循环链表123假如列表中有n个元素访问:O(n) 访问特定位置的元素插入删除:O(1) 需知道插入元素的位 ...