2018年5月

正则表达式中需要转义的特殊字符

$    匹配输入字符串的结尾位置。如果设置了 RegExp 对象的 Multiline 属性,则 $ 也匹配 ‘\n' 或 ‘\r'。要匹配 $ 字符本身,请使用 \$

( )  标记一个子表达式的开始和结束位置。子表达式可以获取供以后使用。要匹配这些字符,请使用 和

*    匹配前面的子表达式零次或多次。要匹配 * 字符,请使用 \*

+    匹配前面的子表达式一次或多次。要匹配 + 字符,请使用 \+

.    匹配除换行符 \n之外的任何单字符。要匹配 .,请使用 \

[ ]  标记一个中括号表达式的开始。要匹配 [,请使用 \[

?    匹配前面的子表达式零次或一次,或指明一个非贪婪限定符。要匹配 ? 字符,请使用 \?

\    将下一个字符标记为或特殊字符、或原义字符、或向后引用、或八进制转义符。例如, ‘n' 匹配字符 ‘n'。'\n' 匹配换行符。序列 ‘\\' 匹配 “\”,而 ‘\(' 则匹配 “(”

^    匹配输入字符串的开始位置,除非在方括号表达式中使用,此时它表示不接受该字符集合。要匹配 ^ 字符本身,请使用 \^

{ }  标记限定符表达式的开始。要匹配 {,请使用 \{

|    指明两项之间的一个选择。要匹配 |,请使用 \|

css3二维码扫描动画效果

<!DOCTYPE HTML>
<html lang="en-US">
<head>
    <meta charset="UTF-8">
    <title>css3二维码扫描动画效果</title>
    <style type="text/css">
        .scan-box{
            width: 200px;
            height: 200px;
            background: url('http://project.icphp.com/assets/images/icecry613.jpg');
        }
        .scan{
            animation-name: saoma;
            -webkit-animation-name: saoma;
            animation-duration: 5s;
            -webkit-animation-duration: 5s;
            animation-timing-function: linear;
            -webkit-animation-timing-function: linear;
            -webkit-animation-iteration-count: infinite;
            animation-iteration-count: infinite;

            width: 200px;
            height: 200px;
            position: absolute;
            top: -225px;
            background: rgba(26, 132, 190, 0.3);
            border-bottom: 3px solid #4AB86A;
        }
        @keyframes saoma{0%{top:-205px;}100%{top:0;}}
        @-webkit-keyframes saoma{0%{top:-205px;}100%{top:0;}}
        @-moz-keyframes saoma{0%{top:-205px;}100%{top:0;}}
    </style>
</head>
<body>
    <div class="scan-box">
        <div class="scan"></div>
    </div>
</body>
</html>

redis入门整理

启动redis
redis-server [redis.conf]
默认情况,redis-server以非daemon方式运行(如需后台进程运行,更改为daemonize yes),默认端口6379


停止redis
1. redis-cli shutdown
2. redis-cli -p xxxx shutdown 非6379默认端口需指定端口号

备份redis
1. save 生成dump.rdb备份
2. 设置从节点,定时启动、同步、停止

使用redis
redis-cli -h x.x.x.x -p 6379 -a password

redis支持的写指令
set setnx setex append
incr decr rpush lpush rpushx lpushx linsert lset rpoplpush sadd
sinter sinterstore sunion sunionstore sdiff sdiffstore zadd zincrby
zunionstore zinterstore hset hsetnx hmset hincrby incrby decrby
getset mset msetnx exec sort

redis数据结构
1. 字符串 strings
2. 字符串列表 lists
3. 字符串集合 sets
4. 有序字符串集合 sorted sets
5. 哈希 hashes

key设置
1. key长度尽量不超过1024,避免内存消耗、降低查询效率
2. 一个项目中,最好使用统一命名模式,提高可读性

strings
    set num "2"
    incr num //redis将字符串转换为数值,原子性

lists
    消息队列
    LRANGE实现分页
    文章评论存放单独list中

sets
    无序集合
    sadd|smembers|sismembers|sunion

sorted sets | zsets

    有序集合
    zrange|zadd|zrevrange|zrangebyscore
    add myzset 1 baidu.com #score值为1
    zrange myzset 0 -1 [with scores]

hashes
    哈希
    哈希存储字符串和字符串值之间的映射
    HMSET user:001 username hitortoise password helloworld age 30
    HGETALL user:001
    HSET user:001 password 12345 #修改

redis持久化
    1. RDB Redis DataBase 不同时间点将redis存储的数据生成快照并存储到磁盘等介质
    2. AOF Append Only File 记录redis指令,重启redis时重复执行已记录指令,只允许追加不允许改写的文件
    3. 如同时使用RDB AOF 则redis重启优先采用AOF恢复数据,数据恢复完整度高

RDB
    1. redis进行持久化过程中会先将数据写入到一个临时文件,待持久化结束才会将临时文件替换上次持久化好的文件,确保快照文件完整可用;
    2. redis单独创建(fork)一个子进程进行持久化,主进程不会进行任何IO操作,确保redis高性能;
    3. 如进行大规模数据恢复,且对完整性不是很敏感,RDB比AOF更高效;
    4. 即使每5分钟持久化一次,当redis故障时,仍有近5分钟数据丢失;

AOF
    1. 通过配置redis.conf中 `appendonly yes` 开启AOF功能;
    2. 默认AOF持久化策略为每秒钟fsync一次,即每秒将缓存中的指令记录到磁盘;
    3. 如追加日志恰好遇到磁盘满、inode满或断电灯情况导致日志写入不完整,redis提供redis-check-aof工具进行修复;
    4. 重写机制:AOF文件大小超过所设定的阈值时,redis启动AOF内容压缩,只保留可以恢复数据的最小指令集。如调用100次INCR指令需存储100条指令,完全可将100条指令合并成一条SET指令;
    5. AOF重写时采用先写临时文件,全部完成后替换的流程,确保断电、磁盘满等问题不影响AOF文件可用性;
    6. 如误操作FLUSHALL导致redis内存中数据清空,在AOF文件未被重写则可以最快的速度暂定redis并编辑AOF文件,删除FLUSH命令,重启redis,如AOF已重写,则无法通过该方式恢复数据;
    7. 同数据量规模,AOF文件大于RDB且AOF文件恢复速度慢于RDB;
    8. `BGREWRITEAOF`命令生成最优可恢复当前数据的命令集,如AOF文件写坏,redis无法加载报错退出。通过【备份被写坏的AOF文件->运行redis-check-aof-fix修复->用diff -u查看两文件差异确认问题->重启redis加载修复后AOF文件】;
    
    AOF重写流程
        a. AOF重写时fork‘重写子进程’,该进程首先读取现有AOF文件,并将其包含指令压缩写入临时文件;
        b. 与此同时,主进程会将新接收到的写指令一边积累到内存缓冲区,一边继续写入原有的AOF文件中,确保原有AOF文件可用性;
        c. 当‘重写子进程’完成重写后会给父进程发信号,父进程将内存中缓存的写指令追加到新AOF文件中;
        d. 追加完毕,覆盖;

AOF or RDB
    官方建议同时使用更可靠

redis主从
    1. 主从结构:冗余备份、提升读性能,如很耗性能的SORT就可由从服务器承担;
    2. redis主从同步是异步进行的,不影响主逻辑,不会降低redis处理能力;
    3. 主从架构中可考虑关闭主服务器持久化,仅从服务器进行持久化操作;
    4. 主从架构中从服务器通常被设置为只读模式,避免从服务器数据被误修改。但从服务器仍可接收CONFIG等指令,所以不应该将从服务器直接暴露到不安全的网络中。如必须如此,可考虑给重要指令进行重命名,避免命令被外人执行;

    主从同步原理
        a. 从服务器向主服务器发出SYNC指令,主服务器调用BGSAVE指令创建一个子进程专门进行数据持久化工作,将主服务器数据写入RDB文件。数据持久化期间,主服务器将执行的写指令缓存在内存中;
        b. BGSAVE指令完成后,主服务器将持久化好的RDB文件发送给从服务器,从服务器将文件存储到磁盘再读取到内存中。这个动作完成后,主服务器会将这段时间缓存的写指令再以redis协议的格式发送给从服务器;
        c. 如多个从服务器发送SYNC指令,主服务器也只会执行一次BGSAVE然后分发下游。如主从意外断开,2.8之后版本支持增量同步策略;
        d. 主服务器会在内存中维护一个缓冲区,缓冲区中存储着将要发给从服务器的内容。从服务器与主服务器出现网络瞬断后,从服务器会再次尝试与主服务器连接,一旦连接成功,从服务器就会把“希望同步的主服务器ID”和“希望请求的数据偏移的位置(replication offset)”发送出去。主服务器接收到这样的同步请求后,首先会验证主服务器ID是否和自己的ID匹配,其次会检查“请求的偏移位置”是否存在于自己的缓冲区中,如果两者都满足,主服务器就会向从服务器发送增量内容(增量同步功能,需要服务器端支持全新的PSYNC指令 >redis-2.8)。

redis事务
    MULTI 组装事务
    EXEC 执行事务
    DISCARD 取消事务
    WATCH 用来监视一些key,一旦这些key在事务执行前被改变,则取消事务执行

    如果开启AOF,事务一旦成功执行,事务中命令就会通过write命令一次性写入到磁盘中,如果写入过程中出现断电、硬件故障将可能导致只有部分命令进行AOF,从而出现不完整,此时可通过redis-check-aof工具移除不完整信息,确保AOF可用;

    事务错误:
    a. 调用EXEC之前的错误(可能语法错误或内存不足导致)
        >multi
        >hah #明显错误
        >exec #无法执行
    b. 调用EXEC之后的错误(redis忽略错误继续执行)
        >multi
        >set age 20
        >sadd age 15 #age非集合,错误
        >set age 30
        >exec #正常执行age=30

    WATCH
    类似“乐观锁”,即CAS check and set;
    监视key是否被改动过,支持同时监视多个key,只要没触发事务,一旦key改动则执行EXEC则返回nil,表示事务无法触发;
    >set age 20
    >watch age
    >set age 30 #在EXEC之前 age的值被修改
    >multi
    >set age 40
    >get age
    >exec #无法执行

redis.conf配置
    1. 启动redis指定加载的配置 redis-server /path/redis.conf
    2. redis配置不区分大小写,redis只支持bytes,不支持bit单位
    3. 支持主配置文件引入外部配置文件 include /path/to/other.conf
    4. 配置
        a. 通用(general)
        b. 快照(snapshotting)
        c. 复制(replication)
        d. 安全(security)
        e. 限制(limits)
        f. 追加模式(append only mode)
        g. LUA脚本(lua scripting)
        h. 慢日志(slow log)
        i. 事件通知(event notification)

    a. 通用
        `daemonize no` 若以daemon运行redis会生成一个pid文件,默认会生成在/var/run/redis.pid,也可以通过pidfile来指定pid文件生成的位置,当运行多个redis服务时,需要指定不同的pid文件和端口;
        `bind 192.168.1.2 10.8.4.2` 默认情况下,redis会响应本机所有可用网卡的连接请求,在生产环境中最好设置127.0.0.1;
        `port 6379` 如果端口设置为0的话,redis便不会监听端口;
        `unixsocket /tmp/redis.sock` `unixsocketperm 755` redis还支持通过unix socket方式来接收请求;
        `timeout 0` timeout来设置“空闲超时时限”,0表示永不关闭;
        `tcp-keepalive 0` TCP连接保活策略,单位为秒,规定时间向连接空闲的客户端发起ACK请求,检测是否挂掉,0为不进行保活检测;
        `loglevel notice` 日志等级共分四级,即
            debug 记录很多信息,用于开发和测试
            verbose 精简的有用信息
            notice 普通的verbose,常用于生产环境
            warning 只有非常重要或者严重的信息会记录到日志
        `logfile ""` 设置日志文件的生成位置,设置为空字符串,则redis会将日志输出到标准输出;
        `syslog-enabled` 日志打印到syslog中;
        `syslog-ident redis` 指定syslog里的日志标志;
        `syslog-facility local0` syslog设备,值可以是USER或LOCAL0-LOCAL7;
        `databases 16` 设置其数据库的总数量,默认编号为0,使用select DBid来选择相应的数据库;

    b. 快照
        快照主要涉及redis的RDB持久化配置
        `save <seconds> <changes>` 每seconds秒且至少有changes个key改变则触发一次持久化;
        `save ""` 为空或不设置则禁用RDB持久化
        `stop-writes-on-bgsave-error yes` 默认RDB持久化出错则redis停止所有写请求(如下次持久化成功则恢复写请求),便于用户识别内存数据与磁盘数据不一致,如设yes则强制写入;
        `rdbcompression yes` 磁盘快照启用压缩;
        `rdbchecksum yes` 存储快照后让redis使用CRC64算法来进行数据校验,大约带来10%性能消耗;
        `dbfilename dump.rdb` 自定义快照名称;
        `dir /path/` 自定义路径;

    c. 复制
        redis提供了主从同步功能
        `slaveof <masterip> <masterport>` 从服务器配置主服务器ip及端口,一般
        `masterauth <master-password>` 如主服务器设置密码,则从redis的配置中要使用masterauth来设置校验密码;

        从服务器失去与主服务器连接或主从同步正在进行中,redis该如何处理外部发来的访问请求?
            (1) `slave-serve-stale-data yes` 则redis仍会继续响应客户端的读写请求;
            (2) `slave-serve-stale-data no` 则redis会对客户请求返回“SYNC with master in progress”,当客户端发来INFO请求和SLAVEOF请求则redis仍会处理;
        `slave-read-only yes` 从服务器只读;
        `rename-command CONFIG b840fc02d524045429941cc15f59e41cb7be6c52` 从reids为降低暴露给不可信的客户端,为降低风险,使用rename-command指令将一些可能有破坏力的命令重命名,避免外部直接调用;
        `repl-ping-slave-period 10` 从redis周期性的向主redis发出PING包,默认10s;

        `repl-timeout 60` 超时时间,需大于repl-ping-slave-period;
        主从同步时,可能发生超时
            (1) 以从redis的角度来看,当有大规模IO传输时;
            (2) 以从redis的角度来看,当数据传输或PING时,主redis超时;
            (3) 以主redis的角度来看,在回复从redis的PING时,从redis超时;

        `repl-disable-tcp-nodelay no` 如果开启TCP_NODELAY,那么主redis会使用更少的TCP包和更少的带宽来向从redis传输数据。但是这可能会增加一些同步的延迟,大概会达到40毫秒左右。如果你关闭了TCP_NODELAY,那么数据同步的延迟时间会降低,但是会消耗更多的带宽;
        `repl-backlog-size 1mb` 同步队列长度,主从端口主服务器用该缓冲区缓存指令,等连接后增量写入;
        `repl-backlog-ttl 3600` 主从断开最大等待时间,到时间后缓冲区清空,0为不清空;
        `slave-priority 100` 从redis优先级,主redis出错,优先级数字越小的从redis优先替代主redis,0永远不会被选中;
        `min-slaves-to-write 3`
        `min-slaves-max-lag 10` 如主redis发现超过min-slaves-to-write个从redis连接延迟min-slaves-max-lag秒,则主redis停止接收外来写请求,如果其中一个设为0则表示禁用;

    d. 安全
        `requirepass zhimakaimen` 每秒可达15万次的密码尝试,密码需足够复杂;
        `rename-command CONFIG b840fc02d524045429941cc15f59e41cb7be6c89`
        `rename-command CONFIG ""` 禁用CONFIG命令
        如果使用AOF方式进行数据持久化,或者需要与从redis进行通信,那么更改指令的名字可能会引起一些问题。

    e. 限制
        `maxclients 10000` 设置redis同时可以与多少个客户端进行连接;
        `maxmemory <bytes>` redis可使用的内存量,一旦达到使用上限,redis尝试移除内部数据,移除规则通过maxmemory-policy来指定。如果redis无法根据规则移除内存中数据或设置了禁止移除,则redis会针对那些需要申请内存的指令返回错误,无内存申请的如GET仍正常响应;

        `maxmemory-policy volatile-lru` 内存移除规则
        redis提供了多达6种的移除规则:
            (1) volatile-lru:使用LRU算法移除过期集合中的key
            (2) allkeys-lru:使用LRU算法移除key
            (3) volatile-random:在过期集合中移除随机的key
            (4) allkeys-random:移除随机的key
            (5) volatile-ttl:移除那些TTL值最小的key,即那些最近才过期的key。
            (6) noeviction:不进行移除。针对写操作,只是返回错误信息。

            无论使用上述哪一种移除规则,如果没有合适的key可以移除的话,redis都会针对写请求返回错误信息。

        `maxmemory-samples 3` LRU算法和最小TTL算法都并非是精确的算法,而是估算值,可以设置样本的大小。假如redis默认会检查三个key并选择其中LRU的那个,那么你可以改变这个key样本的数量。


    f. 追加模式
        `appendonly no`
        `appendfsync everysec`
        redis支持三种不同的模式:
            (1) no:不调用fsync()。操作系统自行决定sync的时间。这种模式下,redis的性能会最快。
            (2) always:在每次写请求后都调用fsync()。这种模式下,redis会相对较慢,但数据最安全。
            (3) everysec:每秒钟调用一次fsync()。这是性能和安全的折衷。
        
        `appendfilename "appendonly.aof"`
        `no-appendfsync-on-rewrite no`

        `auto-aof-rewrite-percentage 100` redis基准值与当前AOF文件大小增长比例,大于则触发重写,设为0则关闭重写功能;
        `auto-aof-rewrite-min-size 64mb` redis自动重写AOF触发最小值;

LUA脚本
    `lua-time-limit 5000` LUA最大运行时间 ms,设为0或负值则无限制;

慢日志
    指日志查询超过指定时长,不包括IO操作,仅包含实际执行命令查询时间;
    `slowlog-log-slower-than 10000` 执行时长,单位微秒,负值为禁止慢查询,0表示强制记录每一个命令;
    `slowlog-max-len 128` 慢查询日志最大长度,可用SLOWLOG RESET重置;

事件通知

高级配置

lnmp MySQL5.7.18 重置 root 密码

1、修改 /etc/my.cnf,在 [mysqld] 小节下添加一行:skip-grant-tables=1
2、重启 mysqld 服务:systemctl restart mysqld
3、使用 root 用户登录到 mysql -u root
4、切换到mysql数据库,更新 user 表:
update user set authentication_string = password('root'), password_expired = 'N', password_last_changed = now() where user = 'root';
在之前的版本中,密码字段的字段名是 password,5.7版本改为了 authentication_string
5、退出 mysql,编辑 /etc/my.cnf 文件,删除 skip-grant-tables=1 的内容
6、重启 mysqld 服务,再用新密码登录即可