一、什么是非关系型数据库
- 要理解什么是非关系型数据库,那么就不得不提到什么是关系型数据库
(1)关系型数据库
- 关系型数据库是一个结构化的数据库,创建在关系模型基础上,一般是面向于记录的,也叫SQL数据库,他的数据存放结构一般为:库——表——数据,例如:Oracle、Mysql、Sql Server、DB2这种都属于关系型数据库
(2)非关系型数据库
一般来说,除了主流的关系型数据库以外的数据库都被认为是非关系型的,非关系数据库也叫NoSQL数据库,从字面意思来看就是Not-Only SQL,这种数据库一般是作为SQL数据库的良好补充。
为什么要学习并且使用NoSQL数据库呢,因为随着互联网web2.0网站的兴起,NoSQL数据库已经成为了一个极其热门的领域,NoSQL数据库支持超大规模的数据存储,并且可以很好的支持web2.0网站和应用,正是因为如此,NoSQL数据库产品发展非常迅速,SQL数据库在应付web2.0网站特别是超大规模的高并发的SNS(社会性网络服务)类型的web2.0纯动态网站时,已经是力不从心了,从而暴露了SQL数据库很多难以克服的问题,这个时候就需要去使用NoSQL数据库去代替一些传统的SQL数据库。NoSQL数据库的数据存放结构常用的有:键值对(key-value)、列存储、文档、图形(graph)
NoSQL数据库例如有:Redis、MongBD、Hbase、CouhDB等
(3)非关系型数据库产生背景
-High performance——对数据库高并发读写需求
web2.0网站要根据用户个性化信息来实时生成动态页面和提供动态信息,所以基本上无法使用动态页面静态化技术,因此数据库并发负载非常高,往往要达到每秒上万次读写请求。 关系数据库应付上万次SQL查询还勉强顶得住,但是应付上万次SQL写数据请求,硬盘IO就已经无法承受了。 其实对于普通的BBS网站,往往也存在对高并发写请求的需求,例如网站的实时统计在线用户状态,记录热门帖子的点击次数,投票计数等,因此这是一个相当普遍的需求。
-Huge Storage——对海量数据高效存储与访问需求
类似Facebook,twitter,Friendfeed这样的SNS网站,每天用户产生海量的用户动态,以Friendfeed为例,一个月就达到了2.5亿条用户动态, 对于关系数据库来说,在一张2.5亿条记录的表里面进行SQL查询,效率是极其低下乃至不可忍受的。 再例如大型web网站的用户登录系统,例如腾讯,盛大,动辄数以亿计的帐号,关系数据库也很难应付。
-High Scalability && High Availability——对数据库高可扩展性与高可用性需求
在基于web的架构当中,SQL数据库是最难进行横向扩展的,当一个应用系统的用户量和访问量与日俱增的时候,你的数据库却没有办法像web server和app server那样简单的通过添加更多的硬件和服务节点来扩展性能和负载能力。对于很多需要提供24小时不间断服务的网站来说,对数据库系统进行升级和扩展是非常痛苦的事情,往往需要停机维护和数据迁移,为什么数据库不能通过不断的添加服务器节点来实现扩展呢?NoSQL的出现就是为了解决这一难题。
-总结
NoSQL数据库就是为了解决大规模数据集合多重数据种类带来的挑战,尤其是大数据应用难题而产生的。
本次讲述的就是采用键值对(key-value)存储形式的NoSQL数据库——Redis
二、Redis简介
- Redis基于内存运行并支持持久化,采用键值对(key-value)的存储形式
(1)优点
具有极高的数据读写速度
Redis是将数据存放到内存中,由于内存的存取速度快, 所以Redis被广泛应用在互联网项目中。
Redis官方称:Redis的读取速度会达到30万次每秒,写的速度在10万次每秒,具体局限主要看硬件
支持丰富的数据类型
Redis是用C语言开发的一个开源的高性能的键值对(key-value)数据库。
Redis通过提供多种键值数据类型来适应不同场景下的存储需求,目前为止,Redis支持的键值数据类型如下:
字符串类型、散列类型、列表类型、集合类型
支持数据的持久化
Redis可以将内存中的数据异步写入到硬盘中,同时不影响继续提供服务, 但是Redis对持久化的支持不够好,所以一般来说Redis是配合传统的SQL数据库去使用的
原子性
Redis的所有操作都是原子性的(要么完整的执行,要么全不执行)
支持数据备份
master/slave模式的数据备份(主从备份)
功能丰富
Redis可以为每一个键设置生存时间,时间到期后该键被自动删除, 这一功能配合出色的性能让Redis可以作为缓存服务器来使用。而作为缓存服务器,Redis还可以限定数据占用的最大内存空间, 在数据达到空间限制后可以按照一定的规则自动淘汰不需要的键。Redis的列表类型键可以用来实现队列,并且支持阻塞式读取, 可以很容易的实现一个高性能的优先级队列。此外, Redis还支持“发布/订阅”的消息模式。
(2)Redis的应用场景
缓存、分布式集群架构中的session分离、聊天室的在线好友列表、任务队列、应用排行榜、网站访问统计、数据过期处理等。
(3)搭建Redis数据库
本实验使用cetnos7.*版本
******(1)先做基础配置 [root@centos7-007 ~]# hostnamectl set-hostname redis [root@centos7-007 ~]# su [root@redis ~]# systemctl stop firewalld [root@redis ~]# setenforce 0 setenforce: SELinux is disabled [root@redis ~]# mount /dev/cdrom /media/cdrom/ mount: /dev/sr0 写保护,将以只读方式挂载 ******(2)上传redis源码包,解压、配置、编译、安装 [root@redis ~]# ll 总用量 1516 -rw-------. 1 root root 1220 9月 3 2020 anaconda-ks.cfg -rw-r--r-- 1 root root 1547695 3月 7 06:01 redis-3.2.9.tar.gz [root@redis ~]# tar xf redis-3.2.9.tar.gz -C /usr/src/ [root@redis ~]# cd /usr/src/redis-3.2.9/ [root@redis redis-3.2.9]# ls 00-RELEASENOTES INSTALL runtest tests BUGS Makefile runtest-cluster utils CONTRIBUTING MANIFESTO runtest-sentinel COPYING README.md sentinel.conf deps redis.conf src [root@redis redis-3.2.9]# make && make install (我的这个源码包提供了makefile的文件,所以可以直接进行编译安装) [root@redis redis-3.2.9]# cd utils/ [root@redis utils]# ls build-static-symbols.tcl lru cluster_fail_time.tcl redis-copy.rb corrupt_rdb.c redis_init_script create-cluster redis_init_script.tpl generate-command-help.rb redis-sha1.rb hashtable releasetools hyperloglog speed-regression.tcl install_server.sh whatisdoing.sh [root@redis utils]# ./install_server.sh (执行脚本)输入六次回车 Welcome to the redis service installer This script will help you easily set up a running redis server Please select the redis port for this instance: [6379] (默认监听端口——回车) Selecting default: 6379 Please select the redis config file name [/etc/redis/6379.conf] (默认配置文件——回车) Selected default - /etc/redis/6379.conf Please select the redis log file name [/var/log/redis_6379.log] (默认日志文件——回车) Selected default - /var/log/redis_6379.log Please select the data directory for this instance [/var/lib/redis/6379] (默认数据库目录——回车) Selected default - /var/lib/redis/6379 Please select the redis executable path [/usr/local/bin/redis-server] (执行命令——回车) Selected config: Port : 6379 Config file : /etc/redis/6379.conf Log file : /var/log/redis_6379.log Data dir : /var/lib/redis/6379 Executable : /usr/local/bin/redis-server Cli Executable : /usr/local/bin/redis-cli Is this ok? Then press ENTER to go on or Ctrl-C to abort. Copied /tmp/6379.conf => /etc/init.d/redis_6379 Installing service... Successfully added to chkconfig! Successfully added to runlevels 345! Starting Redis server... Installation successful! [root@redis utils]# /etc/init.d/redis_6379 start (启动redis) Starting Redis server... [root@redis utils]# netstat -anpt | grep redis (检查端口号,确认是否已经成功启动) tcp 0 0 127.0.0.1:6379 0.0.0.0:* LISTEN 4678/redis-server 1 [root@redis utils]# cd ******(3)可以通过脚本来管理redis的状态 [root@redis ~]# /etc/init.d/redis_6379 status Redis is running (4678) [root@redis ~]# /etc/init.d/redis_6379 stop Stopping ... Redis stopped [root@redis ~]# /etc/init.d/redis_6379 start Starting Redis server... [root@redis ~]# /etc/init.d/redis_6379 status Redis is running (4690) ******(4)编辑redis的主配置文件,绑定本地的ip地址 [root@redis ~]# vim /etc/redis/6379.conf (编辑主配置文件) 。。。。。。 61 # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~ 62 bind 127.0.0.1 192.168.100.7 (添加本机地址) 63 64 # Protected mode is a layer of security protection, in order to avoid that 。。。。。。 保存退出 ******(5)重启redis [root@redis ~]# /etc/init.d/redis_6379 restart (利用脚本重启redis) Stopping ... Redis stopped Starting Redis server... [root@redis ~]# netstat -anpt | grep redis (再次查看端口号) tcp 0 0 192.168.100.7:6379 0.0.0.0:* LISTEN 4704/redis-server 1 tcp 0 0 127.0.0.1:6379 0.0.0.0:* LISTEN 4704/redis-server 1 至此redis搭建完成!!!!
-主配置文件详解
******利用grep查看redis的主配置文件 [root@redis ~]# cat /etc/redis/6379.conf | grep -v "^#" | grep -v "^$" bind 127.0.0.1 192.168.100.7 ——(监听的ip地址) protected-mode yes ——(是否开启保护模式,默认是开启的,如果已经指定bind和密码那么只会在本地进行访问而拒绝外部访问,如果没有指定bind和密码那么这个选项最好关闭) port 6379 ——(监听的端口号) tcp-backlog 511 ——(TCP连接中已经完成队列的长度,即完成三次握手之后的长度) timeout 0 ——(当客户端空闲超过指定时间后,服务器会断开连接,如果为0则不会主动断开连接) tcp-keepalive 300 ——(定时给对端的端口发送ack,检测到对端关闭需要两倍的设置值) daemonize yes ——(守护进程模式) supervised no ——(是否可以通过upstart和systemd管理redis守护进程) pidfile /var/run/redis_6379.pid ——(redis进程的pi文件) loglevel notice ——(指定了服务端日志的级别,即:notice表示适当的日志级别适合生产环境,debug表示很多信息方便开发和测试,verbose表示许多有用的信息但是没有debug的信息多,warn表示只有非常重要的信息) logfile /var/log/redis_6379.log ——(指定了redis记录日志的文件) databases 16 ——(数据库的数量,默认使用的数据库是DB0) save 900 1 ——(save项是数据持久化配置,将内存中的数据写入到数据库中,900 1即表示900秒内只要发生1个key值的变化就进行数据保存) save 300 10 save 60 10000 stop-writes-on-bgsave-error yes ——(当RDB持久化出现错误后是否依然进行工作) rdbcompression yes ——(是否使用压缩rdb文件,rdb文件压缩使用LZF压缩算法,即:yes表示使用压缩但是会消耗一定的cpu资源,no表示不压缩但是需要更多的存储空间) rdbchecksum yes ——(是否校验rdb文件,开启这个项会有%10的性能损耗但是更有利于rdb文件的容错性,如果追求高性能建议关闭) dbfilename dump.rdb ——(指定rdb文件的名称) dir /var/lib/redis/6379 ——(指定数据目录,数据库的写入、rdb文件、aof文件都会写在这个目录) slave-serve-stale-data yes ——(在从库和主机失去连接或者复制正在进行时,从机库有两种运行方式,即:yes表示从库会继续响应客户端的请求,no表示出去INFO和SLAVOF命令之外的任何请求都会返回错误信息”SYNC with master in progress”) slave-read-only yes ——(作为从服务器,yes表示只读也是默认的,no用于写但是不建议修改) repl-diskless-sync no ——(是否使用socket方式复制数据,在磁盘速度缓慢,网速快的情况下推荐使用) repl-diskless-sync-delay 5 ——(指定diskless复制的延迟时间,防止设置为0,一旦复制开始,节点不会再接收新的slave的复制请求,直到下一个rdb传输,所以最好等待一段时间,等待更多的slave连上来) repl-disable-tcp-nodelay no ——(是否禁止复制tcp链接的tcp nodelay参数,默认是no,即使用tcp nodelay参数,如果选择yes那么在把数据复制给slave的时候,会减少包的数量和更小的网络宽带,可能会带来数据延迟,所以默认选择低延迟,在数据量传输很大的场景下推荐使用yes) slave-priority 100 ——(指定slave的优先级,当master不可用时,Sentinel会根据slave优先级选举master,最低的优先级选举为master,如果配置成0则永远不会被选举) appendonly no ——(是否使用append only file的持久化方式,redis默认使用的持久化方式是rdb,这种方式在许多应用中已经足够了,但是在服务器宕机时还是会操作几分钟的数据丢失,并且rdb根据save来策略进行持久化,而append only file提供更好的持久化方式,但是开启后redis每次都会先把appendonly.aof文件存入内存,会忽略rdb文件) appendfilename "appendonly.aof" ——(指定aof文件名) appendfsync everysec ——(指定aof持久化策略,everysec表示每秒执行一次同步,可能会丢失这1秒的数据,always表示每次写入都执行一次同步,no则表示不执行同步,由操作系统保证数据同步到磁盘,速度最快) no-appendfsync-on-rewrite no ——(配置是否不在rewrite期间对新写操作不进行同步,对延迟要求很高的应用,可以配置为yes,为yes即表示在rewrite完成后在进行写入,默认为no,但是linux默认策略是30秒进行同步,可能会丢失30秒的数据所以建议选择yes) auto-aof-rewrite-percentage 100 ——(aof自动重写配置,当前aof文件大小是上次日志重写得到aof文件大小的两倍(设置为100时),会自动启动新的日志重写过程) auto-aof-rewrite-min-size 64mb ——(设置运行重写的最小aof文件的大小,此项可以避免达到约定百分比但是尺寸依然很小的情况下还要重写) aof-load-truncated yes ——(选择yes则表示截断的aof文件被导入时,会自动发布一个log日志给客户端然后load保存,如果是no则表示用户必需手动输入redis-check-aof修复aof文件才可以) lua-time-limit 5000 ——(配置最大时间限制,当达到最大时间redis会记个log日志,然后返回error错误) slowlog-log-slower-than 10000 ——(slowlog用来记录redis运行中执行比较慢的命令耗时,当命令的执行超过配置的时间,就会记录在slow log中,slow log保存在内存里,所以没有I/O操作。注意:这个单位是微秒即1000000微妙 = 1秒) slowlog-max-len 128 ——(指定慢查询日志的长度,当一个新的命令被写进日志的时候最老的记录会被删除,这个长度没有限制,只要有足够的内存就行,也可以通过SLOWLOG RESET 来释放内存) latency-monitor-threshold 0 ——(是否开启延迟监控功能,延迟监控功能是用来监控redis中执行比较缓慢的一些操作,设置为0则表示关闭监视,默认情况是关闭的,可以使用CONFIG SET命令动态设置) notify-keyspace-events "" ——(是否开启键空间通知,键空间通知使得客户端可以通过订阅频道或模式,来接受那些以某种方式改动了redis数据集的事件,默认情况下是关闭的) hash-max-ziplist-entries 512 ——(当数据量小于等于指定值的使用ziplist,大于指定值使用hash) hash-max-ziplist-value 64 ——(value大小小于等于指定值的使用ziplist,大于指定值使用hash) list-max-ziplist-size -2 list-compress-depth 0 set-max-intset-entries 512 zset-max-ziplist-entries 128 zset-max-ziplist-value 64 hll-sparse-max-bytes 3000 activerehashing yes ——(开启这个选项redis将在每100毫秒时使用1毫秒的cpu时间来对redis的hash表进行重新hash,可以降低内存的使用,如果你有非常严格的实时性要求的话,可以把此项关闭no) client-output-buffer-limit normal 0 0 0 ——(这个选项可以对客户端输出缓冲进行限制可以强迫那些不是从服务器读取数据的客户端断开连接,用来强制关闭传输缓慢的客户端,第一个0表示取消hard limit第二个和第三个0表示取消soft limit,normal client默认取消限制) client-output-buffer-limit slave 256mb 64mb 60 ——(对于slave,当client-output-buffer(客户端的输出缓存区)一旦超过256mb或者超过64mb并且持续60秒,那么服务器会立即断开客户端连接) client-output-buffer-limit pubsub 32mb 8mb 60 ——(对于pubsub,当client-output-buffer一旦超过32mb或者超过8mb并且持续60秒,那么服务器会立即断开客户端链接) hz 10 ——(redis执行任务的频率为1秒除以hz的值) aof-rewrite-incremental-fsync yes ——(当选择yes时,在aof重写的时候,系统会每32mb执行一次fsync同步,对于把文件写入磁盘是有帮助的,可以避免过大的延迟峰值)
-redis主配置文件主要配置项
(1)bind:监听的主机地址 (2)port:端口 (3)daemonize yes:启动守护进程 (4)pidfile:指定的pid文件 (5)loglevel notice:日志级别 (6)logfile:指定日志文件
-redis命令工具
******redis的命令工具放在了/usr/local/bin/下,其中以reids开头的都为redis的命令工具 [root@redis ~]# ls /usr/local/bin/ redis-benchmark redis-check-rdb redis-sentinel redis-check-aof redis-cli redis-server ******命令工具解析: redis-benchmark 用于检测redis在本机的运行效率,即服务的性能 redis-check-rdb 修复RDB持久化文件 redis-sentinel redis-server的软连接 redis-check-aof 修复AOF持久化文件 redis-cli redis命令行工具 redis-server 用于启动redis的工具
-命令行工具redis-cli
******连接本机的redis数据库 [root@redis ~]# redis-cli (连接本机数据库) 127.0.0.1:6379> ping (检测redis是否启动返回PONG则说明已经启动) PONG 127.0.0.1:6379> exit [root@redis ~]# ******远程访问redis数据库 -h 指定远程主机 -p 指定服务端口 -a 用户密码 [root@redis ~]# redis-cli -h 192.168.100.7 -p 6379 192.168.100.7:6379> ******在数据库环境下获取命令帮助: help @<group>:获取<group>中的命令列表 help <command>:获取某个命令的帮助 help <tab>:获取可能帮助的主题列表 192.168.100.7:6379> info (查看服务的统计信息) 192.168.100.7:6379> help @list (查看所有与list数据类型相关的命令) 192.168.100.7:6379> help set (查看set命令的帮助信息)
-测试工具redis-benchmark
******redis-benchmark测试工具可以模拟n个客户端发出m个请求,类似于apache ab程序,从而测试服务性能 语法:redis-benchmark [-h <host>][-p ] [-c <clients>][-n ]> [-k <boolean>] ******选项: -h <hostname> 主机名 (默认 127.0.0.1) -p <port> 主机端口 (默认 6379) -s <socket> UNIX socket (会覆盖 -h -p 设置的内容) -a <password> 密码(密码错误之类的不会直接保错,而是在操作时才会保错,这时可以使用 Redis 的 AUTH 命令再次认证) -c <clients> 客户端的并发数量(默认是50) -n <requests> 客户端请求总量(默认是100000) -d <size> 使用 SET/GET 添加的数据的字节大小 (默认 2) -dbnum <db> 选择一个数据库进行测试 (默认 0) -k <boolean> 客户端是否使用keepalive,1为使用,0为不使用,(默认为 1) -r <keyspacelen> 使用 SET/GET/INCR 命令添加数据 key, SADD 添加随机数据,keyspacelen 指定的是添加 键的数量 -P <numreq> 每个请求 pipeline 的数据量(默认为1,没有 pipeline ) -q 仅仅显示redis-benchmark的requests per second信息 --csv 将结果按照csv格式输出,便于后续处理 -l 循环测试 -t <tests> 可以对指定命令进行基准测试 -I 空闲模式 只打开N个空闲连接并等待。 ******例:向redis服务器发送100个并发连接与100000个请求 [root@redis ~]# redis-benchmark -h 192.168.100.7 -p 6379 -c 100 -n 100000 ====== PING_INLINE ====== 100000 requests completed in 1.13 seconds 100 parallel clients 3 bytes payload keep alive: 1 。。。。。。。。。。。(中间省略) ====== MSET (10 keys) ====== (汇总信息) 100000 requests completed in 1.27 seconds (表示十万个请求包在1.27秒完成) 100 parallel clients (100个并发连接统计) 3 bytes payload keep alive: 1 60.54% <= 1 milliseconds (milliseconds表示毫秒) 99.99% <= 2 milliseconds 100.00% <= 2 milliseconds 78678.20 requests per second (每秒可以处理78678.20个请求) ******例:测试存取大小为100b的数据包的性能 [root@redis ~]# redis-benchmark -h 192.168.100.7 -p 6379 -q -d 100PING_INLINE: 96899.23 requests per second PING_BULK: 97943.19 requests per second SET: 94607.38 requests per second GET: 95328.88 requests per second INCR: 96525.09 requests per second LPUSH: 92336.11 requests per second RPUSH: 73691.97 requests per second LPOP: 91996.32 requests per second RPOP: 91911.76 requests per second SADD: 94786.73 requests per second SPOP: 96246.39 requests per second LPUSH (needed to benchmark LRANGE): 91575.09 requests per second LRANGE_100 (first 100 elements): 42283.30 requests per second LRANGE_300 (first 300 elements): 13468.01 requests per second LRANGE_500 (first 450 elements): 7964.32 requests per second LRANGE_600 (first 600 elements): 5575.07 requests per second MSET (10 keys): 75757.57 requests per second (表示每秒75757.57个请求) ******例:测试本机上redis服务在进行set和lpush操作时的性能 [root@redis ~]# redis-benchmark -t set,lpush -n 100000 -q SET: 65832.78 requests per second (在进行set操作时每秒65832.78个请求) LPUSH: 93984.96 requests per second (在进行lpush操作时每秒93984.96个请求)
-redis数据库常用命令
******常用存放、获取命令 (1)set:存放数据 (2)get:获取数据 (3)key的相关命令: keys、exists、del、type、rename、renamenx、dbsize (4)key-value键值对的数据存储形式: set :set key value get :get key [root@redis ~]# redis-cli (进入数据库) 127.0.0.1:6379> set aaa ly (存放一个键名为aaa值为ly的数据) OK 127.0.0.1:6379> get aaa (获取键名为aaa的值) "ly" 127.0.0.1:6379>