一,redis概述与实验环境说明

1.1 什么是redis

redis是一种内存型的NoSQL数据库,优点是快,常用来做缓存用 
redis存储数据的方法是以key-value的形式 
value类型支持字符串,列表,哈希等多种类型

1.2 环境说明

主机名

IP

用途

Redis01

10.1.1.146

Redis-master

[root@Redis01 ~]# cat /etc/redhat-release
CentOS Linux release 7.5.1804 (Core)
[root@Redis01 ~]# uname -r
3.10.0-862.el7.x86_64
[root@Redis01 ~]# systemctl stop firewalld
[root@Redis01 ~]# systemctl disable firewalld
[root@Redis01 ~]# setenforce 0
setenforce: SELinux is disabled
[root@Redis01 ~]# sestatus
SELinux status:                 disabled

1.3 yum仓库使用技巧

查找一个命令出自哪个rpm包

二,Redis服务器4.0版本源码编译安装

2.1 redis下载地址https://redis.io/download

2.2 redis源码编译

[root@Redis01 ~]# yum -y install wget gcc gcc-c++ make tar openssl openssl-devel cmake

[root@Redis01 ~]# tar xf redis-4.0.11.tar.gz -C /usr/src/
[root@Redis01 ~]# cd /usr/src/redis-4.0.11/
[root@Redis01 redis-4.0.11]# make && make MALLOC=jemalloc && make PREFIX=/usr/local/redis install

[root@Redis01 ~]# cd /usr/local/redis/
[root@Redis01 redis]# ls
bin
[root@Redis01 redis]# mkdir -p /usr/local/redis/conf
[root@Redis01 redis]# cp /usr/src/redis-4.0.11/redis.conf /usr/local/redis/conf/

[root@Redis01 redis]# cp /usr/src/redis-4.0.11/sentinel.conf /usr/local/redis
/conf/[root@Redis01 redis]# ln -s /usr/local/redis/bin/* /usr/local/bin/
[root@Redis01 redis]# which redis-server
/usr/local/bin/redis-server
[root@Redis01 redis]# redis-server --version
Redis server v=4.0.11 sha=00000000:0 malloc=jemalloc-4.0.3 bits=64 build=4d00
c4dd9c0e3653[root@Redis01 redis]# redis-cli --version
redis-cli 4.0.11

(快照)

三,Redis服务器启动和系统参数调整

3.1 简化redis配置文件

[root@Redis01 redis]# pwd
/usr/local/redis
[root@Redis01 redis]# cp conf/redis.conf{,.bak}
[root@Redis01 redis]# egrep -v "^$|^#" conf/redis.conf.bak > conf/redis.conf
[root@Redis01 redis]# mkdir -p /data/redis/  创建redis数据目录

修改redis配置文件以下参数

修改成以下设置

[root@Redis01 redis]# vim conf/redis.conf
[root@Redis01 redis]# cat -n conf/redis.conf | sed -n '1p;3p;4p;7p;9p;11p;21p'
     1    bind 0.0.0.0  #监听地址
     3    port 6379   #监听端口
     4    tcp-backlog 1024  #tcp连接数
     7    daemonize yes  #是否后台启动
     9    pidfile /data/redis/redis.pid    #pid存放目录
    11    logfile "/data/redis/redis.log"   #日志存放目录
    21    dir /data/redis  #工作目录

3.3 redis服务器启动和关闭

启动redis服务器
[root@Redis01 redis]# redis-server /usr/local/redis/conf/redis.conf
[root@Redis01 redis]# netstat -antup | grep redis
tcp        0      0 0.0.0.0:6379            0.0.0.0:*               LISTEN     
 17416/redis-server

关闭redis服务器

[root@Redis01 redis]# redis-cli -p 6379 -h 127.0.0.1 shutdown
[root@Redis01 redis]# netstat -antup | grep redis
[root@Redis01 redis]# redis-server /usr/local/redis/conf/redis.conf
[root@Redis01 redis]# netstat -antup | grep redis
tcp        0      0 0.0.0.0:6379            0.0.0.0:*               LISTEN     
 17426/redis-server

[root@Redis01 redis]# redis-cli shutdown
[root@Redis01 redis]# netstat -antup | grep redis
连接redis服务器

[root@Redis01 ~]# redis-server /usr/local/redis/conf/redis.conf
[root@Redis01 ~]# redis-cli -h 127.0.0.1
127.0.0.1:6379> exit
[root@Redis01 ~]# redis-cli
127.0.0.1:6379> exit

3.4 系统参数优化调整

启动redis以后,我们查看系统日志 cat /data/redis/redis.log

警告提示1:系统文件描述符设置的太小了,才1024,我们最好设置到10032

警告提示2:对一个高负载的环境来说tcp设置128这个值,太小了。

警告提示3:overcommit_memory=0为不允许超额抢占内存,但是,rdb保存可能会失败。建议将vm.overcommit_memory = 1进行修改

警告提示4:你的内核中启用了巨大内存页的支持,这将与redis的延迟内存使用冲突。

1)调整系统文件描述符

[root@Redis01 ~]# echo "* - nofile 10240" >> /etc/security/limits.conf

退出登陆一下即可生效

[root@Redis01 ~]# exit

[root@Redis01 ~]# ulimit -n
10240

2)调整系统tcp连接数

[root@Redis01 ~]# sysctl -a | grep soma
net.core.somaxconn = 128
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"
[root@Redis01 ~]# echo "net.core.somaxconn = 10240" >> /etc/sysctl.conf
[root@Redis01 ~]# sysctl -p
net.core.somaxconn = 10240

3)调整系统内存分配策略

[root@Redis01 ~]# echo "vm.overcommit_memory = 1" >> /etc/sysctl.conf
[root@Redis01 ~]# sysctl -p
net.core.somaxconn = 10240
vm.overcommit_memory = 1
[root@Redis01 ~]# 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

4)关闭系统内核的巨大内存页支持

[root@Redis01 ~]# echo never > /sys/kernel/mm/transparent_hugepage/enabled
[root@Redis01 ~]# cat /sys/kernel/mm/transparent_hugepage/enabled
always madvise [never]
[root@Redis01 ~]# echo never > /sys/kernel/mm/transparent_hugepage/defrag
[root@Redis01 ~]# cat /sys/kernel/mm/transparent_hugepage/defrag
always madvise [never]

添加到/etc/rc.local

[root@Redis01 ~]# echo 'echo never > /sys/kernel/mm/transparent_hugepage/enabled' >> /etc/rc.local

[root@Redis01 ~]# echo 'echo never > /sys/kernel/mm/transparent_hugepage/defrag' >> /etc/rc.local

[root@Redis01 ~]# tail -2 /etc/rc.local
echo never > /sys/kernel/mm/transparent_hugepage/enabled
echo never > /sys/kernel/mm/transparent_hugepage/defrag

5)重启redis-server验证修改

关闭redis     清空日志     启动redis

四,Redis客户端使用和字符串简单操作

  • mysql命令用来跟MySQL服务器进行交互
  • redis-cli命令用来跟redis服务器进行交互

4.1 使用redis-cli客户端登陆redis-server

[root@Redis01 ~]# redis-cli
127.0.0.1:6379> exit
[root@Redis01 ~]# redis-cli -h localhost -p 6379
localhost:6379> exit

4.2 redis字符串操作

4.1 使用redis-cli客户端登陆redis-server

[root@Redis01 ~]# redis-cli
127.0.0.1:6379> set name wwl    #增加键(key)和值(value)
OK
127.0.0.1:6379> get name #根据键获取值
"wwl"
127.0.0.1:6379> set name xiaomei    #修改键的值
OK
127.0.0.1:6379> get name   #根据键获取值
"xiaomei"
127.0.0.1:6379> del name   #删除,返回1代表删除成功
(integer) 1
127.0.0.1:6379> GET name  #命令不区分大小写
(nil)
127.0.0.1:6379> set NAME test
OK
127.0.0.1:6379> get name
(nil)
127.0.0.1:6379> get NAME   #key区分大小写
"test"
127.0.0.1:6379> del NAME
(integer) 1

4.3 非交互式操作redis服务器

[root@Redis01 ~]# redis-cli set name welcome
OK
[root@Redis01 ~]# redis-cli get name
"welcome"
[root@Redis01 ~]# redis-cli del name
(integer) 1
[root@Redis01 ~]# redis-cli get name
(nil)

五,Redis列表集合简单操作

redis的key都是字符串,value支持字符串,列表,集合等

5.1 redis列表的操作,有序的可重复的

列表就是有顺序的,可重复的一堆值的组合

[root@Redis01 ~]# redis-cli
127.0.0.1:6379> lpush names yun1    #创建一个列表names,并从左边推入一个值yun1
(integer) 1
127.0.0.1:6379> lpush names yun2    #向列表names左边推入一个值yun2
(integer) 2
127.0.0.1:6379> lpush names yun3
(integer) 3
127.0.0.1:6379> lpush names yun4
(integer) 4
127.0.0.1:6379> lpush names yun5
(integer) 5
127.0.0.1:6379> lrange names 0 -1  #查看列表names从索引0开始到结束所有的值
1) "yun5"
2) "yun4"
3) "yun3"
4) "yun2"
5) "yun1"
127.0.0.1:6379> lrange names 0 1     #查看索引0到1的值
1) "yun5"
2) "yun4"
127.0.0.1:6379> lrange names 0 3
1) "yun5"
2) "yun4"
3) "yun3"
4) "yun2"
127.0.0.1:6379> lrange names 0 0
1) "yun5"
127.0.0.1:6379> lpush names yun  
(integer) 6
127.0.0.1:6379> lpush names yun
(integer) 7
127.0.0.1:6379> lrange names 0 -1
1) "yun"
2) "yun"
3) "yun5"
4) "yun4"
5) "yun3"
6) "yun2"
7) "yun1"
127.0.0.1:6379> lrem names 1 yun  #从左边数删除第一个yun
(integer) 1
127.0.0.1:6379> lrem names 1 yun
(integer) 1
127.0.0.1:6379> lrange names 0 -1
1) "yun5"
2) "yun4"
3) "yun3"
4) "yun2"
5) "yun1"
127.0.0.1:6379> lpush names xue   #从列表的左边加入一个元素xue
(integer) 6
127.0.0.1:6379> lpush names xue
(integer) 7
127.0.0.1:6379> lrange names 0 -1
1) "xue"
2) "xue"
3) "yun5"
4) "yun4"
5) "yun3"
6) "yun2"
7) "yun1"
127.0.0.1:6379> lrem names 0 xue   #从列表的左边数删除所有的雪
(integer) 2
127.0.0.1:6379> lrange names 0 -1
1) "yun5"
2) "yun4"
3) "yun3"
4) "yun2"
5) "yun1"
127.0.0.1:6379> lpop names  #移除列表最左边的元素
"yun5"
127.0.0.1:6379> lpop names
"yun4"
127.0.0.1:6379> lpop names
"yun3"
127.0.0.1:6379> lpop names
"yun2"
127.0.0.1:6379> lpop names
"yun1"
127.0.0.1:6379> lpush names lili
(integer) 1
127.0.0.1:6379> lpush names lili1
(integer) 2
127.0.0.1:6379> lpush names lili12
(integer) 3
127.0.0.1:6379> lrange names 0 -1
1) "lili12"
2) "lili1"
3) "lili"
127.0.0.1:6379> rpop names    #移除列表最右边的元素
"lili"
127.0.0.1:6379> rpop names
"lili1"
127.0.0.1:6379> rpop names
"lili12"
127.0.0.1:6379> lpush wang haha1
(integer) 1
127.0.0.1:6379> lpush wang haha2
(integer) 2
127.0.0.1:6379> lpush wang haha3
(integer) 3
127.0.0.1:6379> lrange wang 0 -1
1) "haha3"
2) "haha2"
3) "haha1"
127.0.0.1:6379> lset wang 0 www   #修改列表左起第一个元素
OK
127.0.0.1:6379> lrange wang 0 -1
1) "www"
2) "haha2"
3) "haha1"

5.2 redis集合的操作,无序的不重复的

集合就是不能重复的,无固定顺序的列表

127.0.0.1:6379> sadd ages 10    #向集合中添加元素
(integer) 1
127.0.0.1:6379> sadd ages 15
(integer) 1
127.0.0.1:6379> sadd ages 20
(integer) 1
127.0.0.1:6379> sadd ages 25
(integer) 1
127.0.0.1:6379> sadd ages 25    #失败,集合的元素具有唯一性
(integer) 0
127.0.0.1:6379> smembers ages    #查看集合里的元素
1) "10"
2) "15"
3) "20"
4) "25"
127.0.0.1:6379> srem ages 25     #移除集合里是25的元素
(integer) 1
127.0.0.1:6379> smembers ages
1) "10"
2) "15"
3) "20"
127.0.0.1:6379> spop ages   #随机移除集合里的一个元素
"10"
127.0.0.1:6379> smembers ages
1) "15"
2) "20"
127.0.0.1:6379> sismember ages 40  #查找集合里是否有40的元素
(integer) 0        #集合里没有40的元素
127.0.0.1:6379> sismember ages 15
(integer) 1

六,Redis的hash和订阅简单操作

6.1 redis的hash操作

hash就是可以存多个键值对的组合(类似python字典)

127.0.0.1:6379> hset info name 'yunjisuan'   #增加一个hash
(integer) 1
127.0.0.1:6379> hset info age 25
(integer) 1
127.0.0.1:6379> hset info location 'beijing'
(integer) 1
127.0.0.1:6379> hgetall info
1) "name"
2) "yunjisuan"
3) "age"
4) "25"
5) "location"
6) "beijing"
127.0.0.1:6379> hget info name
"yunjisuan"
127.0.0.1:6379> hdel info name age
(integer) 2
127.0.0.1:6379> hgetall info
1) "location"
2) "beijing"
127.0.0.1:6379> del info
(integer) 1
127.0.0.1:6379> hmset info name 'yunjisuan' age 25 location 'beijing'
OK
127.0.0.1:6379> hgetall info
1) "name"
2) "yunjisuan"
3) "age"
4) "25"
5) "location"
6) "beijing"

6.2 redis的订阅操作

开启redis的订阅功能
[root@Redis01 ~]# redis-cli
127.0.0.1:6379> subscribe yunjisuan    #开启频道名:yunjisuan的订阅功能,可开启多个窗口进行订阅
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "yunjisuan"
3) (integer) 1
对频道进行内容推送
[root@Redis01 ~]# redis-cli
127.0.0.1:6379> publish yunjisuan '你真美'     #向频道yunjisuan推送你真美
(integer) 1     #推送成功的人数
再开两个窗口,查看订阅信息
[root@Redis01 ~]# redis-cli
127.0.0.1:6379> subscribe yunjisuan
[root@Redis01 ~]# redis-cli
127.0.0.1:6379> subscribe yunjisuan
127.0.0.1:6379> publish yunjisuan 'nihao'
(integer) 3
关掉登录一个
127.0.0.1:6379> publish yunjisuan 'hahaha'
(integer) 2

七,使用Shell往Redis批量添加数据

1)批量往redis server上插入数据

[root@Redis01 ~]# for line in `seq -w 10`;do redis-cli set name_${line} value_${line};done

2)查看key的情况

[root@Redis01 ~]# redis-cli
127.0.0.1:6379> keys *    #查看所有key命令,不建议使用,上千万的key会使redis服务器堵塞
 1) "name_03"
 2) "name_08"
 3) "name_07"
 4) "name_02"
 5) "name_10"
 6) "name_09"
 7) "name_06"
 8) "name_05"
 9) "name_01"
10) "name_04"
127.0.0.1:6379> randomkey   #随机返回一个key
"name_02"
127.0.0.1:6379> randomkey
"name_07"
127.0.0.1:6379> scan 0   #分页查看key
1) "0"
2)  1) "name_08"
    2) "name_07"
    3) "name_02"
    4) "name_10"
    5) "name_09"
    6) "name_03"
    7) "name_06"
    8) "name_05"
    9) "name_01"
   10) "name_04"

八,Redis服务器info状态信息查看

redis提供了一个info命令查看redis服务器的信息,类似Linux提供一个top命令查看系统的信息

[root@Redis01 ~]# redis-cli info
# Server    #服务器的信息
redis_version:4.0.11     #redis服务器版本
redis_git_sha1:00000000   #Git SHA1
redis_git_dirty:0      #Git dirty flag
redis_build_id:4d00c4dd9c0e3653     #redis build id
redis_mode:standalone     #运行模式,单机或集群
os:Linux 3.10.0-862.el7.x86_64 x86_64   #redis服务器宿主机操作系统
arch_bits:64     #架构64位
multiplexing_api:epoll       #redis所使用的事件处理模型
atomicvar_api:atomic-builtin
gcc_version:4.8.5     #编译redis时gcc版本
process_id:17876    #redis服务器进程的pid
run_id:be4b0e741fa09976438795ea0d240bfcce94330d  #redis服务器的随机标识符(sentinel和集群)
tcp_port:6379  
uptime_in_seconds:3989
uptime_in_days:0
hz:10
lru_clock:3099797
executable:/root/redis-server
config_file:/usr/local/redis/conf/redis.conf

# Clients
connected_clients:1
client_longest_output_list:0
client_biggest_input_buf:0
blocked_clients:0

# Memory
used_memory:849248
used_memory_human:829.34K
used_memory_rss:2428928
used_memory_rss_human:2.32M
used_memory_peak:910592
used_memory_peak_human:889.25K
used_memory_peak_perc:93.26%
used_memory_overhead:836686
used_memory_startup:786592
used_memory_dataset:12562
used_memory_dataset_perc:20.05%
total_system_memory:1021906944
total_system_memory_human:974.57M
used_memory_lua:37888
used_memory_lua_human:37.00K
maxmemory:0
maxmemory_human:0B
maxmemory_policy:noeviction
mem_fragmentation_ratio:2.86
mem_allocator:jemalloc-4.0.3
active_defrag_running:0
lazyfree_pending_objects:0

# Persistence
loading:0
rdb_changes_since_last_save:7
rdb_bgsave_in_progress:0
rdb_last_save_time:1546603255
rdb_last_bgsave_status:ok
rdb_last_bgsave_time_sec:0
rdb_current_bgsave_time_sec:-1
rdb_last_cow_size:352256
aof_enabled:0
aof_rewrite_in_progress:0
aof_rewrite_scheduled:0
aof_last_rewrite_time_sec:-1
aof_current_rewrite_time_sec:-1
aof_last_bgrewrite_status:ok
aof_last_write_status:ok
aof_last_cow_size:0

# Stats
total_connections_received:27
total_commands_processed:144
instantaneous_ops_per_sec:0
total_net_input_bytes:4876
total_net_output_bytes:124503
instantaneous_input_kbps:0.00
instantaneous_output_kbps:0.00
rejected_connections:0
sync_full:0
sync_partial_ok:0
sync_partial_err:0
expired_keys:0
expired_stale_perc:0.00
expired_time_cap_reached_count:0
evicted_keys:0
keyspace_hits:25
keyspace_misses:11
pubsub_channels:0
pubsub_patterns:0
latest_fork_usec:105
migrate_cached_sockets:0
slave_expires_tracked_keys:0
active_defrag_hits:0
active_defrag_misses:0
active_defrag_key_hits:0
active_defrag_key_misses:0

# Replication
role:master
connected_slaves:0
master_replid:e2baa8fec4ff2b9aa764c386381e9c6556d4c5a0
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:0
second_repl_offset:-1
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0

# CPU
used_cpu_sys:1.65
used_cpu_user:1.15
used_cpu_sys_children:0.00
used_cpu_user_children:0.00

# Cluster
cluster_enabled:0

# Keyspace
db0:keys=10,expires=0,avg_ttl=0

九,Redis服务器加密和无密码攻击演示

在这之前先演示一下怎么操作redis
修改redis的配置文件一般都要重启redis,但是redis有一种平滑修改的功能
[root@Redis01 ~]# cd /data/redis/
[root@Redis01 redis]# ls
dump.rdb  redis.log  redis.pid
默认redis是开着持久化存储的,我们给它关了
配置文件里查找一下和save有关的参数
127.0.0.1:6379> config get save
1) "save"
2) "900 1 300 10 60 10000"
因为之前我的机器快照过,所以会有这些信息,现在要去掉它的持久化

127.0.0.1:6379> config set save ""
OK
127.0.0.1:6379> config get save
1) "save"
2) ""
这时它的配置文件没有任何变化,执行重写配置文件,再看配置文件已经发生了变化,save的信息已经没了

127.0.0.1:6379> config rewrite
OK

这就是redis的平滑修改,不需要重启配置文件

127.0.0.1:6379> config get dir
1) "dir"
2) "/data/redis"
我们用config get dir发现,redis的工作目录我们都会知道在哪,因此我们只要连上redis,就能够修改它的配置文件

9.1 入侵无密码redis服务器演示
开启Redis02,测试效果,开始攻击
[root@Redis02 ~]# redis-cli -h 10.1.1.146 -p 6379
10.1.1.146:6379> config get dir
1) "dir"
2) "/data/redis"
攻击之前记得将redis01快照一下。。。。。
10.1.1.146:6379> config set dir /etc/
OK
10.1.1.146:6379> config set dbfilename "crontab"
OK
10.1.1.146:6379> config set save "900 1 300 10 60 10000"
OK
10.1.1.146:6379> config get save
1) "save"
2) "900 1 300 10 60 10000"
10.1.1.146:6379> config rewrite
OK
[root@Redis02 ~]# echo "* * * * * root echo 'attack'" >> /tmp/attack
[root@Redis02 ~]# vim /tmp/attack
[root@Redis02 ~]# cat /tmp/attack    #这个文件内容上下必须各有两个回车

* * * * * root echo 'attack'

[root@Redis02 ~]# cat /tmp/attack | redis-cli -h 10.1.1.146 -x set attack
OK
[root@Redis02 ~]# redis-cli -h 10.1.1.146 save
OK

然后你的redis服务器就会被攻击了

redis无密码如果放在公网的话,会被攻击

9.2给redis增加密码的两种方式

(1)通过redis配置文件增加密码

给配置文件增加密码参数
[root@Redis01 ~]# echo 'requirepass "yunjisuan"' >> /usr/local/redis/conf/redis.
conf[root@Redis01 ~]# tail -1 /usr/local/redis/conf/redis.conf
requirepass "yunjisuan"
[root@Redis01 ~]# redis-cli shutdown
[root@Redis01 ~]# redis-server /usr/local/redis/conf/redis.conf
[root@Redis01 ~]# redis-cli
127.0.0.1:6379> keys *
(error) NOAUTH Authentication required.
127.0.0.1:6379> auth yunjisuan
OK
127.0.0.1:6379> set name benet
OK
非交互式输入密码进行登录
[root@Redis01 ~]# redis-cli -h 127.0.0.1 -p 6379 -a yunjisuan get name
Warning: Using a password with '-a' option on the command line interface may not be safe.

"benet"
警告:使用-a方式输入密码并不安全

(2)使用交互式的方式给redis增加密码(无需重启redis)

将之前在配置文件里设置的密码参数删除
[root@Redis01 ~]# sed -i '$d' /usr/local/redis/conf/redis.conf
重启redis-server
[root@Redis01 ~]# redis-cli -a yunjisuan shutdown
Warning: Using a password with '-a' option on the command line interface may not
 be safe.[root@Redis01 ~]# redis-server /usr/local/redis/conf/redis.conf
[root@Redis01 ~]# netstat -antup | grep redis
tcp        0      0 0.0.0.0:6379            0.0.0.0:*               LISTEN      
23539/redis-server 
交互式登陆redis设置密码
127.0.0.1:6379> set name benet
OK
127.0.0.1:6379> get name
"benet"
127.0.0.1:6379> config get requirepass
1) "requirepass"
2) ""
127.0.0.1:6379> config set requirepass yunjisuan
OK
127.0.0.1:6379> config get requirepass
(error) NOAUTH Authentication required.
127.0.0.1:6379> auth yunjisuan
OK
127.0.0.1:6379> config get requirepass
1) "requirepass"
2) "yunjisuan"
127.0.0.1:6379> config rewrite
OK
127.0.0.1:6379> exit
[root@Redis01 ~]# tail -2 /usr/local/redis/conf/redis.conf
# Generated by CONFIG REWRITE
requirepass "yunjisuan"

十,Redis的RDB存储方式

10.1 redis的运行方式说明

redis如果提供缓存服务,可以关闭所有持久化存储,如此一来redis重启后所有数据会丢失 
开启rdb或aof持久化存储,能把redis中的数据持久化到磁盘中。 
rdb和aof对性能都有影响,所以建议持久化的操作在从库上进行

10.2 redis
rdb存储方式,使用save配置开启rdb存储或者关闭rdb存储

与rdb相关的配置文件信息

dir /data/redis/    #dir为rdb存储的路径

dbfilename dump.rdb #rdb存储文件的名字

save 60 10000       #60s改变10000key,触发rdb存储

save 300 10         #300s改变10个key,触发rdb存储

save 900 1          #900s改变1个key触发rdb存储

rdbcompression no   #rdb压缩最好关闭,影响cpu

0.3 设置开启或者关闭rdb存储

提示:默认情况下rdb持久化存储是开启的

[root@Redis01 ~]# redis-cli config set save " " #关闭rdb存储
OK
[root@Redis01 ~]# redis-cli config rewrite #配置保存
OK
[root@Redis01 ~]# redis-cli config set save "180 1 120 10 60 10000"   #开启rdb
OK
[root@Redis01 ~]# redis-cli config rewrite
OK
flushdb或flushall代表清空redis的数据(这两个命令以后也是要屏蔽掉的,很危险)
redis-cli info 查看redis里有多少个键,键的总数

10.4 进行数据写入,观察rdb存储日志

输入1万条数据

for line in `seq -w 10000`;do redis-cli set key_${line} value1_${line};done

查看日志信息cat /data/redis/redis.log

发生了1万条数据改变60秒内,触发rdb存储

10.5 redis提供的bgsave命令能够立刻触发rdb存储,观察存储日志

[root@Redis01 ~]# redis-cli save  #会阻塞前端客户数据输入
OK
[root@Redis01 ~]# redis-cli bgsave   #后台启动新进程进行rdb存储
Background saving started

#查看日志

[root@Redis01 ~]# cat /data/redis/redis.log

1228:M 04 Jan 22:26:53.345 * DB saved on disk       #save触发的日志信息
1228:M 04 Jan 22:27:00.370 * Background saving started by pid 25038     #bgsave触发的信息
25038:C 04 Jan 22:27:00.376 * DB saved on disk  #bgsave触发的信息
25038:C 04 Jan 22:27:00.377 * RDB: 0 MB of memory used by copy-on-write  #bgsave触发的信息
1228:M 04 Jan 22:27:00.392 * Background saving terminated with success   #bgsave触发的信息

十一,Redis的AOF存储方式

redis的appendonly(aof)持久化存储会把用户每次的操作都记录到文件中(类似mysqlbinlog)

11.1 动态开启或者关闭aof

[root@Redis01 ~]# redis-cli
127.0.0.1:6379> config get appendonly
1) "appendonly"
2) "no"
127.0.0.1:6379> config set appendonly "yes"
OK
127.0.0.1:6379> config rewrite
OK

11.2 写入数据,观察aof。多次运行,aof文件不断增大,rdb文件大小不变(略)

开启rdb之后瞬间就有了,这时数据库里的数据都已经被写过来了

[root@Redis01 redis]# cat appendonly.aof
[root@Redis01 redis]# du -sh appendonly.aof
460K    appendonly.aof
127.0.0.1:6379> flushdb
OK
127.0.0.1:6379> bgrewriteaof
Background append only file rewriting started

11.3 重写aof文件,整理相同的key,写入最后的有效值

BGREWRITEAOF 
执行一个AOF文件重写操作。重写会创建一个当前AOF文件的体积优化版本 
即使BGREWRITEAOF执行失败,也不会有任何数据丢失,因为旧的AOF文件在BGREWRITEAOF成功之前不会被修改。 
重写操作只会在没有其他持久化工作在后台执行时被触发。 
从Redis2.4开始,AOF重写由Redis自行触发,BGREWRITEAOF仅仅用于手动触发重写操作。

AOF默认情况下,也是和binlog日志一样增量往里面写的,测试如下:

127.0.0.1:6379> set name benent
OK

redis有16个库,0-15,默认是在0里面写的
[root@Redis01 redis]# cat appendonly.aof
*2
$6      (指的是下一个命令的字符数)
SELECT
$1
0  ( 先切进第0个大表)
*3
$3
set(之后的动作)
$4
name(之后的动作)
$6
benent(之后的动作)

127.0.0.1:6379> select 0
OK
127.0.0.1:6379> keys *
1) "name"
127.0.0.1:6379> select 1
OK
127.0.0.1:6379[1]> keys *
(empty list or set)
redis不像mysql有库名还有表名,可以理解成它只有(0-15)16张大表或者16个大库,刚开始是默认在第0张大表里,往里写的键都在那里面,select 1就相当于切换到1这个大表里了,所以里面没有,是空的

这就是aof文件里面记录的,但是它不好的地方也很突出

127.0.0.1:6379> select 0
OK
127.0.0.1:6379> del name
(integer) 1

再看一下aof是怎么记录的
[root@Redis01 redis]# cat appendonly.aof
*2
$6
SELECT
$1
0
*3
$3
set
$4
name
$6
benent
*2
$3
del
$4
name

我们发现虽然我们向redis添加了一个key,又删除了这个key。redis数据库从本质上来说并没有新增任何数据。但是aof文件仍旧把操作都给记录了。这样就会导致aof文件最终会非常大。所以aof文件的优化,就是让aof文件进行重写,只记录数据的增量部分。如此aof文件就小很多了。

完全复制了我之前的操作,但是在数据库里,一加一删是没用的,反而还会占大小,如果它一直这么记录下去,这个文件会越来越大,因此,在3.0之前运维都会写一个脚本,让它自动触发一个叫做bgrewriteaof,它的作用是优化aof,把所有的没有产生增量的aof文件里记录的数据全都删了
触发一下这个命令

里面就没东西了,将所有没有产生增量的语句全去掉了

但是4.0就不用了,它有自动触发

11.4 aof配置自动rewrite机制

在默认配置文件里,默认存在

获取aof-rewrite配置

127.0.0.1:6379> config get auto-aof-rewrite*
1) "auto-aof-rewrite-percentage"
2) "100"     #默认100%,也就是aof增加一倍后考虑rewrite,两个条件要同时满足
3) "auto-aof-rewrite-min-size"
4) "67108864"     #默认64mb,也就是aof达到64M后考虑rewirte,两个条件要同时满足

这就是为什么之前导入了一万条数据却发现aof并没有多大的原因
aof和binlog还有一个最大的不同是,binlog就记录之后的,aof一旦重写,它不光重写之后的,所有的键它都会写进去,aof文件是可以来进行数据迁移的,rdb是用来做主从复制的

[root@Redis01 ~]# for line in `seq -w 10000`;do redis-cli set key_${line} value
1_${line};done

刚开aof,如果它是增量的话,文件大小应该是0,如果它没有自动触发aof重写的话,它也是0,但是由于一万条太多了它就自动触发这个机制了,aof重写还用来数据迁移,也就是说aof现在是460k,里面所有的键都写到了aof里了,而且是增量写的,只要触发了aof,它是把redis里的所有的键重新写一遍

aof在工作中是用来做数据迁移的,rdb是用来做主从复制的

aof数据迁移也有很多种方式,如果能够ping通,直接建个从库数据就迁移过去了,比如要把redis从本地迁移到云上,在云上建一个从库,如果能连到公司里,数据自己就过去了,数据过去之后,再把它变成主库就行了,如果碰到不通的,数据连接不了,那就要把aof文件给弄过去。

十二,Redis最大内存设置和删除算法

redis-cli flushall #手动清空redis里所有数据

12.1 redis的键设置有效期,过期自动删除

127.0.0.1:6379> set name yunjisuan
OK
127.0.0.1:6379> get name
"yunjisuan"
127.0.0.1:6379> ttl name
(integer) -1
127.0.0.1:6379> expire name 5
(integer) 1
127.0.0.1:6379> ttl name
(integer) 3
127.0.0.1:6379> ttl name
(integer) 2
127.0.0.1:6379> ttl name
(integer) 1
127.0.0.1:6379> ttl name
(integer) 0
127.0.0.1:6379> ttl name
(integer) -2
127.0.0.1:6379> get name
(nil)

12.2 查看设置最大内存

查看和设定最大内存限制
127.0.0.1:6379> config get maxmemory
1) "maxmemory"
2) "0"      #默认对内存无限制

限制1M

127.0.0.1:6379> config set maxmemory 1M
OK
127.0.0.1:6379> config get maxmemory
1) "maxmemory"
2) "1000000"
127.0.0.1:6379> config rewrite
OK

12.3 可选择的删除算法

  • volatile-lru:

    • 使用LRU算法删除键(key需要设置过期时间)
  • volatile-random: 
    • 随机删除键(key需要设置过期时间)
  • volatile-ttl: 
    • 删除ttl最小的键(key需要设置过期时间)
  • allkeys-lru: 
    • 使用LRU算法删除键(所有key)
  • allkeys-random: 
    • 随机删除键(所有key)
  • noeviction: 
    • 不进行任何的操作,只返回错误,默认

[root@Redis01 ~]# redis-cli config get maxmemory-policy
1) "maxmemory-policy"
2) "noeviction"
在工作中最常用的是LRU算法,一旦内存不够用了,它会优先删除设了过期时间的键值

12.4 模拟超过内存

127.0.0.1:6379> keys *
(empty list or set)
127.0.0.1:6379> exit
[root@Redis01 ~]# for line in `seq -w 2000`;do redis-cli set key_${line} value_
${line};done

[root@Redis01 ~]# redis-cli info


到达了内存限制,已经不允许再往里面写了。

12.5 设置删除算法

将删除算法设置为volatile-lru

127.0.0.1:6379> config get maxmemory-policy
1) "maxmemory-policy"
2) "noeviction"
127.0.0.1:6379> config set maxmemory-policy volatile-lru
OK
127.0.0.1:6379> config get maxmemory-policy
1) "maxmemory-policy"
2) "volatile-lru"
127.0.0.1:6379> config rewrite
OK
127.0.0.1:6379> get key_0111
"value_0111"
127.0.0.1:6379> expire key_0111 3600
(integer) 1
127.0.0.1:6379> ttl key_0111
(integer) -2
127.0.0.1:6379> get key_0111
(nil)

说明:由上述测试可以发现volatile-lru算法,当内存到了最大值以后,会优先删除有过期时间的key。

十三,Redis禁用屏蔽危险命令

13.1 redis禁用的命令

FLUSHALL和FLUSHDB会清除redis的数据,比较危险 
KEYS在键过多的时候使用会阻塞业务请求

13.2 redis禁用危险命令配置代码如下(写入配置文件即可,此配置无法平滑更新)

rename-command  FLUSHALL " " #将命令改名成空

rename-command  FLUSHDB " "  #将命令改名成空

rename-command  KEYS " "     #将命令改名成空

[root@Redis01 ~]# echo 'rename-command  FLUSHALL ""' >> /usr/local/redis/conf/r
edis.conf[root@Redis01 ~]# echo 'rename-command  FLUSHDB ""' >> /usr/local/redis/conf/re
dis.conf[root@Redis01 ~]# echo 'rename-command  KEYS ""' >> /usr/local/redis/conf/redis
.conf[root@Redis01 ~]# tail -3 /usr/local/redis/conf/redis.conf
rename-command  FLUSHALL ""
rename-command  FLUSHDB ""
rename-command  KEYS ""

13.3 登陆redis,运行禁止命令进行测试

重启redis-server
[root@Redis01 ~]# redis-cli shutdown
[root@Redis01 ~]# redis-server /usr/local/redis/conf/redis.conf
测试被屏蔽的危险命令
如果测试本地不让登录了,如下图:

日志显示

因为我之前用过flushdb这个命令,aof记录了这个命令,如果要改名aof就不认识了

重写一下aof

十四,Redis主从服务器环境的搭建

主机名

IP

用途

Redis01

10.1.1.146

Redis-master

Redis02

10.1.1.147

Redis-slaveA

Redis03

10.1.1.148

Redis-slaveB

14.1 环境要求与redis基础编译部署调优

操作系统环境要求

三台redis都进行编译安装,三台都进行配置文件优化和简单的基础调优,三台的redis-server都启动

过程略,前面有写

基础调优设置:

[root@Redis03 redis]# echo "* - nofile 10240" >> /etc/security/limits.conf
[root@Redis03 redis]# echo "net.core.somaxconn = 10240" >> /etc/sysctl.conf
[root@Redis03 redis]# echo "vm.overcommit_memory = 1" >> /etc/sysctl.conf
[root@Redis03 redis]# sysctl -p
net.core.somaxconn = 10240
vm.overcommit_memory = 1
[root@Redis03 redis]# echo never > /sys/kernel/mm/transparent_hugepage/enabled
[root@Redis03 redis]# echo never > /sys/kernel/mm/transparent_hugepage/defrag
[root@Redis03 redis]# echo 'echo never > /sys/kernel/mm/transparent_hugepage/enabled'>>/etc/rc.local

[root@Redis03 redis]# echo 'echo never > /sys/kernel/mm/transparent_hugepage/defrag' >> /etc/rc.local

14.2 redis主从同步服务器搭建

redis的主从同步,不用修改master任何配置 
只需要在redis-slave上指定master的IP地址即可

先启动redis-master,将主的日志清空  > /data/redis/redis.log  一会主要是想看看日志信息的。然后再在两个redis-slave上都进行如下操作
[root@Redis02 redis]# redis-cli shutdown
[root@Redis02 redis]# echo "SLAVEOF 10.1.1.146 6379" >> /usr/local/redis/conf/redis.conf

[root@Redis02 redis]# tail -1 /usr/local/redis/conf/redis.conf
SLAVEOF 10.1.1.146 6379
[root@Redis02 redis]# > /data/redis/redis.log
[root@Redis02 redis]# redis-server /usr/local/redis/conf/redis.conf
[root@Redis02 redis]# ss -antup | grep redis
tcp    LISTEN     0      1024      *:6379                  *:*                 
  users:(("redis-server",pid=1449,fd=6))tcp    ESTAB      0      0      10.1.1.147:33796              10.1.1.146:6379  
              users:(("redis-server",pid=1449,fd=7))

14.3 主从同步日志分析(全量同步)查看redis-slave同步日志,查看redis-slave同步日志
查看日志信息:略,自己能看懂就行,看不懂百度单词,工作中是会经常看redis的日志信息的

keys *    从库里也有了数据

redis的主从复制原理:是在后台起一个进程并生成一个rdb文件,来把当前这个时刻的所有的内存数据给BGSAVE到内存里,并不是写到硬盘上,然后把这个rdb文件给从,redis的第一次同步方式都是全量同步,就是把所有数据都给从库

14.4 主从同步日志分析(部分同步)

如果是从宕了,不触发半同步,从宕了之后好了再连,还是全量,如果主宕了,从库就找不着了,这个时候主宕了之后再恢复,从就会找主做增量复制,就是部分同步
[root@Redis01 ~]# > /data/redis/redis.log
[root@Redis01 ~]# redis-cli shutdown
从的日志  略

14.5 主从同步的停止

[root@Redis02 ~]# redis-cli
127.0.0.1:6379> slaveof no one
OK
127.0.0.1:6379>
[root@Redis02 ~]# cat /data/redis/redis.log

恢复主从

127.0.0.1:6379> slaveof 10.1.1.146 6379
OK

14.6 加密的主从同步

1)为redis-master平滑设置连接密码

[root@Redis01 ~]# redis-cli config get requirepass
1) "requirepass"
2) ""
[root@Redis01 ~]# redis-cli config set requirepass 'yunjisuan'
OK
[root@Redis01 ~]# redis-cli config get requirepass
(error) NOAUTH Authentication required.
[root@Redis01 ~]# redis-cli auth yunjisuan
OK

查看从库日志信息

2)为从库提供主从同步密码验证

从服务器需要设置主从同步的认证密码

查看从服务器日志

十五,使用Python操作Redis单例

[root@Redis01 ~]# yum -y install epel-release
[root@Redis01 ~]# yum -y install python2-pip
[root@Redis01 ~]# pip install redis

15.2 利用python进行redis数据的读写

[root@Redis01 ~]# python
Python 2.7.5 (default, Apr 11 2018, 07:36:10)
[GCC 4.8.5 20150623 (Red Hat 4.8.5-28)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import redis
>>> r = redis.Redis(host='127.0.0.1',port=6379,password='yunjisuan',db=0)
>>> r.get('key_0008')
'value_0008'
>>> exit()

Redis4.0之持久化存储的更多相关文章

  1. Redis4.0 之持久化存储

    redis如果提供缓存服务,可以关闭所有持久化存储,如此一来redis重启后所有数据会丢失 开启rdb或aof持久化存储,能把redis中的数据持久化到磁盘中. rdb和aof对性能都有影响,所以建议 ...

  2. redis系列--redis4.0深入持久化

    前言 在之前的博文中已经详细的介绍了redis4.0基础部分,并且在memcache和redis对比中提及redis提供可靠的数据持久化方案,而memcache没有数据持久化方案,本篇博文将详细介绍r ...

  3. 自顶向下redis4.0(5)持久化

    redis4.0的持久化 目录 redis4.0的持久化 简介 正文 rdb持久化 save命令 bgsave命令 rdb定期保存数据 进程结束保存数据 aof持久化 数据缓冲区 刷新数据到磁盘 ap ...

  4. Redis4.0.0 安装及配置 (Linux — Centos7)

    本文中的两个配置文件可在这里找到 操作系统:Linux Linux发行版:Centos7 安装 下载地址,点这里Redis4.0.0.tar.gz 或者使用命令: wget http://downlo ...

  5. redis-4.0.8 配置文件解读

    # Redis configuration file example.## Note that in order to read the configuration file, Redis must ...

  6. centos7.5 安装 redis-4.0.11

    1.下载redis包 wget wget http://download.redis.io/releases/redis-4.0.11.tar.gz 2.解压安装 #解压 .tar.gz #安装 cd ...

  7. 阿里云 CentOS7安装redis4.0.9并开启远程访问

    1 安装redis编译的c环境 yum install gcc-c++ redis是c语言开发的,安装redis需要先将官网下载的源码进行编译,编译依赖gcc环境. 如果没有gcc环境,需要安装gcc ...

  8. Redis(二)CentOS7安装Redis4.0.10与集群搭建

    一 Redis单机安装 1 Redis下载安装 1.1 检查依赖环境(Redis是C语言开发,编译依赖gcc环境) [root@node21 redis-]$ gcc -v -bash: gcc: c ...

  9. linux下redis4.0.2安装与部署

    一.redis的介绍 Redis是当前比较热门的NOSQL系统之一,它是一个key-value存储系统.和Memcache类似,但很大程度补偿了Memcache的不足,它支持存储的value类型相对更 ...

随机推荐

  1. sublime text 3 前端开发常用插件

    sublime text 3 前端开发常用插件 https://packagecontrol.io/browse 代码对齐: Alignment html代码补全:  Emmet CoffeeScri ...

  2. 06点睛Spring MVC 4.1-文件上传

    6.1 文件上传 在控制器参数使用@RequestParam("file") MultipartFile file接受单个文件上传; 在控制器参数使用@RequestParam(& ...

  3. jstat介绍

    命令可用选项 ➜ ~ jstat -options -class -compiler -gc -gccapacity -gccause -gcmetacapacity -gcnew -gcnewcap ...

  4. consul服务注册与服务发现的巨坑

    最近使用consul作为项目的服务注册与服务发现的基础功能.在塔建集群使用中遇到一些坑,下面一个个的记录下来. consul集群多node consul集群的node也就是我们所说的consul实例. ...

  5. logstash kafka output 日志处理

    今天在用logstash解析日志并传送给kafka的时候,发现kafka能收到数据但数据内容已经丢失,具体如下: 在logstash output中增加输出样式之后,问题解决kafka再次接受到的内容 ...

  6. JavaScript图形实例:图形的旋转变换

    旋转变换:图形上的各点绕一固定点沿圆周路径作转动称为旋转变换.可用旋转角表示旋转量的大小. 旋转变换通常约定以逆时针方向为正方向.最简单的旋转变换是以坐标原点(0,0)为旋转中心,这时,平面上一点P( ...

  7. date.toLocaleString()的替换

    Date date = new Date(); System.out.println("前:" + date.toLocaleString()); SimpleDateFormat ...

  8. 题解 Luogu P1099 【树网的核】

    这题是真的水啊... ------------ 昨天模拟赛考了这题,很多人都是O($n^3$)水过,但我认为,要做就做的足够好(其实是我根本没想到O($n^3$)的做法),然后就开始想O(n)的解法. ...

  9. golang 管理 pidfile

    Pidfile 存储了进程的进程 id.一般情况下 pidfile 有以下几个作用: 其他进程可以读取 pidfile 获取运行进程的 pid(当然也可以通过其他命令 动态获取) 在启动进程前先检查 ...

  10. JAVA堆,栈的区别,用AarrayList、LinkedList自定义栈

    大家都知道java模拟机在运行时要开辟空间所以它有特定的五个内存划分: 1.寄存器:    2.本地方法区:    3.方法区:    4.栈内存:    5.堆内存: 但是我们今天来注重讲一下栈和堆 ...