@zhangsiming65965
2019-02-14T03:22:22.000000Z
字数 13388
阅读 220
云计算
如果有梦想,就放开的去追;
因为只有奋斗,才能改变命运。
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-release
CentOS Linux release 7.5.1804 (Core)
[root@ZhangSiming ~]# uname -r
3.10.0-862.el7.x86_64
[root@ZhangSiming ~]# systemctl stop firewalld
[root@ZhangSiming ~]# systemctl disable firewalld
[root@ZhangSiming ~]# getenforce 0
Disabled
#使用CentOS7.5,关闭防火墙、Selinux
[root@ZhangSiming ~]# cat redis.sh
#!/bin/bash
#designed by ZhangSiming
yum -y install wget gcc gcc-c++ make tar openssl openssl-devel cmake
#安装支持包
cd /tmp
tar xf redis-4.0.11.tar.gz -C /usr/src/
cd /usr/src/redis-4.0.11/
make
make MALLOC=jemalloc
make PREFIX=/usr/local/redis install
#编译安装redis
cd /usr/local/redis
mkdir -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 --version
Redis server v=4.0.11 sha=00000000:0 malloc=jemalloc-4.0.3 bits=64 build=86784b34d12465ce
[root@ZhangSiming ~]# redis-cli --version
redis-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
#监听任意来源IP
3 port 6379
#监听端口6379
4 tcp-backlog 1024
#TCP连接数为1024
7 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]# exit
logout
#退出登录之后重新登录使更改生效
[root@ZhangSiming ~]# ulimit -n
10240
#单个进程文件描述符备改为10240
[root@ZhangSiming ~]# echo "net.core.somaxconn = 10240" >> /etc/sysctl.conf
[root@ZhangSiming ~]# sysctl -p
net.core.somaxconn = 10240
#调整TCP连接数为10240
[root@ZhangSiming ~]# echo "vm.overcommit_memory = 1" >> /etc/sysctl.conf
[root@ZhangSiming ~]# tail -1 /etc/sysctl.conf
vm.overcommit_memory = 1
[root@ZhangSiming ~]# sysctl -p
net.core.somaxconn = 10240
vm.overcommit_memory = 1
#调整vm.overcommit_memory为1
[root@ZhangSiming ~]# sysctl -a | grep commit
sysctl: 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 = 0
vm.overcommit_kbytes = 0
vm.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.local
echo never > /sys/kernel/mm/transparent_hugepage/enabled
echo 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 redis
tcp 0 0 0.0.0.0:6379 0.0.0.0:* LISTEN 1801/redis-server 0
[root@ZhangSiming ~]# cat /data/redis/redis.log
1800:C 09 Feb 15:02:18.742 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
1800:C 09 Feb 15:02:18.742 # Redis version=4.0.11, bits=64, commit=00000000, modified=0, pid=1800, just started
1800: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 initialized
1801:M 09 Feb 15:02:18.746 * DB loaded from disk: 0.000 seconds
1801:M 09 Feb 15:02:18.746 * Ready to accept connections
#启动成功,日志干净不报警告
[root@ZhangSiming ~]# redis-cli -h localhost -p 6379
localhost:6379> exit
[root@ZhangSiming ~]#
#登录方式与MySQL类似,exit退出登录交互界面
给Redis设置密码的两种方式
通过Redis配置文件增加密码
[root@ZhangSiming ~]# redis-cli -h localhost -p 6379
localhost:6379> exit
[root@ZhangSiming ~]# echo "requirepass '666666'" >> /usr/local/redis/conf/redis.conf
#在配置文件中指定密码为666666
[root@ZhangSiming ~]# tail -1 /usr/local/redis/conf/redis.conf
requirepass '666666'
[root@ZhangSiming ~]# redis-cli shutdown
[root@ZhangSiming ~]# redis-server /usr/local/redis/conf/redis.conf
#重启Redis
[root@ZhangSiming ~]# redis-cli
127.0.0.1:6379> get name
(error) NOAUTH Authentication required.
127.0.0.1:6379> auth 666666
OK
#交互模式用auth验证密码
127.0.0.1:6379> get name
(nil)
127.0.0.1:6379> exit
[root@ZhangSiming ~]# redis-cli -h localhost -a 666666 get name
Warning: 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-cli
127.0.0.1:6379> get name
(nil)
127.0.0.1:6379> config set requirepass 666666
#设置密码为666666
OK
127.0.0.1:6379> config rewrite
(error) NOAUTH Authentication required.
#设置完密码,任何操作都需要先验证密码
127.0.0.1:6379> auth 666666
OK
127.0.0.1:6379> config rewrite
OK
#验证密码之后,把密码重写到配置文件中
127.0.0.1:6379> exit
[root@ZhangSiming ~]# tail -1 /usr/local/redis/conf/redis.conf
requirepass "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.conf
save 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 rewrite
OK
[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 rewrite
OK
#记得交互式修改完成之后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.log
17047: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 28398
28398:C 09 Feb 16:10:57.136 * DB saved on disk
28398:C 09 Feb 16:10:57.136 * RDB: 0 MB of memory used by copy-on-write
17047: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.log
17047: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.log
17047: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 disk
38523:C 09 Feb 16:14:30.497 * RDB: 0 MB of memory used by copy-on-write
17047: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 yes
OK
#开启aof存储的方式
[root@ZhangSiming ~]# redis-cli config rewrite
OK
[root@ZhangSiming ~]# redis-cli config set appendonly no
OK
#关闭aof存储的方式
[root@ZhangSiming ~]# redis-cli config rewrite
OK
开启了aof存储之后,一般的操作没有达到rdb存储的触发条件的时候,只会写入aof文件中,rdb文件大小不变。
[root@ZhangSiming ~]# redis-cli config set appendonly yes
OK
[root@ZhangSiming ~]# redis-cli config rewrite
OK
[root@ZhangSiming ~]# du -sh /data/redis/dump.rdb
228K /data/redis/dump.rdb
[root@ZhangSiming ~]# du -sh /data/redis/appendonly.aof
452K /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.rdb
228K /data/redis/dump.rdb
[root@ZhangSiming ~]# du -sh /data/redis/appendonly.aof
960K /data/redis/appendonly.aof
#只有aof文件增大了,aof文件类似mysqlbinlog,所有的操作语句都会记录其中
- 重写aof文件就是整理相同的key,写入最后的有效值;
- 执行一个aof文件重写操作,会创建一个当前aof文件的体积优化版本。即使重写失败,也不会有任何的数据丢失,因为旧的aof文件在重写操作成功之前不会被修改;
- 重写操作只会在没有其他持久化工作在后台执行时才会触发;
- 从Redis2.4版本开始,aof重写由Redis自行触发,bgrewriteaof命令仅仅用于手动触发重写操作。
[root@ZhangSiming ~]# du -sh /data/redis/appendonly.aof
0 /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.aof
8.0K /data/redis/appendonly.aof
#此时aof是8k大小
[root@ZhangSiming ~]# redis-cli bgrewriteaof
Background append only file rewriting started
[root@ZhangSiming ~]# du -sh /data/redis/appendonly.aof
0 /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 100000
OK
[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.aof
768K /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.aof
384K /data/redis/appendonly.aof
#删除等量的数据,发现没有累加记录aof文件,而且容量已经变小,即自动触发了aof重写
[root@ZhangSiming ~]# redis-cli flushall
OK
#删除所有数据库中的所有key;flushdb是删除当前数据库中的所有key。这两个命令十分危险,必须禁用
[root@ZhangSiming ~]# redis-cli set key value
OK
[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 maxmemory
1) "maxmemory"
2) "0"
#Redis默认不限制内存
[root@ZhangSiming ~]# redis-cli config set maxmemory 1M
OK
[root@ZhangSiming ~]# redis-cli config get maxmemory
1) "maxmemory"
2) "1000000"
#设置最大内存为1M
[root@ZhangSiming ~]# redis-cli config get maxmemory-policy
1) "maxmemory-policy"
2) "noeviction"
#默认的内存清理算法式报警
[root@ZhangSiming ~]# redis-cli config set maxmemory-policy volatile-lru
OK
[root@ZhangSiming ~]# redis-cli config get maxmemory-policy
1) "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.conf
appendonly no
rename-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)
#成功屏蔽掉敏感命令