一、redis数据库的基础介绍与对比
Redis(RemoteDictionaryServer,远程字典型)是一个开源的、使用C语言编写的NoSQL数据库。Redis 基于内存运行并支持持久化,采用 key-value(键值对)的存储形式,是目前分布式架构中不可或缺的一环。
1.非关系性数据库
NoSQL(NoSQL= Not Only SQL),意思是"不仅仅是 SQL",是非关系型数据库的总称。主流的 NoSQL 数据库有 Redis、MongBD、Hbase、CouhDB 等等。以上这些非关系型数据库,他们的存储方式、存储结构以及使用的场景都是完全不同的。所以我们认为它是一个非关系型数据库的集合,而不是像关系型数据库一样,是一个统称。换言之,除了主流的关系型数据库以外的数据库,都可以认为是非关系型的。NOSQL数据库凭借着其非关系型、分布式、开源及横向扩展等优势,被认为是下一代数据库产品。
2.关系型数据库
关系型数据库是一个结构化的数据库,创建在关系模型基础上,一般面向于记录。它借助于集合代数等数学概念和方法来处理数据库中的数据。关系模型就是指二维表格模型,因而一个关系型数据库就是由二维表及其之间的联系组成的一个数据组织。现实世界中,各种实体与实体之间的各种联系都可以用关系模型来表示。SQL语句(标准数据查询语言)就是一种基于关系型数据库的语言,用于执行对关系型数据库中数据的检索和操作。
3.非关系型数据库产生背景
随着 Web2.0网站的兴起,关系型数据库在应对 Web2.0网站,特别是海量数据和高并发的 SNS(Social Networking Services,即社交网络服务)类型的 Web2.0 纯动态网站时,暴露出很多难以解决的问题,例如三高问题。
(1)High performance--对数据库高并发读写需求
Web2.0网站会根据用户的个性化信息来实时生成动态页面和提供动态信息,因此无法使用动态页面静态化技术。所以数据库的并发负载非常高,一般会达到10000 次/s 以上的读写请求。关系型数据库对于上万次的查询请求还是可以勉强支撑的,但出现上万次的写数据请求,硬盘 I0 就已经无法承受了。对于普通的 BBS 网站,往往也会存在高并发的写数据请求。
(2)Huge Storage--对海量数据高效存储与访问需求
类似于 Facebook、Friendfeed 这样的 SNS 网站,每天会产生大量的用户动态信息。如 Friendfeed,一个月就会产生不少于 2.5亿条用户动态信息,对于关系型数据库来说,在一个包含 2.5亿条记录的表中执行SQL查询,查询效率是非常低的。
(3)High Scalability && High Availability--对数据库高可扩展性与高可用性需求
在Web 架构中,数据库是最难进行横向扩展的。当应用系统的用户量与访问量与日俱增时,数据库是没办法像 Web 服务一样,简单地通过添加硬件和服务器节点来扩展其性能和负载能力的。尤其对于一些需要 24小时对外提供服务的网站来说,数据库的升级与扩展往往伴随着停机维护与数据迁移,其工作量是非常庞大的。
关系型数据库和非关系型数据库都有各自的特点与应用场景,两者的紧密结合将会给Web2.0的数据库发展带来新的思路。让关系数据库关注在关系上,非关系型数据库关注在存储上。例如,在读写分离的 MySQL数据库环境中,可以把经常访问的数据存储在非关系型数据库中,提升访问速度。
4.Redis 的优点
具有极高的数据读写速度,数据读取的速度最高可达到 110000 次/s,数据写入速度最高可达到 81000 次/s。
支持丰富的数据类型,不仅仅支持简单的 key-value 类型的数据,还支持Strings,Lists,Hashes,Sets 及 Ordered Sets 等数据类型操作。
支持数据的持久化,可以将内存中的数据保存在磁盘中,重启的时候可以再次加载进行使用。
原子性,Redis 所有操作都是原子性的。
支持数据备份,即master-salve 模式的数据备份。
Redis 作为基于内存运行的数据库,缓存是其最常应用的场景之一。除此之外,Redis常见应用场景还包括获取最新 N个数据的操作、排行榜类应用、计数器应用、存储关系、实时分析系统、日志记录。
二、redis的安装及优化
1:安装
[root@localhost ~]# systemctl stop firewalld //实验环境,关闭防火墙没有影响,生产环境中不建议关闭,尽量是添加防火墙策略
[root@localhost ~]# setenforce 0 //关闭内核,内核会阻挡应用的运行
[root@localhost ~]# yum -y install gcc* zlib-devel //下载解压tar包所需的工具
[root@localhost ~]# tar xvzf redis-4.0.9.tar.gz //redis是一个开源免费的应用,官网即可下载此包
[root@localhost ~]# cd redis-4.0.9/
[root@localhost redis-4.0.9]# make
注意:
在make的时候,可能会出现如下错误提示:
解决方法1:用make MALLOC=libc指定内存分配器为 libc进行编译
解决方法2:make clean && make distclean
[root@localhost redis-4.0.9]# make PREFIX=/usr/local/redis install
[root@localhost ~]# ln -s /usr/local/redis/bin/* /usr/local/bin/
[root@localhost redis-4.0.9]# cd /root/redis-4.0.9/utils/
[root@localhost utils]# ./install_server.sh
备注:
Config file : /etc/redis/6379.conf //配置文件路径
Log file : /var/log/redis_6379.log //日志文件路径
Data dir : /var/lib/redis/6379 //数据文件路径
Executable : /usr/local/redis/bin/redis-server //可执行文件路径
Cli Executable : /usr/local/redis/bin/redis-cli //客户端命令行工具
2:查看进程
[root@localhost utils]# netstat -anpt | grep redis
3:服务控制
[root@localhost ~]#/etc/init.d/redis_6379 stop
[root@localhost ~]#/etc/init.d/redis_6379 start
[root@localhost ~]#/etc/init.d/redis_6379 restart
[root@localhost ~]#/etc/init.d/redis_6379 status
4:配置参数的修改
[root@localhost ~]#vim /etc/redis/6379.conf
bind 127.0.0.1 192.168.10.101 //监听的主机地址
port 6379 //端口
daemonize yes //启用守护进程
pidfile /var/run/redis_6379.pid //指定 PID 文件
loglevel notice //日志级别
logfile /var/log/redis_6379.log //指定日志文件
[root@localhost~]#/etc/init.d/redis_6379 restart
[root@localhost utils]# netstat -anpt | grep redis
三、Redis 命令工具
Ø redis-server:用于启动 Redis 的工具;
Ø redis-benchmark:用于检测 Redis 在本机的运行效率;
Ø redis-check-aof:修复 AOF 持久化文件;
Ø redis-check-rdb:修复 RDB 持久化文件;
Ø redis-cli:Redis 命令行工具。
1:redis-cli 命令行工具
(1)连接本机redis
[root@localhost ~]# redis-cli
127.0.0.1:6379>
(2)测试redis服务是否启动
127.0.0.1:6379> ping
PONG
(3)远程连接
[root@localhost ~]#redis-cli -h 192.168.10.101 -p 6379
2:获取帮助
Ø help @<group>:获取<group>中的命令列表;
Ø help <command>:获取某个命令的帮助;
Ø help <tab>:获取可能帮助的主题列表。
备注:
Ø help <tab>:获取可能帮助的主题列表。
输入help后,按下tab键
(1)查看所有与 List 数据类型的相关命令
127.0.0.1:6379>help @list
(2)查看 set 命令的命令帮助
127.0.0.1:6379>help set
3:redis-benchmark 测试工具
redis-benchmark 是官方自带的 Redis 性能测试工具,可以有效的测试 Redis 服务的性能。
Ø -h:指定服务器主机名;
Ø -p:指定服务器端口;
Ø -s:指定服务器 socket;
Ø -c:指定并发连接数;
Ø -n:指定请求数;
Ø -d:以字节的形式指定 SET/GET 值的数据大小;
Ø -k:1=keep alive 0=reconnect;
Ø -r:SET/GET/INCR 使用随机 key, SADD 使用随机值;
Ø -P:通过管道传输<numreq>请求;
Ø -q:强制退出 redis。仅显示 query/sec 值;
Ø --csv:以 CSV 格式输出;
Ø -l:生成循环,永久执行测试;
Ø -t:仅运行以逗号分隔的测试命令列表;
Ø -I:Idle 模式。仅打开 N 个 idle 连接并等待。
(1)测试请求性能
[root@localhost ~]#redis-benchmark -h 192.168.10.101 -p 6379 -c 100 -n 100000 //向 IP 地址为 192.168.10.101、端口为6379 的 Redis 服务器发送 100 个并发连接与100000 个请求测试性能
备注:
Ø -h:指定服务器主机名;
Ø -p:指定服务器端口;
Ø -c:指定并发连接数;
Ø -n:指定请求数;
====== MSET (10 keys) ======
100000 requests completed in 1.02 seconds
100 parallel clients ##100个并发连接
3 bytes payload
keep alive: 1
87.25% <= 1 milliseconds ##87.25%的命令执行时间小于等于1毫秒
99.90% <= 2 milliseconds
100.00% <= 2 milliseconds
97943.19 requests per second #每秒的请求数
(2)测试存取性能
[root@localhost ~]#redis-benchmark -h 192.168.10.101 -p 6379 -q -d 100
备注:
Ø -h:指定服务器主机名;
Ø -p:指定服务器端口;
Ø -d:以字节的形式指定 SET/GET 值的数据大小;
Ø -q:强制退出 redis。仅显示 query/sec 值;
PING_INLINE: 121506.68 requests per second //每秒完成多少次PING操作
PING_BULK: 124378.11 requests per second
SET: 121654.50 requests per second //每秒完成多少次SET key vlaue
GET: 122100.12 requests per second //每秒完成多少次GET key vlaue
INCR: 118764.84 requests per second //每秒完成多少次原子计数
LPUSH: 112612.61 requests per second
RPUSH: 118623.96 requests per second
LPOP: 107874.87 requests per second
RPOP: 114416.48 requests per second
SADD: 123304.56 requests per second
HSET: 122249.38 requests per second
SPOP: 128040.97 requests per second
LPUSH (needed to benchmark LRANGE): 116686.12 requests per second
LRANGE_100 (first 100 elements): 40016.00 requests per second
LRANGE_300 (first 300 elements): 11991.85 requests per second
LRANGE_500 (first 450 elements): 7381.71 requests per second
LRANGE_600 (first 600 elements): 5230.67 requests per second
MSET (10 keys): 92421.44 requests per second //每秒多个key vlaue请求次数
(3)set 与 lpush 操作性能
[root@localhost ~]# redis-benchmark -t set,lpush -n 100000 -q //测试本机上 Redis 服务在进行 set 与 lpush 操作时的性能。
备注:
Ø -n:指定请求数;
Ø -q:强制退出 redis。仅显示 query/sec 值;
Ø -t:仅运行以逗号分隔的测试命令列表;
SET: 121951.22 requests per second
LPUSH: 127226.46 requests per second
四、Redis 数据库常用命令
Ø set:存放数据,基本的命令格式为 set key value。
Ø get:获取数据,基本的命令格式为 get key。
1 . key 相关命令
在 Redis 数据库中,与 key 相关的命令主要包含以下几种。
(1)添加键值对
使用 keys 命令可以取符合规则的键值列表,通常情况可以结合*、?等选项来使用。
127.0.0.1:6379>set k1 1
OK
127.0.0.1:6379>set k2 2
OK
127.0.0.1:6379>set k3 3
OK
127.0.0.1:6379>set v1 4
OK
127.0.0.1:6379>set v5 5
OK
(2)查看当前数据库中所有键
127.0.0.1:6379>KEYS *
-
"teacher"
-
"k1"
-
"k2"
-
"k3"
-
"v1"
-
"v5"
127.0.0.1:6379>set v22 5
OK
(3)查看当前数据库中以 v 开头的数据
127.0.0.1:6379>KEYS v*
-
"v1"
-
"v5"
-
"v22"
(4)查看当前数据库中以 v 开头后面包含任意一位的数据
127.0.0.1:6379>KEYS v?
-
"v1"
-
"v5"
(5)查看当前数据库中以 v 开头 v 开头后面包含任意两位的数据
127.0.0.1:6379>KEYS v??
- "v22"
2: exists
exists 命令可以判断键值是否存在
127.0.0.1:6379>exists teacher
(integer) 1
结果为1,表示 teacher 键是存在
127.0.0.1:6379>exists tea
(integer) 0
结果为0,表示 tea 键不存在
3:del
del 命令可以删除当前数据库的指定 key
127.0.0.1:6379>keys *
-
"teacher"
-
"v1"
-
"v22"
-
"k3"
-
"k1"
-
"k2"
-
"v5"
127.0.0.1:6379> del v5
(integer) 1
127.0.0.1:6379>get v5
(nil)
4: type
使用 type 命令可以获取 key 对应的 value 值类型
127.0.0.1:6379>type k1
string
备注:
redis支持的数据类型
- String:最简单的类型,就是普通的set和get,作key value缓存。
- Hash:类似map的一种结构,一般就是可以将结构化的数据,比如一个对象给缓存在redis里
- List:List是有序列表,可以通过list存储一些列表型的数据结构,类似粉丝列表、文章的评论列表之类的东西
- Set:Set是无序集合,自动去重。
- Sorted Set:Sorted Set是排序的set,去重但可以排序,写进去的时候给一个分数,自动根据分数排序。
5: rename
rename 命令是对已有 key 进行重命名
在实际使用过程中,建议先用 exists 命令查看目标 key 是否存在,然后再决定是否执行 rename 命令,以避免覆盖重要数据
127.0.0.1:6379>keys v*
-
"v1"
-
"v22"
127.0.0.1:6379>rename v22 v2
OK
127.0.0.1:6379>keys v*
-
"v1"
-
"v2"
127.0.0.1:6379>get v1
"4"
127.0.0.1:6379>get v2
"5"
127.0.0.1:6379>rename v1 v2
OK
127.0.0.1:6379>get v1
(nil)
127.0.0.1:6379>get v2
"4"
6: renamenx
renamenx 命令的作用是对已有 key 进行重命名,并检测新名是否存在。
使用renamenx 命令进行重命名时,如果目标 key 存在则不进行重命名。
127.0.0.1:6379>keys *
-
"teacher"
-
"k3"
-
"k1"
-
"k2"
-
"v2"
127.0.0.1:6379>get teacher
"zhanglong"
127.0.0.1:6379>get v2
"4"
127.0.0.1:6379>renamenx v2 teacher
(integer) 0
127.0.0.1:6379>keys *
-
"teacher"
-
"k3"
-
"k1"
-
"k2"
-
"v2"
127.0.0.1:6379>get teacher
"zhanglong"
127.0.0.1:6379>get v2
"4
7: dbsize
dbsize 命令的作用是查看当前数据库中 key 的数目。
127.0.0.1:6379> dbsize
(integer) 5
五、多数据库常用命令
1:多数据库间切换
Redis 在没有任何改动的情况下默认包含 16 个数据库,数据库名称是用数字 0-15 来依次命名的
(1)切换至序号为 10 的数据库
127.0.0.1:6379>select 10
OK
(2)切换至序号为 15 的数据库
127.0.0.1:6379[10]>select 15
OK
(3)切换至序号为 0 的数据库
127.0.0.1:6379[15]>select 0
2:多数据库间移动数据
Redis 的多数据库在一定程度上是相对独立的,例如在数据库 0 上面存放 k1 的数据,在其它 1-15 的数据库上是无法查看到的。
127.0.0.1:6379>set k1 100
OK
127.0.0.1:6379>get k1
"100"
127.0.0.1:6379>select 1
OK
127.0.0.1:6379[1]>get k1
(nil)
127.0.0.1:6379[1]>select 0 //切换至目标数据库 0
OK
127.0.0.1:6379>get k1 //查看目标数据是否存在
"100"
127.0.0.1:6379>move k1 1 //将数据库 0 中 k1 移动到数据库 1 中
(integer) 1
127.0.0.1:6379>select 1 //切换至目标数据库 1
OK
127.0.0.1:6379[1]>get k1 //查看被移动数据
"100"
127.0.0.1:6379[1]> select 0
OK
127.0.0.1:6379> get k1 //在数据库 0 中无法查看到 k1 的值
(nil)
3:清除数据库内数据
清空当前数据库数据,使用 FLUSHDB
命令实现;清空所有数据库的数据,使用 FLUSHALL 命令实现
六、Redis 持久化
Redis 的所有数据都是保存在内存中,然后不定期的通过异步方式保存到磁盘上(这称为"半持久化模式");也可以把每一次数据变化都写入到一个 append only file(aof)里面(这称为"全持久化模式")。
由于 Redis 的数据都存放在内存中,如果没有配置持久化,Redis 重启后数据就全丢失了。所以,需要开启 Redis 的持久化功能,将数据保存到磁盘上,当 Redis 重启后,可以从磁盘中恢复数据。Redis 提供两种方式进行持久化,一种是 RDB(Redis DataBase) 持久化(原理是将 Reids在内存中的数据库记录定时 dump 到磁盘上的 RDB 持久化),另外一种是 AOF(append only file)持久化(原理是将 Reids 的操作日志以追加的方式写入文件)。
1: RDB 和 AOF 的区别
(1)RDB是什么?
默认采用的方法
RDB持久化是把当前进程数据生成快照保存到硬盘的过程,触发RDB持久化过程分为手动触发和自动触发。
触发机制:手动触发分别对应为save和bgsave命令
save命令:阻塞当前Redis服务器,直到RDB过程完成为止,对于内存比较多的实例会造成时间阻塞。线上环境不建议使用。
bgsave命令:Redis进程执行fork(用于创建进程的函数)操作创建子进程,RDB持久化过程由子进程负责,完成后自动结束。阻塞只发生在fork阶段。
(2)RDB的优缺点:
RDB的优点:
RDB是一个紧凑压缩的二进制文件,代表Redis在某一个时间点上的数据快照。非常适用于备份,全量复制等场景。比如每6小时执行bgsave备份,并把RDB文件拷贝到远程机器或者文件系统中,用于灾难恢复。
Redis加载RDB恢复数据远远快于AOF方式。
RDB的缺点:
RDB方式数据没办法做到实时持久化/秒级持久化。因为bgsave每次运行都有执行fork操作创建子进程,属于重量级操作,频繁执行成本过高。
RDB文件使用特定二进制格式保存,Redis版本演进过程中有多个格式的RDB版本,存在老版本Redis服务无法兼容新版RDB格式的问题。
二、AOF是什么
AOF(append only file)持久化:以独立日志的方式记录每次写命令,重启时再重新执行AOF文件中命令达到恢复数据的目的。AOF的主要作用是解决了数据持久化的实时性,目前已经是Redis持久化的主流
二者选择的标准:
牺牲一些性能,换取更高的缓存一致性(AOF),
写操作频繁的时候,不启用备份来换取更高的性能,待手动运行 save 的时候,再做备份(RDB)
备注:
如果redies重启之后,需要加载一个持久化文件,有限会选择AOF文件。
如果先开启了RDB,再开启AOF,RDB先执行了持久化,那么RDB文件中的内容会被AOF覆盖掉。
3: Redis 持久化配置
(1) RDB 持久化配置
[root@localhost ~]# vim /etc/redis/6379.conf
打开 6379.conf 文件之后,搜索 save,可以看到如下所示配置信息。
- Ø save 900 1:在 900 秒(15 分钟)之后,如果至少有 1 个 key 发生变化,则 dump内存快照。
- Ø save 300 10:在 300 秒(5 分钟)之后,如果至少有 10 个 key 发生变化,则 dump内存快照。
- Ø save 60 10000:在 60 秒(1 分钟)之后,如果至少有 10000 个 key 发生变化,则dump 内存快照。
- dbfilename dump.rdb :RDB文件名称 ##254行
- dir /var/lib/redis/6379 :RDB文件路径 ##264行
- rdbcompression yes :是否进行压缩 ##242行
(2)AOF 持久化配置
在 Redis 的配置文件中存在三种同步方式,它们分别是:
- appendonly yes :开启AOF持久化(默认为no) ##673行
- appendfilename "appendonly.aof " :AOF文件名称 ##677行
-
appendfsync always
- appendfsync everysec
-
appendfsync no
always:同步持久化,每次发生数据变化会立刻写入磁盘
everysec:默认推荐,每秒异步记录一次(默认值)
no:不同步,交给操作系统决定如何同步
- aof-load-truncated yes ##769行
忽略最后一条可能存在问题的指令
[root@localhost ~]#/etc/init.d/redis_6379 restart
(2)AOF重写
为了解决 AOF 文件体积不断增大的问题,用户可以向 Redis 发送 BGREWRITEAOF命令。BGREWRITEAOF 命令会通过移除 AOF 文件中的冗余命令来重写(rewrite)AOF文件,使 AOF 文件的体积尽可能地变小。
127.0.0.1:6379> bgrewriteaof
Background append only file rewriting started
在日志进行BGREWRITEAOF时,如果no-appendfsync-on-rewrite设置为yes表示新写操作不进行同步fsync,只是暂存在缓冲区里,避免造成磁盘IO操作冲突,等重写完成后再写入。Redis中默认为no
no-appendfsync-on-rewrite no
当前AOF文件大小是上次日志重写时AOF文件大小两倍时,发生BGREWRITEAOF操作
auto-aof-rewrite-percentage 100
备注:
100指的是aof文件增长比例,指当前aof文件比上次重写的增长比例大小,100为两倍
#当前AOF文件执行BGREWRITEAOF命令的最小值,避免刚开始启动Reids时由于文件尺寸较小导致频繁的BGREWRITEAOF
auto-aof-rewrite-min-size 64mb
七、性能管理
1:查看内存信息
192.168.9.236:7001> info memory
used_memory:1210776 #已经内存使用的大小,以字节为单位
used_memory_human:1.15M # 带单位展示,以M为单位
used_memory_rss:7802880 # 从操作系统角度看redis内存占用多少
used_memory_rss_human:7.44M # 带单位展示
maxmemory:1073741824 # 最大内存大小
maxmemory_human:1.00G # 带单位展示
2:回收策略
maxmemory-policy:回收策略
Ø volatile-lru:它允许 Redis 从整个数据集中挑选最近最少使用的 key 进行删除
Ø volatile-ttl:按照key的过期时间进行淘汰
Ø volatile-random:从已设置过期时间的数据集合中随机挑选数据淘汰;
Ø allkeys-lru:使用 LRU 算法从所有数据集合中淘汰数据;
Ø allkeys-random:从数据集合中任意选择数据淘汰;
Ø noeviction:禁止淘汰数据(默认值)
备注:
设置key的过期时间
expire v1 10
v1的过期时间为10秒
备注:
当 Redis 由于内存压力需要回收一个 key 时,Redis 首先考虑的不是回收最旧的数据,而是在最近最少使用的 key 或即将过期的 key 中随机选择一个 key,从数据集中删除
八、redis设置密码
1:设置方法
** 方法一. 通过配置文件redis.conf设置密码**
找到requirepass关键字,后面就是跟的密码,默认情况下是注释掉的,即默认不需要密码,如下:
打开注释,设置为自己的密码,重启即可
** 方法二. 通过命名设置密码**
使用redis-cli连接上redis,执行如下命令
config set requirepass 123456
执行完毕,无需重启,退出客户端,重新登录就需要输入密码了
2.连接方法
1. 连接时输入密码
[root@localhost bin]# ./redis-cli -a 123456
2. 先连接再输入密码
[root@localhost bin]# ./redis-cli127.0.0.1:6379> auth 123456
3:关闭方法
[root@localhost bin]# ./redis-cli -a 123456 shutdown
4:区别
1)修改配置文件设置的密码永久生效;使用命令设置的密码临时生效,重启后失效
2)修改配置文件设置的密码,需要重启生效;使用命令设置的密码,退出后再登录生效,重启后失效
3)命令的优先级高于配置文件的优先级