@zhangsiming65965
2019-02-14T03:22:22.000000Z
字数 13388
阅读 241
云计算
如果有梦想,就放开的去追;
因为只有奋斗,才能改变命运。

Redis是一种NoSQL(Not Only SQL),非关系型数据库;即数据和数据之间是没有关系的,使用内存空间作为存储,一般情况下作为数据库前端缓存,降低数据库的读取压力。

一般企业的Web服务的读请求远远大于写请求;上图利用MySQL一主四从架构实现读写压力分离;主库负责接收PHP的写请求、其中一台服务器专用备份,另外3台MySQL从库,作为LVS后方节点,接收PHP的读请求。
但是读压力是非常大的,即使从库负载均衡了,仍然承受不住,这样就需要在读请求过来的时候加一个Redis数据库缓存,来降低MySQL从库的读压力。
1.每次写入数据的时候,双写,一个写到MySQL数据库,一个写到Redis;
2.用户请求过来,先去到Redis-Sentinel主,读取命中直接返回用户,降低了数据库的读取压力;
3.读取未命中再去后方LVS找MySQL从库拿数据,拿回来之后还是先给Redis一份数据方便下次访问,之后再返回用户。
[root@ZhangSiming ~]# cat /etc/redhat-releaseCentOS Linux release 7.5.1804 (Core)[root@ZhangSiming ~]# uname -r3.10.0-862.el7.x86_64[root@ZhangSiming ~]# systemctl stop firewalld[root@ZhangSiming ~]# systemctl disable firewalld[root@ZhangSiming ~]# getenforce 0Disabled#使用CentOS7.5,关闭防火墙、Selinux
[root@ZhangSiming ~]# cat redis.sh#!/bin/bash#designed by ZhangSimingyum -y install wget gcc gcc-c++ make tar openssl openssl-devel cmake#安装支持包cd /tmptar xf redis-4.0.11.tar.gz -C /usr/src/cd /usr/src/redis-4.0.11/makemake MALLOC=jemallocmake PREFIX=/usr/local/redis install#编译安装rediscd /usr/local/redismkdir -p /usr/local/redis/conf#创建redis配置文件目录,并把配置文件移动进来cp /usr/src/redis-4.0.11/redis.conf /usr/local/redis/conf/cp /usr/src/redis-4.0.11/sentinel.conf /usr/local/redis/conf/ln -s /usr/local/redis/bin/* /usr/local/bin/
[root@ZhangSiming ~]# redis-server --versionRedis server v=4.0.11 sha=00000000:0 malloc=jemalloc-4.0.3 bits=64 build=86784b34d12465ce[root@ZhangSiming ~]# redis-cli --versionredis-cli 4.0.11#成功安装4.0.11版本的redis
[root@ZhangSiming ~]# cd /usr/local/redis/[root@ZhangSiming redis]# cp conf/redis.conf{,.bak}[root@ZhangSiming redis]# egrep -v "^$|^#" conf/redis.conf.bak > conf/redis.conf[root@ZhangSiming redis]# mkdir -p /data/redis/#创建Redis数据目录[root@ZhangSiming redis]# vim conf/redis.conf[root@ZhangSiming redis]# cat -n conf/redis.conf | sed -n '1p;3p;4p;7p;9p;11p;21p'1 bind 0.0.0.0#监听任意来源IP3 port 6379#监听端口63794 tcp-backlog 1024#TCP连接数为10247 daemonize yes#守护进程模式开启9 pidfile /date/redis/redis.pid#PID文件11 logfile "/data/redis/redis.log"#日志文件21 dir /data/redis#数据目录
复制一份配置文件,换一个监听端口,在启动Redis的时候指向不同的配置文件,就可以实现Redis多实例
Redis使用内存存储数据,读取极快;但是它是单进程单线程工作的。因此,同一时间Redis其实只能处理一个用户的请求,处理完毕再去处理另一用户的请求。这就导致了Redis本身对CPU没多大压力,但是会有一个TCP的连接队列,这就是为什么我们要适当加大TCP连接数来优化Redis(Redis一般在内网环境下,是绝对不能开放公网连接的,否则TCP很容易遭受攻击)
[root@ZhangSiming redis]# vim /etc/security/limits.conf[root@ZhangSiming redis]# tail -1 /etc/security/limits.conf* - nofile 10240[root@ZhangSiming redis]# exitlogout#退出登录之后重新登录使更改生效[root@ZhangSiming ~]# ulimit -n10240#单个进程文件描述符备改为10240
[root@ZhangSiming ~]# echo "net.core.somaxconn = 10240" >> /etc/sysctl.conf[root@ZhangSiming ~]# sysctl -pnet.core.somaxconn = 10240#调整TCP连接数为10240
[root@ZhangSiming ~]# echo "vm.overcommit_memory = 1" >> /etc/sysctl.conf[root@ZhangSiming ~]# tail -1 /etc/sysctl.confvm.overcommit_memory = 1[root@ZhangSiming ~]# sysctl -pnet.core.somaxconn = 10240vm.overcommit_memory = 1#调整vm.overcommit_memory为1[root@ZhangSiming ~]# sysctl -a | grep commitsysctl: reading key "net.ipv6.conf.all.stable_secret"sysctl: reading key "net.ipv6.conf.default.stable_secret"sysctl: reading key "net.ipv6.conf.ens32.stable_secret"sysctl: reading key "net.ipv6.conf.lo.stable_secret"vm.nr_overcommit_hugepages = 0vm.overcommit_kbytes = 0vm.overcommit_memory = 1#调整生效vm.overcommit_ratio = 50
[root@ZhangSiming ~]# echo 'echo never > /sys/kernel/mm/transparent_hugepage/enabled' >> /etc/rc.local[root@ZhangSiming ~]# echo 'echo never > /sys/kernel/mm/transparent_hugepage/defrag' >> /etc/rc.local[root@ZhangSiming ~]# echo never > /sys/kernel/mm/transparent_hugepage/enabled[root@ZhangSiming ~]# echo never > /sys/kernel/mm/transparent_hugepage/defrag[root@ZhangSiming ~]# tail -2 /etc/rc.localecho never > /sys/kernel/mm/transparent_hugepage/enabledecho never > /sys/kernel/mm/transparent_hugepage/defrag#根据日志中警告提示修改
[root@ZhangSiming ~]# redis-cli shutdown#关闭Redis的命令[root@ZhangSiming ~]# redis-server /usr/local/redis/conf/redis.conf#根据配置文件启动redis的命令[root@ZhangSiming ~]# netstat -antup | grep redistcp 0 0 0.0.0.0:6379 0.0.0.0:* LISTEN 1801/redis-server 0[root@ZhangSiming ~]# cat /data/redis/redis.log1800:C 09 Feb 15:02:18.742 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo1800:C 09 Feb 15:02:18.742 # Redis version=4.0.11, bits=64, commit=00000000, modified=0, pid=1800, just started1800:C 09 Feb 15:02:18.742 # Configuration loaded_.__.-``__ ''-.__.-`` `. `_. ''-._ Redis 4.0.11 (00000000/0) 64 bit.-`` .-```. ```\/ _.,_ ''-._( ' , .-` | `, ) Running in standalone mode|`-._`-...-` __...-.``-._|'` _.-'| Port: 6379| `-._ `._ / _.-' | PID: 1801`-._ `-._ `-./ _.-' _.-'|`-._`-._ `-.__.-' _.-'_.-'|| `-._`-._ _.-'_.-' | http://redis.io`-._ `-._`-.__.-'_.-' _.-'|`-._`-._ `-.__.-' _.-'_.-'|| `-._`-._ _.-'_.-' |`-._ `-._`-.__.-'_.-' _.-'`-._ `-.__.-' _.-'`-._ _.-'`-.__.-'1801:M 09 Feb 15:02:18.746 # Server initialized1801:M 09 Feb 15:02:18.746 * DB loaded from disk: 0.000 seconds1801:M 09 Feb 15:02:18.746 * Ready to accept connections#启动成功,日志干净不报警告
[root@ZhangSiming ~]# redis-cli -h localhost -p 6379localhost:6379> exit[root@ZhangSiming ~]##登录方式与MySQL类似,exit退出登录交互界面
给Redis设置密码的两种方式
通过Redis配置文件增加密码
[root@ZhangSiming ~]# redis-cli -h localhost -p 6379localhost:6379> exit[root@ZhangSiming ~]# echo "requirepass '666666'" >> /usr/local/redis/conf/redis.conf#在配置文件中指定密码为666666[root@ZhangSiming ~]# tail -1 /usr/local/redis/conf/redis.confrequirepass '666666'[root@ZhangSiming ~]# redis-cli shutdown[root@ZhangSiming ~]# redis-server /usr/local/redis/conf/redis.conf#重启Redis[root@ZhangSiming ~]# redis-cli127.0.0.1:6379> get name(error) NOAUTH Authentication required.127.0.0.1:6379> auth 666666OK#交互模式用auth验证密码127.0.0.1:6379> get name(nil)127.0.0.1:6379> exit[root@ZhangSiming ~]# redis-cli -h localhost -a 666666 get nameWarning: Using a password with '-a' option on the command line interface may not be safe.(nil)#非交互模式用-a验证密码
[root@ZhangSiming ~]# vim /usr/local/redis/conf/redis.conf#删除配置文件里的密码[root@ZhangSiming ~]# redis-cli -a 666666 shutdown#此时删除密码操作因为还没有重启所以没有生效,我们仍然需要用密码才能关闭Redis服务Warning: Using a password with '-a' option on the command line interface may not be safe.[root@ZhangSiming ~]# redis-server /usr/local/redis/conf/redis.conf#重新启动,此时Redis已经没有密码[root@ZhangSiming ~]# redis-cli127.0.0.1:6379> get name(nil)127.0.0.1:6379> config set requirepass 666666#设置密码为666666OK127.0.0.1:6379> config rewrite(error) NOAUTH Authentication required.#设置完密码,任何操作都需要先验证密码127.0.0.1:6379> auth 666666OK127.0.0.1:6379> config rewriteOK#验证密码之后,把密码重写到配置文件中127.0.0.1:6379> exit[root@ZhangSiming ~]# tail -1 /usr/local/redis/conf/redis.confrequirepass "666666"#查看配置文件最后一行
在企业中,Redis切记要加密码,并且隔绝外网,否则很容易被攻击。
持久化存储就是将数据保存到硬盘中,使得在应用程序或机器重启之后可以继续访问之前保存的数据;
Redis如果提供缓存服务,因为Redis存储是在内存中,重启服务器Redis数据会丢失;这就需要开启rdb或者aof持久化存储,把Redis中的数据持久化存储到硬盘中;
注意。rdb或者aof方式对数据都有一定影响,所以建议持久化的操作在Redis从库上进行。
[root@ZhangSiming ~]# sed -n "14p;15p;16p;18p;20p;21p" /usr/local/redis/conf/redis.confsave 900 1#900s改变1个key触发rdb存储save 300 10#300s改变10个key触发rdb存储save 60 10000#60s改变10000个key触发rdb存储rdbcompression no#关闭rdb压缩,否则影响性能dbfilename "dump.rdb"#rdb存储文件的名字dump.rdb,存储在工作目录中dir "/data/redis"[root@ZhangSiming ~]# redis-cli -a 666666 shutdown[root@ZhangSiming ~]# redis-server /usr/local/redis/conf/redis.conf[root@ZhangSiming ~]# redis-cli -a 666666 config set save ""OK#清空save值就是关闭rdb存储[root@ZhangSiming ~]# redis-cli -a 666666 config rewriteOK[root@ZhangSiming ~]# redis-cli -a 666666 config set save "180 1 120 10 60 10000"OK#设置save值就是开启rdb存储[root@ZhangSiming ~]# redis-cli -a 666666 config rewriteOK#记得交互式修改完成之后config rewrite
进行数据写入,观察rdb存储日志。
[root@ZhangSiming ~]# > /data/redis/redis.log#清空日志文件[root@ZhangSiming ~]# for line in `seq -w 10000`; do redis-cli -a 666666 set key_${line} value_${line} ; done &>/dev/null#写入数据测试[root@ZhangSiming ~]# cat /data/redis/redis.log17047:M 09 Feb 16:10:57.079 * 10000 changes in 60 seconds. Saving...#查看日志文件,10000改变发生在60s内,自动触发rdb存储17047:M 09 Feb 16:10:57.079 * Background saving started by pid 2839828398:C 09 Feb 16:10:57.136 * DB saved on disk28398:C 09 Feb 16:10:57.136 * RDB: 0 MB of memory used by copy-on-write17047:M 09 Feb 16:10:57.179 * Background saving terminated with success[root@ZhangSiming ~]# > /data/redis/redis.log#清空日志文件[root@ZhangSiming ~]# redis-cli -a 666666 save#手动进行rdb存储OK[root@ZhangSiming ~]# cat /data/redis/redis.log17047:M 09 Feb 16:14:19.064 * DB saved on disk#查看日志文件,成功存储[root@ZhangSiming ~]# > /data/redis/redis.log#继续清空日志文件[root@ZhangSiming ~]# redis-cli -a 666666 bgsave#使用bgsave存储Background saving started[root@ZhangSiming ~]# cat /data/redis/redis.log17047:M 09 Feb 16:14:30.489 * Background saving started by pid 38523#bgsave和save的区别是bgsave会启动一个新进程(38523)来进行rdb存储;而save会阻塞前端输入,所以推荐bgsave存储38523:C 09 Feb 16:14:30.497 * DB saved on disk38523:C 09 Feb 16:14:30.497 * RDB: 0 MB of memory used by copy-on-write17047:M 09 Feb 16:14:30.504 * Background saving terminated with success
Redis的appendonly(aof)存储会把用户每次的操作都记录到文件中,类似mysqlbinlog。
[root@ZhangSiming ~]# redis-server /usr/local/redis/conf/redis.conf[root@ZhangSiming ~]# redis-cli config set appendonly yesOK#开启aof存储的方式[root@ZhangSiming ~]# redis-cli config rewriteOK[root@ZhangSiming ~]# redis-cli config set appendonly noOK#关闭aof存储的方式[root@ZhangSiming ~]# redis-cli config rewriteOK
开启了aof存储之后,一般的操作没有达到rdb存储的触发条件的时候,只会写入aof文件中,rdb文件大小不变。
[root@ZhangSiming ~]# redis-cli config set appendonly yesOK[root@ZhangSiming ~]# redis-cli config rewriteOK[root@ZhangSiming ~]# du -sh /data/redis/dump.rdb228K /data/redis/dump.rdb[root@ZhangSiming ~]# du -sh /data/redis/appendonly.aof452K /data/redis/appendonly.aof[root@ZhangSiming ~]# for line in `seq -w 100` ;do redis-cli set key_${line} value_${line} &>/dev/null ;done#写入数据[root@ZhangSiming ~]# du -sh /data/redis/dump.rdb228K /data/redis/dump.rdb[root@ZhangSiming ~]# du -sh /data/redis/appendonly.aof960K /data/redis/appendonly.aof#只有aof文件增大了,aof文件类似mysqlbinlog,所有的操作语句都会记录其中
- 重写aof文件就是整理相同的key,写入最后的有效值;
- 执行一个aof文件重写操作,会创建一个当前aof文件的体积优化版本。即使重写失败,也不会有任何的数据丢失,因为旧的aof文件在重写操作成功之前不会被修改;
- 重写操作只会在没有其他持久化工作在后台执行时才会触发;
- 从Redis2.4版本开始,aof重写由Redis自行触发,bgrewriteaof命令仅仅用于手动触发重写操作。
[root@ZhangSiming ~]# du -sh /data/redis/appendonly.aof0 /data/redis/appendonly.aof[root@ZhangSiming ~]# for line in `seq -w 100` ;do redis-cli set key_${line} value_${line} &>/dev/null ;done#创建100个key[root@ZhangSiming ~]# for line in `seq -w 100` ;do redis-cli del key_${line} &>/dev/null ;done#再删除这100个key[root@ZhangSiming ~]# du -sh /data/redis/appendonly.aof8.0K /data/redis/appendonly.aof#此时aof是8k大小[root@ZhangSiming ~]# redis-cli bgrewriteaofBackground append only file rewriting started[root@ZhangSiming ~]# du -sh /data/redis/appendonly.aof0 /data/redis/appendonly.aof#手动aof重写之后,两两相消,只有0k
[root@ZhangSiming ~]# redis-cli config get auto-aof-rewrite*1) "auto-aof-rewrite-percentage"2) "100"3) "auto-aof-rewrite-min-size"4) "67108864"#aof文件增加数量超过一半,且容量大于64M就自动触发aof重写[root@ZhangSiming ~]# redis-cli config set auto-aof-rewrite-min-size 100000OK[root@ZhangSiming ~]# redis-cli config get auto-aof-rewrite*1) "auto-aof-rewrite-percentage"2) "100"3) "auto-aof-rewrite-min-size"4) "100000"#修改为aof文件增加数量超过一半,且容量大于100k就自动触发aof重写[root@ZhangSiming ~]# for line in `seq -w 10000` ;do redis-cli set key_${line} value_${line} &>/dev/null ;done[root@ZhangSiming ~]# du -sh /data/redis/appendonly.aof768K /data/redis/appendonly.aof#写入数据,已经超过了100k[root@ZhangSiming ~]# for line in `seq -w 10000` ;do redis-cli del key_${line} &>/dev/null ;done[root@ZhangSiming ~]# du -sh /data/redis/appendonly.aof384K /data/redis/appendonly.aof#删除等量的数据,发现没有累加记录aof文件,而且容量已经变小,即自动触发了aof重写
[root@ZhangSiming ~]# redis-cli flushallOK#删除所有数据库中的所有key;flushdb是删除当前数据库中的所有key。这两个命令十分危险,必须禁用[root@ZhangSiming ~]# redis-cli set key valueOK[root@ZhangSiming ~]# redis-cli ttl key(integer) -1#查看过期时间,-1代表永远不过期[root@ZhangSiming ~]# redis-cli expire key 10(integer) 1#设置过期时间为10s[root@ZhangSiming ~]# redis-cli ttl key(integer) -2#等待10s,这个key已经不存在[root@ZhangSiming ~]# redis-cli get key(nil)#查看键值也没有了
[root@ZhangSiming ~]# redis-cli config get maxmemory1) "maxmemory"2) "0"#Redis默认不限制内存[root@ZhangSiming ~]# redis-cli config set maxmemory 1MOK[root@ZhangSiming ~]# redis-cli config get maxmemory1) "maxmemory"2) "1000000"#设置最大内存为1M
[root@ZhangSiming ~]# redis-cli config get maxmemory-policy1) "maxmemory-policy"2) "noeviction"#默认的内存清理算法式报警[root@ZhangSiming ~]# redis-cli config set maxmemory-policy volatile-lruOK[root@ZhangSiming ~]# redis-cli config get maxmemory-policy1) "maxmemory-policy"2) "volatile-lru"#修改内存清理算法为清理有过期时间的key[root@ZhangSiming ~]# for line in `seq -w 10000` ;do redis-cli set key_${line} value_${line} &>/dev/null ;done[root@ZhangSiming ~]# redis-cli set zhansiming 111(error) OOM command not allowed when used memory > 'maxmemory'.#写入数据,已经超内存,不能再写入了[root@ZhangSiming ~]# redis-cli expire key_55 100(integer) 0[root@ZhangSiming ~]# redis-cli get key_55(nil)#随便给一个已经有的key设置过期时间,立马就被内存清理算法删除了
[root@ZhangSiming ~]# sed -n "28p;58p;59p;60p" /usr/local/redis/conf/redis.confappendonly norename-command flushall ""rename-command flushdb ""rename-command keys ""#在配置文件最后设置重命名命令为空,就可以屏蔽了;但是注意对于flushall命令,必须设置appendonly no ,否则服务器无法启动[root@ZhangSiming ~]# redis-server /usr/local/redis/conf/redis.conf[root@ZhangSiming ~]# redis-cli flushdb(error) ERR unknown command `flushdb`, with args beginning with:[root@ZhangSiming ~]# redis-cli flushall(error) ERR unknown command `flushall`, with args beginning with:[root@ZhangSiming ~]# redis-cli keys(error) ERR unknown command `keys`, with args beginning with:[root@ZhangSiming ~]# redis-cli get key(nil)#成功屏蔽掉敏感命令