雪花算法 & Nginx

雪花算法介绍

SnowFlake 算法,是 Twitter 开源的分布式 id 生成算法。其核心思想就是:使用一个 64 bit 的 long 型的数字作为全局唯一 id

  • 1位,不用。二进制中最高位为1的都是负数,但是生成的id都是正数,所以这个最高位固定是0

  • 41位,用来记录时间戳(毫秒)。

    • 41位可以表示2<sup>41</sup>-1个数字,

    • 如果只用来表示正整数(计算机中正数包含0),可以表示的数值范围是:0 至 2<sup>41</sup> - 1,减1是因为可表示的数值范围是从0开始算的,而不是1。

    • 也就是说41位可以表示2<sup>41</sup> - 1个毫秒的值,转化成单位年则是2<sup>41</sup> - 1 / (1000 * 60 * 60 * 24 * 365) = 69年

  • 10位,用来记录工作机器id。

    • 可以部署在2<sup>10</sup> = 1024个节点,包括5位datacenterId5位workerId

    • 5位(bit)可以表示的最大正整数是2<sup>5</sup> - 1 = 31,即可以用0、1、2、3、....31这32个数字,来表示不同的datecenterId或workerId

  • 12位,序列号,用来记录同毫秒内产生的不同id。

    • 12位(bit)可以表示的最大正整数是2<sup>12</sup> - 1 = 4095,即可以用0、1、2、3、....4095这4096个数字,来表示同一机器同一时间截(毫秒)内产生的4096个ID序号,减1是因为可表示的数值范围是从0开始算的,而不是1。

同一毫秒:0-4095 4096,因为这一毫秒生产的ID数已经满了,因此需要让CPU空转,使得毫秒数增加1,那么此时这一毫秒的ID生成应该从0重新开始

算法实现

java 复制代码
package com.qf.electronic.util;

/**
 * 雪花算法
 */
public class SnowFlake {
    /**
     * 这里需要记录最后一次生成ID的时间,因为同一毫秒内,可能会生成多个ID,记录后可以用来做比对
     */
    private long lastTime = -1L;
    /**
     * 初始时间,因为时间占41位,所以可以从这个时间开始,差不多使用69年
     */
    private long startTime = System.currentTimeMillis();
    /**
     * 机房ID,占5位,因此最多能够对32个机房有效
     */
    private long dataCenterId;
    /**
     * 机器ID,占5位,因此最多能够对32个机器有效
     */
    private long workId;
    /**
     * 序列号,占12位,因此在一毫秒内最多生成2^12 = 4096个序列号
     */
    private long sequence;


    public SnowFlake(long dataCenterId, long workId, long sequence){
        //机房ID最小值为0,最大值为31
        if(dataCenterId > 31 || dataCenterId < 0){
            throw new IllegalArgumentException("机房ID必须>=0且<=31,当前使用机房ID:" + dataCenterId);
        }
        if(workId > 31 || workId < 0){
            throw new IllegalArgumentException("机器ID必须>=0且<=31,当前使用机器ID:" + workId);
        }
        this.dataCenterId = dataCenterId;
        this.workId = workId;
        this.sequence = sequence;
    }

    public long generateId(){
        long time = System.currentTimeMillis(); //获取系统当前时间
        if(time < lastTime){//防止时间回拨,必须手动将时间拨回
            throw new RuntimeException("时间回拨");
        }
        if(time == lastTime){//同一时间段内,生成多个ID
            //按位与操作符所得结果最大值不会超过参与运算的最小操作数,这里不能超过4096
            sequence = (sequence + 1) & 4095;
            if(sequence == 0){//如果计数重新归0,表示该毫秒内,ID生成的数量已满
                //CPU空转1毫秒
                while ((time = System.currentTimeMillis()) == lastTime);
            }
        } else {
            sequence = 0;
        }
        //时间本身占41位,但是需要向左移动22位才能在指定的位置上
        //机房ID占5位,但是需要向左移动17位才能在指定的位置上
        //机器ID占5位,但是需要向左移动12位才能在指定的位置上
        long id = (time - startTime) << 22 | dataCenterId << 17 | workId << 12 | sequence;
        lastTime = time;
        return id;
    }
}

Nginx

1. Nginx是什么

Nginx是一个高性能的基于HTTP的反向代理的服务器、也是一个基于SMTP和POP3的邮件服务器其主要功能就类似于Tomcat,对外提供资源共享

反向代理(Reverse Proxy)是指以代理服务器来接收客户端请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给客户端

反向代理的作用:

  • 保证内网的安全,阻止web攻击,因为客户端是无法感知真正做事的服务器的存在

  • 负载均衡:代理服务器将接收的请求均分给被代理的服务器

2. Nginx能干什么

Nginx既然是服务器,那么其能做的事就是数据共享,具体体现如下:

  • 虚拟主机

    虚拟主机就是虚拟服务器,就跟Java虚拟机差不多,Java虚拟机虽然是虚拟的,但也具备计算机的功能,也能运行。虚拟主机也一样,虽然不存在,但Nginx可以虚拟出来,对外提供服务

  • 反向代理

    前面已经介绍过

  • 负载均衡

    负载就是服务器承载的负荷,所谓均衡指的是多个服务器之间的负荷对比,单个服务器没有均衡的说法。负载均衡就是指多个服务器之间处理的请求数量要大致相同

  • 动静分离

    动指的是资源会变化,比如从服务器获取的数据。

    静指的就是资源不会变化,比如从服务器获取的html、css、js、图片等。

    动静分离指的是动态资源放在服务器上处理,静态资源放在nginx上处理。

3. Nginx的安装及目录说明

演示

4. Nginx配置

nginx的学习也就是配置文件的学习

4.1 虚拟主机配置
java 复制代码
server {
       listen   8888;
       server_name localhost;
       location /{ 
         root d:/demo;
         index index.html;
       }
}
4.2 反向代理配置
java 复制代码
# 以/electronic/开始的请求会被代理到另外的服务器访问
location /electronic/ {
   proxy_pass  http://localhost:9000/;
}
4.3 负载均衡配置
java 复制代码
upstream electronicServer {
    server localhost:9000;
    server localhost:9001;
}
# 以/electronic/开始的请求会被代理到另外的服务器访问
location /electronic/ {
	proxy_pass  http://electronicServer/;
}
  • 负载均衡---轮询

    java 复制代码
    upstream electronicServer {
        server localhost:9000;
        server localhost:9001;
    }
  • 负载均衡---权重

    java 复制代码
    upstream electronicServer {
        server localhost:9000 weight=2; #权重越大,被分配处理的请求越多
        server localhost:9001 weight=1;
    }
  • 负载均衡---ip_hash

    ip_hash就是通过请求的ip地址,使用hash算法,算出来应该访问那一台服务器,如果是ip地址没变,那么这个请求的服务器 就永远都不会变

    java 复制代码
    upstream electronicServer {
        ip_hash; # 负载均衡规则
        server localhost:9000;
        server localhost:9001;
    }
4.4 动静分离

5. 附录: 匹配规则

  • =

    = 开头表示精确匹配

  • ^~

    ^~ 开头 表示uri以某个常规字符串开头,理解为匹配 url路径即可。nginx不对url做编码,因此请求为/static/20%/aa,可以被规则^~ /static/ /aa匹配到(注意是空格)。

  • ~

    ~ 开头表示区分大小写的正则匹配

  • ~*

    ~* 开头表示不区分大小写的正则匹配

  • !~

    !~开头表示区分大小写不匹配

  • !~*

    !~*开头表示不区分大小写不匹配

  • /

    / 通用匹配,任何请求都会匹配到。

相关推荐
劲夫学编程36 分钟前
leetcode:杨辉三角
算法·leetcode·职场和发展
毕竟秋山澪38 分钟前
孤岛的总面积(Dfs C#
算法·深度优先
浮生如梦_3 小时前
Halcon基于laws纹理特征的SVM分类
图像处理·人工智能·算法·支持向量机·计算机视觉·分类·视觉检测
励志成为嵌入式工程师5 小时前
c语言简单编程练习9
c语言·开发语言·算法·vim
捕鲸叉5 小时前
创建线程时传递参数给线程
开发语言·c++·算法
A charmer5 小时前
【C++】vector 类深度解析:探索动态数组的奥秘
开发语言·c++·算法
wheeldown6 小时前
【数据结构】选择排序
数据结构·算法·排序算法
观音山保我别报错7 小时前
C语言扫雷小游戏
c语言·开发语言·算法
TangKenny8 小时前
计算网络信号
java·算法·华为
景鹤8 小时前
【算法】递归+深搜:814.二叉树剪枝
算法