API设计需要注意的三点

登录验证:非对称加密;生成一对公私钥,将公用给客户进行数据加密,然后服务端用私钥解密。

数据防篡改:MD5摘要,对提交表单数据,进行MD5加密,并将加密后的值一起传递给服服务端,服务端用相同的算法进行md5密码验证

数据泄露:令牌机制 token,登录后服务气器返回一个token,以后的所有请求都必须携带该token。类似于auth2验证

搭建kafka集群

  1. 准备三台服务器,以下是我准备的服务器ip:172.16.11.196,172.16.11.197,172.16.11.198
  2. 从apache下载kafka的安装包,并解压
    curl -O http://mirrors.hust.edu.cn/apache/kafka/1.0.0/kafka_2.11-1.0.0.tgz
    tar -xzf kafka_2.11-1.0.0.tgz
    cd kafka_2.11-1.0.0.tgz
  3.  编辑kafka的配置文件server.properties
    vim config/server.properties
    #主要修改以下几个参数
    broker.id=1
    listeners=PLAINTEXT://172.16.11.196:9092
    log.dirs=/opt/kafka/data
    zookeeper.connect=172.16.11.196:2181,172.16.11.197:2181,172.16.11.198:2181
  4. 启动集群,确保已经启动zookeeper服务
    bin/kafka-server-start.sh -daemon config/server.properties 
    
  5. 创建topic
    #指定5个分区 2个副本
    bin/kafka-topics.sh --create --topic test --replication-factor 2 --partitions 5 --zookeeper 172.16.11.196:2181
    

     

布隆过滤器(BloomFilter)

Bloom Filter概念和原理

布隆过滤器(Bloom Filter)详解

 

Bloom filter 是由 Howard Bloom 在 1970 年提出的二进制向量数据结构,它具有很好的空间和时间效率,被用来检测一个元素是不是集合中的一个成员。如果检测结果为是,该元素不一定在集合中;但如果检测结果为否,该元素一定不在集合中。因此Bloom filter具有100%的召回率。这样每个检测请求返回有“在集合内(可能错误)”和“不在集合内(绝对不在集合内)”两种情况,可见 Bloom filter 是牺牲了正确率和时间以节省空间。

可用于解决缓存穿透问题

创建hadoop集群

  1. 准备三台机器,能相互访问,配置/etc/hosts
    192.168.0.1    master
    192.168.0.2    slave1
    192.168.0.3    slave2
  2. 安装,配置java环境
  3. 创建hadoop用户
    sudo addgroup hadoop
    sudo adduser --ingroup hadoop hduser
  4. 配置ssh
    su - hduser
    ssh-keygen -t rsa -P ""
    cat $HOME/.ssh/id_rsa.pub >> $HOME/.ssh/authorized_keys
    ssh localhost
  5. 下载hadoop的压缩包:http://hadoop.apache.org/releases.html
  6. 安装
    cd /usr/local
    sudo tar xzf hadoop-2.8.2.tar.gz
    sudo mv hadoop-2.8.2 hadoop
    sudo chown -R hduser:hadoop hadoop
  7. 更新$HOME/.bashrc,可能需要安装lzop(apt-get install lzop)
    export HADOOP_HOME=/usr/local/hadoop
    export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64
    unalias fs &> /dev/null
    alias fs="hadoop fs"
    unalias hls &> /dev/null
    alias hls="fs -ls"
    lzohead () {
        hadoop fs -cat $1 | lzop -dc | head -1000 | less
    }
    export PATH=$PATH:$HADOOP_HOME/bin
  8. 配置/usr/local/hadoop/etc/hadoop/hadoop-env.sh
    export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64
  9. 创建数据存放位置
    sudo mkdir -p /app/hadoop/tmp
    sudo chown hduser:hadoop /app/hadoop/tmp
    sudo chmod 750 /app/hadoop/tmp
  10. 配置/usr/local/hadoop/etc/hadoop/core-site.xml
    <property>
      <name>hadoop.tmp.dir</name>
      <value>/app/hadoop/tmp</value>
      <description>A base for other temporary directories.</description>
    </property>
    
    <property>
      <name>fs.default.name</name>
      <value>hdfs://master:54310</value>
      <description>The name of the default file system.  A URI whose
      scheme and authority determine the FileSystem implementation.  The
      uri's scheme determines the config property (fs.SCHEME.impl) naming
      the FileSystem implementation class.  The uri's authority is used to
      determine the host, port, etc. for a filesystem.</description>
    </property>
  11. 配置/usr/local/hadoop/etc/hadoop/mapred-site.xml
    <property>
      <name>mapred.job.tracker</name>
      <value>master:54311</value>
      <description>The host and port that the MapReduce job tracker runs
      at.  If "local", then jobs are run in-process as a single map
      and reduce task.
      </description>
    </property>
  12. 配置/usr/local/hadoop/etc/hadoop//hdfs-site.xml
    <property>
      <name>dfs.replication</name>
      <value>3</value>
      <description>Default block replication.
      The actual number of replications can be specified when the file is created.
      The default is used if replication is not specified in create time.
      </description>
    </property>
  13. 配置master与slave的连接(master only)
    ssh-copy-id -i $HOME/.ssh/id_rsa.pub hduser@slave1
    ssh-copy-id -i $HOME/.ssh/id_rsa.pub hduser@slave2
  14. 测试连接
    ssh master
    ssh slave1
    ssh slave2
    
  15. 增加masters文件写入master,(master only)
    /usr/local/hadoop/etc/hadoop/
    touch masters
  16. 修改slaves文件(master only)
    master
    slave1
    slave2
  17. 格式化文件系统(master only)
    hadoop namenode -format
  18. 启动
    cd /usr/local/hadoop/sbin
    ./start-dfs.sh
    ./start-mapred.sh
  19. web查看允许状态192.168.0.1:50070
    jps
  20. 停止
    ./stop-dfs.sh

参考:

部署单个节点

部署集群

一致性哈希Java实现

import java.util.Collection;
import java.util.SortedMap;
import java.util.TreeMap;

import com.google.common.hash.HashCode;
import com.google.common.hash.HashFunction;

public class ConsistentHash<T> {
    private final HashFunction hashFunction;
    private final int numberOfReplicas;
    private final SortedMap<Integer, T> circle = new TreeMap<Integer, T>();

    public ConsistentHash(HashFunction hashFunction, int numberOfReplicas, Collection<T> nodes) {
        this.hashFunction = hashFunction;
        this.numberOfReplicas = numberOfReplicas;

        for (T node : nodes) {
            add(node);
        }
    }

    private HashCode getHashCode(T node, int i) {
        return hashFunction.hashUnencodedChars(String.format("%s%s", node.toString(), i));
    }

    public void add(T node) {
        for (int i = 0; i < numberOfReplicas; i++) {
            circle.put(getHashCode(node, i).asInt(), node);
        }
    }

    public void remove(T node) {
        for (int i = 0; i < numberOfReplicas; i++) {
            circle.remove(getHashCode(node, i).asInt());
        }
    }

    public T get(Object key) {
        if (circle.isEmpty()) {
            return null;
        }
        int hash = hashFunction.hashUnencodedChars(key.toString()).asInt();
        if (!circle.containsKey(hash)) {
            SortedMap<Integer, T> tailMap = circle.tailMap(hash);
            hash = tailMap.isEmpty() ? circle.firstKey() : tailMap.firstKey();
        }
        return circle.get(hash);
    }

}

 

Redis安装以及集群配置

一、Redis安装

  1. 首先上官网下载Redis 压缩包,地址:http://redis.io/download 下载稳定版4.0.2即可。
  2. 下载、解压、编译,编译安装报错 error: jemalloc/jemalloc.h: No such file or directory解决方法:make MALLOC=libc
    wget http://download.redis.io/releases/redis-4.0.2.tar.gz
    tar xzf redis-4.0.2.tar.gz
    cd redis-4.0.2
    make
  3. 编译成功后,进入src文件夹,执行make install进行Redis安装。

二、Redis部署

  1. 为了方便管理,将Redis文件中的conf配置文件和常用命令移动到统一文件中
    mkdir -p /usr/local/redis/bin
    mv redis-server redis-sentinel redis-cli redis-benchmark redis-check-rdb redis-check-aof /usr/local/redis/bin/
  2. 将Redis的命令加入到PATH中
    vim ~/.bashrc 
    #在文件的末尾:
    export PATH=/usr/local/redis/bin:$PATH
    #保存后执行:
    source ~/.bashrc
  3. 直接执行redis-server 启动的Redis服务,执行完该命令后,如果Lunix关闭当前会话,则Redis服务也随即关闭。正常情况下,启动Redis服务需要从后台启动,并且指定启动配置文件。
  4. 复制redis.conf文件到目录中,并编辑redis.conf文件
    daemonize yes
    bind 172.16.11.2
    pidfile /opt/redis/redis4/redis_6379.pid
    logfile "redis.log"
    #修改作为slave的redis配置文件,指向master的ip和端口
    slaveof 172.16.11.1 6379
  5. 启动redis服务,执行:redis-server redis.conf
  6. 通过客户端连接,执行: redis-cli -h 172.16.11.1 -p 6379

三、高可用的哨兵方案配置

 

四、集群配置

  1. 修改redis.conf配置文件
    cluster-enabled yes
    cluster-config-file nodes-6379.conf
    cluster-node-timeout 5000
  2. 启动各个实例
    redis-server redis.conf
  3. 创建集群,在其中一台实例中执行
    apt-get install ruby
    gem install redis #版本不重要
    redis-trib.rb create --replicas 1 172.16.11.1:6379 172.16.11.1:6380 172.16.11.2:6379 172.16.11.2:6380 172.16.11.3:6379 172.16.11.3:6380
  4. 通过客户端链接
    redis-cli -h 172.16.11.1 -p 6379 -c
  5. Jedis客户端代码
    @Test
    public void testCluster() throws IOException {
        Set<HostAndPort> set = new HashSet<HostAndPort>();
        set.add(new HostAndPort("172.16.11.1", 6379));
        set.add(new HostAndPort("172.16.11.1", 6380));
        set.add(new HostAndPort("172.16.11.2", 6379));
        set.add(new HostAndPort("172.16.11.2", 6380));
        set.add(new HostAndPort("172.16.11.3", 6379));
        set.add(new HostAndPort("172.16.11.3", 6380));
        JedisCluster cluster = new JedisCluster(set);
        cluster.set("name","hello");
        System.out.println(cluster.get("name"));
        cluster.close();
    }

五、注意事项

  1. slave不提供写操作,只提供读取操作
  2. slave在于master同步时,会阻塞

docker运行mysql主从备份,读写分离

  1. 从store.docker.com获取mysql镜像
    docker pull mysql
  2. 添加mysql目录
    mkdir /opt/mysql
    mkdir /opt/mysql/data
    mkdir /opt/mysql/conf
  3. 设置主从配置,server-id分别设置为1、2
    vim /opt/mysql/conf/m.conf
    
    [mysqld]
    log-bin=mysql-bin
    server-id=1
  4. 在/opt/mysql文件夹下创建docker-compose.yml文件
    version: '2'
    
    services:
    
      mysql:
        image: mysql
        volumes:
            - /opt/mysql/data:/var/lib/mysql
            - /opt/mysql/conf:/etc/mysql/conf.d
        environment:
          MYSQL_ROOT_PASSWORD: 123456
        ports:
          - 3306:3306     
      
      adminer:
        image: adminer
        ports:
          - 8099:8080
  5. 启动服务
    docker-compose -f docker-compose.yml up -d
  6. 访问172.16.11.1:8099连接主库,创建一个用户用来同步数据
    GRANT REPLICATION SLAVE ON *.* to 'backup'@'%' identified by '123456';
  7. 查看主库状态,记住File和Position,如:mysql-bin.000004、312
    show master status;
  8. 连接到从库,设置主库链接
    change master to master_host='172.16.11.1',master_user='backup',master_password='123456',master_log_file='mysql-bin.000004',master_log_pos=312,master_port=3306;
  9. 启动同步
    start slave;
  10. 查看同步状态,如果看到Waiting for master to send event,就成功了,你现在在主库上的修改,都会同步到从库上
    show slave status

电子书下载网站

名称
网址
说明
脚本之家 http://www.jb51.net/books/ 主要是中文的扫描版PDF
CSDN http://download.csdn.net/
Fox ebook http://www.foxebook.net/ 文字版的英文图书,可以下载但比较麻烦
Avax https://avxhm.se/ebooks/programming_development 文字版的英文图书
Salttiger https://salttiger.com/ 文字版的英文图书,下载方便

Linux SWAP 配置概要说明

SWAP 简介

Linux 中的 SWAP(交换分区),类似于 Windows 的虚拟内存。系统会把一部分硬盘空间虚拟成内存使用,将系统内非活动内存换页到 SWAP,以提高系统可用内存。

开启 SWAP

1、创建用于交换分区的文件:dd if=/dev/zero of=/mnt/swap bs=1M count=1024

2、设置交换分区文件:mkswap /mnt/swap

3、立即启用交换分区文件:swapon /mnt/swap

4、设置开机时自启用 SWAP 分区:需要修改文件 /etc/fstab 中的 SWAP 行,添加/mnt/swap swap swap defaults 0 0

5、修改 swpapiness 参数:echo 10 >/proc/sys/vm/swappiness

vim /etc/sysctl.conf

vm.swappiness=10

sysctl -p

关闭SWAP

使用命令 swapoff 关闭 SWAP,比如:swapoff /mnt/swap
3、修改 /etc/fstab 文件,删除或注释相关配置,取消 SWAP 的自动挂载: