DanZ's Blog

a normal developer daily blog

0%

一.InnoDB的表和数据

InnoDB 是怎样存储数据的,表是大概怎样的一种格式,表中的数据行又是怎样的一种格式。如果想要大概知道 B+ 索引的执行过程,这块基本是跳不过去的。当然关于 数据行 的东西特别多,没办法涵盖所有,所以我只能将我学的,大概知道的重要部分取出来说一说。

这里先大概说下后面才说的 索引 问题,B+索引 其实利用了表中的 行记录头(可以想象是 HTTP 请求的请求头),然后进行数据结构组织实现快速检索的一种结构。所以不用说啦,行记录头 一些必要的属性,基本要知道的,也可以优化数据库的占用空间。

阅读全文 »

一.InnoDB存储引擎

自从 InnoDBHeikki Tuuri 发明出来以后,可以说安装 MySQL 肯定默认的引擎就是设置 InnoDB,因为其功能强大,实用性强,基本很多业务需求不要太过纠结的话都可以使用 InnoDB 进行存储(当然现在看来,当你的表不需要事务的时候可以使用 MyISAM 来进行存储)。 InnoDB 相比其他的存储引擎,拥有以下几个特点:

  1. 支持完整 ACID 事务;
  2. 行锁设计,可提高并发;
  3. 支持 MVCC 可以说是数据行的版本控制,利用他来避免 幻读 的产生;
  4. 支持外键;
  5. 优秀的 B+ 索引。
    阅读全文 »

一.MySQL介绍

作为 MySQL 系列的开篇,我觉得还是有必要说说大家熟悉的 MySQL 数据库的一些东西。 MySQL 我想作为开发者应该没有人不认识或者不熟悉了吧。不管所在的厂子是大中小,基本上很多时候都会采用 MySQL 作为我们数据的存储介质。当然政府项目很多都会采用 Oracle 数据库,不过最近看来,这个事情貌似也不是绝对。也有很多政府的项目已经决定采用 MySQL 或者其他厂商封装的 MySQL 分支了。 作为数据库,其实定义是这样的:

  • 数据库:文件或者其他文件类型的集合,在 MySQL 中,文件被存储为 frm myd ibd 等多种形式的文件。而有些存储引擎比如 NDB 他的数据信息则是被存储在内存之中的,并不会持久化到硬盘上面,所以他不需要文件来进行存储。速度稍稍快但数据库出现异常重启的话,数据就会丢失。
  • 数据库实例或软件:其实就是运行的,可以读取以上数据库文件的软件进程,他可能是一个也可能是多个,日常开发经常是运行一个的情形。我们运行 SQL 或者其他操作的,其实都是在跟数据库实例进行交互,数据库实例会根据命令,计算出来比较高效的查询策略在硬盘上进行数据查询。
    阅读全文 »

一.实时消息WebSocket

传统的 WEB 开发中,通常我们渲染数据或者请求增删改的时候,都需要通过发送 HTTP 请求。 而每次发送 HTTP 请求基本都需要经历下面的历程(其实和 TCP 大致相同): image-20190804143610798 而当我们需要一些实时消息的需求的时候,比如聊天或者消息推送,那么我们有一种做法就是。浏览器每隔几秒轮训一次服务器(因为不请求服务器就没法回复消息),走一下上面的步骤,然后服务器如果有数据响应数据,没有数据就响应空的数据。哇啊啊啊啊你看这个过程,如果我的后台系统这个账号刚好没什么生意,基本很少需要推送有人下单的消息给我,可是我还是要走这些流程,服务器也还是需要处理我这个没用的卖家的请求。 当然并不是这种方式没人采用,还是有的,因为开发简单。但是性能其实并不怎么样,而且还要浪费一个服务来处理这个请求。 这个问题看起来还是比较棘手的而且很迫切的一个需求,于是乎我们的 W3C 组织站了出来,为浏览器新增了一个新的协议 WebSocket 协议,在 HTML5 发布的时候新增进去的。 WebSocketHTTP 在同一层,利用 HTTP 向服务器请求升级 WebSocket,服务器应答即可将当前的连接升级为 WebSocket 连接。

1
2
3
4
5
6
7
GET ws://localhost:9999/ HTTP/1.1
Host: localhost
Upgrade: websocket # 请求升级WebSocket
Connection: Upgrade # 同样
Origin: http://localhost:8000
Sec-WebSocket-Key: client-random-string
Sec-WebSocket-Version: 13

服务器如果答应了,就会响应:

1
2
3
4
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: server-random-string

这时候相当于说,我浏览器和服务器经历了三次握手,然后在中间建设了一个管道。 这个管道,谁都可以随时使用,客户端和服务端都可以同时发送消息。也就是说在上面订单通知的例子中,我服务器收到了一个订单支付成功,即可立马发送一条消息给你客户端。

阅读全文 »

一.数据传输的容器ByteBuf

1.1. 简单理解一下

OK,上一篇文章我们大致了解了 Netty 在运行过程中所需要的一些组件。接下来需要慢慢的深入了解这些容器了。 为了方便回忆,我先贴一段上一篇的代码:

1
2
3
4
...
ByteBuf in = (ByteBuf) msg;
String message = in.toString(Charset.defaultCharset());
...

我们可以看到,在服务端代码中,使用了 ByteBuf 来读取客户端所传递的消息,然后实现逻辑,再使用 ByteBuf out = Unpooled.copiedBuffer(newMsg.getBytes(Charset.defaultCharset().name())); 来将处理后的数据重新封装成字节,从而写出去,传递给客户端。 所以大概猜一下,ByteBuf 是一个装载着数据字节的容器,在 Netty 中通过网络进行传输。客户端又重新解码,读取出服务端返回的数据。 其实,jdk 自己的 NIO 也有个类似的类 ByteBuffer,但是这个类,他不太灵活,所以 Netty 才决定重写这个类,从而达到一些比较灵活的目的:

  1. 可以被自定义缓冲区类型拓展;
  2. 通过内置的符合缓冲区类型实现透明的零拷贝;
  3. 容量可以自增;
  4. 读写模式不需要来回切换(得益于读写指针);
  5. 支持链式调用、引用计数以及池化计数。
    阅读全文 »

零.Netty

其实了解到 Netty 已经很久了,一直想用,但是因为之前的水平还不够格,回调事件 TCP 什么的还没感觉,所以学起来一头雾水,加上官网的文档,哎呀,官网貌似就没有文档只有示例代码,读不懂。 写了挺多的回调函数,渐渐地有了感觉(通常使用 CompleteFuture 来请求其他服务的数据信息,请求完在执行自己的业务)。其实我也不知道我做了什么,貌似什么没做就突然融会贯通了,所以我感觉理解回调还是蛮重要的一点吧。 突然看到自己的书本库有本书《Netty实战》翻起来阅读,还是蛮好的,这篇文章其实是我读这本书,加上自己的一些理解写出来的。 Netty 是什么应该没人不会知道吧,就是 Java 行业中一个能够顶级处理网络通讯的轻量级框架,如果公司在使用 Dubbo 或者 Thrift 的话,那么也是间接在使用 Netty 框架了。所以学一学无伤大雅还可以了解一些很有趣的东西。

一.Netty服务端

所有 Netty服务器 通常需要以下两部分:

  1. 至少一个 ChannelHandler 来接手客户端的数据以及处理数据;
  2. 引导服务器启动的配置,配置启动参数,这个就没啥好说的了。

ChannelHandlerNetty 中一个接口族的父接口,它主要负责接收和响应事件通知。 在 NettyChannelHandler 有很多默认实现,用来处理服务器中常见的数据传输问题。 因为服务器会响应传入的消息,所以需要实现 ChannelInboundHandler 接口,用来定义响应入站事件的方法。由于刚开始的程序只需要简单的方式即可,所以我们实现 ChannelInboundHandlerAdapter 即可,他提供了 ChannelInboundHandler 接口的默认实现。 我现在想要简单的实现一个服务,就是能够把把我发送的字符串,给反转过来,即发送 abc 服务器给我响应 cba

阅读全文 »

前言

我们知道,使用 SpringCloud 技术栈,上下游传值的方式一般使用 form 表单或者使用 JSON 格式进行传值。但是我感觉,我们内部服务进行传值的时候,还使用这两种类型的方式,显得有点重。所以在查询了 Java 界以及其他语言序列化对象的时候,查询到了几个常用的序列化工具:kryo Hession JSON XML Protocol Buffers JSON XML 就不必多言,使用 Java 语言开发的基本都知道。 kryo 效率高,使用二进制文件进行传递,但是有个缺点就是不能跨语言。 Hession 效率稍稍差一点。 那么剩下的 Protocol Buffers 就是能够弥补上面的缺点,并且带来一个新的缺点:需要编写静态的 .proto 文件使其项目启动的时候,静态编译映射规格。不过速度高,跨语言,这点缺陷我还是可以接受的。 基本确定方向以后,那么本文就从怎么使用 .proto 将其整合到我们常用的 SpringMVC 中去,使其序列化和反序列化的过程对我们业务开发不可见。

ProtocolBuffers入门

ProtocolBuffers 规则是这样的:编辑 .proto 文件,使用编译器编译不同语言的 ClassObject 。有点类似于 Thift 。所以一开始我们需要的是 ProtocolBuffer编译器

下载ProtocolBuffer编译器

下载地址 根据自己所使用的系统版本,下载对应的编译器。 下载完成以后,进入 protoc-3.7.1-osx-x86_64/bin 运行 ./protoc --version 如果能够打印版本号则说明安装成功。

编写简单的proto文件

现在开始尝试生成类似于以下 Java

1
2
3
4
5
public class User {
private String name;
private Integer id;
// 省略 getter setter
}
阅读全文 »

微服务是什么

单体项目

在互联网刚开始的年代,传统的单体项目,一般是一个服务器,对少量的用户足矣。这时候,开发一套系统,可以提供少量的(相比于现在)服务。并发性不大,服务器性能不需要太好都可以跑得好好的。这个时代我没有经历过。

单体项目分布式

互联网稍稍发展起来了,一台服务器好像支撑不大住。这时候,聪明的程序员们就说,如果一个系统撑不住,那就启动两个来为客户服务呀。所以架构就变成这样,用户,可以把请求落到两个随便一毛一样的系统上面,提供服务是一致的。这时候一般考虑 sessionid 的共享。

阅读全文 »

总览

使用的 Redis 版本:4 通常来说,一个小型的项目一台 redis 服务实例即可满足需求,但是当系统很大的时候,客户端读写频繁,一台机器很容易就成为性能和内存的瓶颈,这时候就需要使用集群来拓展性能了。 redis 集群有两种方式:

  1. 复制
  2. 哨兵
  3. 集群

    复制模式

全量复制

redis 在复制模式下被分为两类数据库:主数据库和从数据库。一个主数据库可以拥有多个从数据库,但是一个从数据库则只能拥有一个主数据库。当主库数据发送变化时,redis 会将数据自动同步到多个从数据库中去。 在 redis 数据库中使用复制功能很简单,只需要在从数据库的配置文件中加入以下配置即可实现:

ps:以下配置是 Redis4 的配置,在以前版本需要查看配置文件的配置方式。

1
2
3
replicaof 192.168.1.129 6379 # 配置主数据库链接信息
masterauth 123456 # 配置主数据库的密码
bind 192.168.1.130 # 配置主数据库的IP地址表示可以让这个IP访问数据
阅读全文 »

总览

redis 数据库,可以直接用来当数据库使用,也可以当系统的缓存使用。但是 redis 大部分数据是存储在内存中的,当服务掉线重启,会造成数据的丢失。当然,redis 是有持久化线程的,我们可以利用这个持久化服务来做数据的持久化,这样当 redis 重启的时候,即可从硬盘重新读取数据,然后进行数据的恢复。 redis 的持久化方式有两种:

  1. RDB 方式
  2. AOP方式

    RDB 方式

执行过程

redisRDB 持久化是通过快照完成的。当符合一定条件的时候,redis 可以将目前的数据生成一份副本存储在硬盘。 redis 执行快照的一句有下面几种:

  1. 根据配置的规则
  2. 用户执行 SAVEBGSAVE 命令
  3. 执行 FLUSHALL 命令
  4. 执行复制时

配置规则

redis 可以根据用户在配置文件中配置的规则进行定时,定量的持久化。在 redisconf 文件夹中配置如下:

1
2
3
save 900 1 # 表示900秒以内有一个或以上的简直更改时进行快照
save 300 10
save 60 10000
阅读全文 »