yjiang's cake

斐波那契数列

递归方式

时间复杂度: O(2^n)

function fib($n){
    if( in_array($n, [0, 1]) ) return $n;
    return fib($n-1) + fib($n-2);
}

迭代方式

时间复杂度: O(n), 空间复杂度: O(1)

function fib($n){
    if( in_array($n, [0, 1]) ) return $n;
    $f0 = 0;
    $f1 = 1;
    $f2 = null;
    for($i=0; $i<$n; $i++){
        $f2 = $f0 + $f1;
        $f0 = $f1;
        $f1 = $f2;
    }
    return $f2;
}

随机算法

带权重的随机算法

function roll($arr){

    //获取数组中所有值的和
    $count = array_sum($arr);
    $rand = 0;

    foreach($arr as $k => $v){
        $rand = mt_rand(1, $count);
        if( $rand <= $v){
            return $k;
        }
        else{
            $rand -= $v;
        }
    }
}

$array = ['a' => 5, 'b' => 3, 'c' => 1];
echo roll($array);

洗牌算法


function poker($array){
    $count = count($array);

    for($i=0; $i<$count; $i++){
      $rand = rand(200, 300);
      $index = $rand % $count;
      $tmp = $array[$i];
      $array[$i] = $array[$index];
      $array[$index] = $tmp;
    }
    return $array;
}

$array = array('a', 'b', 'c', 'd', 'e', 'f', 'g');
print_r( poker($array) );

单项链表操作



<?php
class Node {
    public $data;
    public $next;
    public function __construct($data=null, $next=null){
        $this->data = $data;
        $this->next = $next;
    }
}

class Link {
    public $head=null;
    public $size=0;

    public function __construct(){
        //$this->head = new Node();
    }

    //遍历
    public function traverse(){
        //当前指针位置移动到头部
        $curIndex = $this->head;
        $tmp = [];
        //移动指针一直到没有数据位置
        while( !is_null($curIndex) ){
            array_push($tmp, $curIndex->data);
            //移动指针到当前的下一个节点
            $curIndex = $curIndex->next;
        }
        return $tmp;
    }

    //头插
    public function addAtHead($data){
        $node = new Node($data, $this->head);
        $this->head = $node;
        $this->size++;
        return $this;
    }

    //尾插
    public function addAtTail($data){
        $node = new Node($data);
        $curIndex = $this->head;
        //判断当前链表是否为空
        if( is_null($curIndex) ){
            $this->head = $node;
        }
        else{
            //如果链表不为空,则进行遍历
            while( !is_null($curIndex->next) ){
                $curIndex = $curIndex->next;
            }
            $curIndex->next = $node;
        }
        $this->size++;
        return $this;
    }

    public function addAtIndex($data, $index){
        //判断index是头尾的情况
        $count = $this->size;
        if( $index <= 0 ){
            $this->addAtHead($data);
        }
        if( $index > $count ){
            $this->addAtTail($data);
        }

        //将指针移动到index-1的位置
        $curIndex = $this->head;
        for($i=0;$i<$index-1;$i++){
            $curIndex = $curIndex->next;
        }

        //新建一个节点,其next是index之后的链表
        $node = new Node($data, $curIndex->next);
        $curIndex->next = $node;

        $this->size++;
        return $this;
    }

    public function delAtIndex($index){
        $count = $this->size;
        $curIndex = $this->head;
        //如果删除的是第一个节点
        if( $index == 0 ){
            $this->head = $curIndex->next;
            $this->size--;
            return $this;
        }
        //如果删除的是最后一个节点
        if( $index < 0 || $index > $count ){
            echo "没有这个节点\n";
            return $this;
        }

        //将指针移到index-1的位置
        for($i=0;$i<$index-1;$i++){
            $curIndex = $curIndex->next;
        }
        //echo "<pre>"; print_r($curIndex);exit;
        //此时,curIndex->next所处的位置,也就是index
        //将从index开始的链表赋给tmp(tmp所处的位置 = index+2)
        $tmp = $curIndex->next;

        //index+2后的链表赋值跟index
        $curIndex->next = $tmp->next;
        $this->size--;

        return $this;
    }

    public function print(){
        print_r( $this );
    }
}

$link = new Link;
$link->addAtHead(3)
     ->addAtHead(2)
     ->addAtHead(1)
     ->addAtTail(8)
     ->addAtTail(4)
     ->addAtTail(5)
     ->addAtIndex(10, 3)
     ->delAtIndex(2)
     ->print();
//$res = $link->traverse();
//$size = $link->size;
//echo "{$size}<pre>"; print_r($res);exit;

使用haproxy加速ssr

场景

  • 一台非直连cn的vps, 搭建了ssr
  • 一台内网可运行haproxy的机器
  • 家里联通线路访问ssr速度尚可
  • 公司/非联通线路访问ssr速度不佳

方案

  • 在家里路由器搭建haproxy, 使用haproxy反代ssr:
公司 <===> 家里(haproxy) <===> VPS

安装及haproxy配置

1.安装haproxy

此处使用entware-ng环境运行haproxy,需要根据实际情况自行安装haproxy

opkg update && opkg install haproxy

2.创建配置文件ssr.cfg

global
    #ulimit-n  51200
    log /dev/log    local0
    log /dev/log    local1 notice
    chroot /root
    pidfile /tmp/var/run/haproxy.pid
    user yjiang                      #自己运行haproxy的用户
    daemon                           #以后台形式运行haproxy
defaults
    log     global
    mode    tcp
    option  dontlognull
    option redispatch
    timeout http-request 10s
    timeout queue 1m
    timeout connect 2s
    timeout http-keep-alive 10s
    timeout check 10s
    timeout client 50000
    timeout server 50000
listen ssr
    bind *:9988                      #反代后ssr的端口
    mode tcp
    server ssr1 yjiang.cn:9988       #自己的ssr服务器及端口

3.启动haproxy

haproxy -f ssr.cfg

梅林固件User Script脚本创建方式

tips

  1. 可能需要手动开放haproxy绑定的端口, 例如上面配置文件需要开启9988
iptables -I INPUT -p tcp --dport 9988 -j ACCEPT
iptables-save
  1. 1024以内的端口是需要root权限的
  2. 从公司连接haproxy反代后的ssr服务时, 依旧需要vps上ssr服务的用户名/密码/加密协议.

记一次 redis 内存异常排查

    #各种类型的key所占比例
    redis-cli  --bigkeys

654556F2-22A7-4DF3-B1C6-6854D444743B.png

上图可看出, string 类型的key占了近93%

dbsize 查看key总量

randomkey 所占比例较多的key, 随机返回的几率也较大

E0066839244E634E2662E3C48981C753.jpg

  1. 几次randomkey都返回前缀c:s:i的, 可以确定比例肯定很大
  2. keys c:s:i* 查看数量, 确定问题所在key
  3. 确定key以后, 找到相关逻辑, 定位问题

Copyright © 2016 yjiang's cake

返回顶部