一、关系数据库与非关系型数据库
1.关系型数据库(sql结构化数据库)
- 一个结构化的数据库,创建在关系模型基础上
- 一般面向于记录
- 包括 Oracle、MySQL、SQL Server、Microsoft Access、DB2等
2.非关系型数据库(nosql非结构化数据库)
- 除了主流的关系型数据库外的数据库,都认为是非关系型
- 包括Redis、MongBD、Hbase、CouhDB等
非关系型数据库产生背景
- High performance——对数据库高并发读写需求
- Huge Storage——对海量数据高效存储与访问需求
- High Scalability && High Availability——对数据库高可扩展与高可用性需求
二、Redis简介
1.Redis介绍
redis(remote dictionary server,远程字典服务)是一个开源的使用ANSI C语言编写、遵守BSD协议、支持网络,可基于内存可持久化的日志型、key-value的数据库,并提供多种语言的API。
它通常被称为结构服务器,因为值(value)可以是字符串(string),哈希(hash),列表(list),集合(sets)和有序集合(sorted sets)等类型。
- Redis基于内存运行并支持持久化
- 采用key-value(键值对)的存储形式
2.Redis的优点
- 具有极高的数据读写速度
- 支持丰富的数据类型
- 支持数据的持久化(1.将内存中的数据库保存在磁盘中,重启的时候可以再次加载进行使用 2.日志来保证它数据的不丢失)
- 原子性(数据存储的方式不能再分割了,只能关键字与值得方式存储)
- 支持数据备份
3.redis的特点
- 1.redis支持数据的持久化,可以将内存中的数据库保存在磁盘中,重启的时候可以再次加载进行使用
- 2.redis不仅仅支持简单的key-value类型的数据,同时还提供list,set,zset,hash等数据结构的存储
- 3.redis支持数据的备份,即master-slave模式的数据备份
4. redis优势
- 1.性能极高-redis的读的速度是110000次/s,写的速度是81000次/s
- 2.丰富的数据类型-redis支持二进制案例的strings,lists,hashes,sets以及ordered sets数据类型操作
- 3.原子-redis的所有操作都是原子性的,意思就是要么成功执行要么完全不执行。单个操作是原子性的,多个操作也支持事务,即原子性,通过MULTI和EXEC指令包起来
- 4.丰富的特性-redis还支持publish/subscribe通知,key过期等特性
5. redis与其他key-value的不同
- 1.redis有着更为复杂的数据结构并且提供对他们的原子操作,这是一个不同于其他数据库的进化路径。redis的数据类型都是基于基本数据结构的同时对程序员透明,无需进行额外的抽象
- 2.redis运行在内存中但是可以持久化到磁盘,所以在对不同数据集进行高速读写时需要权衡内存,因为数据不能大于硬件内存。在内存数据库方面的另外一个优点是,相比在磁盘上相同的复杂的数据结构,在内存中操作起来非常简单,这样redis可以做很多内部复杂性很强的事情。同时,在磁盘格式方面他们是紧凑的以追加的方式生产的,因为他们不需要进行随机访问
6.Redis与Memcached区别
1.Redis与Memcached区别
虽然redis和memcached都是内存型数据库,并且memcached不仅能够存储string类型,还能够存储图片、文件、视频等格式的文件。然而对于更多的使用内存数据库做缓存以及分布式方案的程序开发者来说,memcached提供的string类型存储的应用场景非常有限,而存储图片视频的功能又十分鸡肋(许多公司的用户场景是没这方面需求)。相比之下,redis提供set,hash,list等多种类型的存储结构,非常适合分布式缓存的实现。
2.数据落盘
memcached 数据不可恢复,虽然大多数人使用缓存以及分布式方案都不会要求数据持久化,但是谁也不能保证不出现万一的情况。一旦发生稳定性问题,memcached挂掉后,数据是不可恢复的,而redis除了支持在配置里打开数据落盘(RDB),还能通过aof来找回数据。
3.内存空间与数据量
memcached可以修改最大内存,使用的是LRU算法,而redis目前底层使用了自己的VM,引入了新的特性突破了物理内存的限制。个人认为在这方面依然是redis更加优秀一些。
value值-redis最大可以达到1GB,而memcache只有1MB;
4.使用场景
1.会话缓存(Session Cache)
最常用的一种使用Redis的情景是会话缓存(session cache)。用Redis缓存会话比其他存储(如Memcached)的优势在于:Redis提供持久化。当维护一个不是严格要求一致性的缓存时,如果用户的购物车信息全部丢失,大部分人都会不高兴的,现在,他们还会这样吗?
幸运的是,随着 Redis 这些年的改进,很容易找到怎么恰当的使用Redis来缓存会话的文档。甚至广为人知的商业平台Magento也提供Redis的插件。
2.全页缓存(FPC)
除基本的会话token之外,Redis还提供很简便的FPC平台。回到一致性问题,即使重启了Redis实例,因为有磁盘的持久化,用户也不会看到页面加载速度的下降,这是一个极大改进,类似PHP本地FPC。
再次以Magento为例,Magento提供一个插件来使用Redis作为全页缓存后端。
此外,对WordPress的用户来说,Pantheon有一个非常好的插件 wp-redis,这个插件能帮助你以最快速度加载你曾浏览过的页面。
3.队列
Reids在内存存储引擎领域的一大优点是提供 list 和 set 操作,这使得Redis能作为一个很好的消息队列平台来使用。Redis作为队列使用的操作,就类似于本地程序语言(如Python)对 list 的 push/pop 操作。
如果你快速的在Google中搜索“Redis queues”,你马上就能找到大量的开源项目,这些项目的目的就是利用Redis创建非常好的后端工具,以满足各种队列需求。例如,Celery有一个后台就是使用Redis作为broker,你可以从这里去查看。
4.排行榜/计数器
Redis在内存中对数字进行递增或递减的操作实现的非常好。集合(Set)和有序集合(Sorted Set)也使得我们在执行这些操作的时候变的非常简单,Redis只是正好提供了这两种数据结构。所以,我们要从排序集合中获取到排名最靠前的10个用户–我们称之为“user_scores”,我们只需要像下面一样执行即可:
当然,这是假定你是根据你用户的分数做递增的排序。如果你想返回用户及用户的分数,你需要这样执行:
ZRANGE user_scores 0 10 WITHSCORES
Agora Games就是一个很好的例子,用Ruby实现的,它的排行榜就是使用Redis来存储数据的,你可以在这里看到。
5.发布/订阅
最后(但肯定不是最不重要的)是Redis的发布/订阅功能。发布/订阅的使用场景确实非常多。我已看见人们在社交网络连接中使用,还可作为基于发布/订阅的脚本触发器,甚至用Redis的发布/订阅功能来建立聊天系统!(不,这是真的,你可以去核实
)。
6.其他
但是如果是对缓存的数据格式有更多的要求,且对安全性也有很高的要求的话,建议还是使用redis,这也是redis目前正在逐渐代替memcached的根本原因。
7.解析图
三、Redis数据类型
Redis支持五种数据类型:String(字符串),hash(哈希),list(列表),set(集合)及zset(sorted set:有序集合)
1.String(字符串)
- String 是redis最基本的类型,你可以理解成为Memcached一模一样的类型,一个key对应一个value。
- String类型的二进制安全的。意思是redis的String可以包括任何数据。比如jpg图片或者序列化的对象
- String类型是Redis最基本的数据类型,String类型的值最大能存储512MB。
set键 值 设置键值对 get 键 获取键的值
1.1 示例
192.168.1.10:6379> set a 5 #设置a表的值为5
OK
192.168.1.10:6379> get a #查看a表的值为5
"5"
192.168.1.10:6379> type a #查看a表的表类型
string
192.168.1.10:6379> incr a #incrby默认是加1
(integer) 6
192.168.1.10:6379> decr a #decrby默认是减1
(integer) 5
192.168.1.10:6379> incrby a 5 #设置a表加5的值
(integer) 10
192.168.1.10:6379> incrby a 8 #设置a表加8
(integer) 18
192.168.1.10:6379> decrby a 8 #设置a表减8
(integer) 10
192.168.1.10:6379>
2.Hash(哈希)
- Redis hash是一个键值(key=>value)对集合
- Redis hash是一个string类型的field和value的映射表,hash特别适合用于存储对象
- Hset:添加hash数据 hget:获取hash数据 hmget:获取多个hash数据
2.1 示例
192.168.1.10:6379> Hset hash key1 f #在hash中加入key1的数据为f
(integer) 1
192.168.1.10:6379> Hset hash key2 a #在hash中加入key2的数据为a
(integer) 1
192.168.1.10:6379> Hset hash key3 c #在hash中加入key3的数据为c
(integer) 1
192.168.1.10:6379> hget hash key1 #查看hash中key1的数据
"f"
192.168.1.10:6379> hmget hash key1 key2 key3 #查看hash1中key1,key2,key3的数据
1) "f"
2) "a"
3) "c"
192.168.1.10:6379> hset hash fieldl1 fa fieldl2 nb #在hash中写入字段field1和field2,数据分别为fa、nb
(integer) 2
192.168.1.10:6379> hmget hash fieldl1 #查看hash中字段field1的数据
1) "fa"
192.168.1.10:6379> hmget hash fieldl1 fieldl2 #查看hash中字段field1、field2的数据
1) "fa"
2) "nb"
3.List(列表)
- Redis列表是简单的字符串列表,按照插入顺序排序。可以添加一个元素到列表的头部(左边)或尾部(右边)
- lpush:从左边推入值 lpop:从左边弹出值 rpush:从右边推入值
rpop:从右边弹出值 llen:查看某个list数据类型的长度
3.1 示例
192.168.1.10:6379> lpush list1 1 #list1左入1
(integer) 1
192.168.1.10:6379> lpush list1 2 #list1左入2
(integer) 2
192.168.1.10:6379> lpush list1 3 #list1左入3
(integer) 3
192.168.1.10:6379> llen list1 #查询列表长度
(integer) 3
192.168.1.10:6379> lrange list1 0 2 #查看list1中从第0位到第2位的值
1) "3"
2) "2"
3) "1"
192.168.1.10:6379> lpop list1 #list1左出
"3"
192.168.1.10:6379> rpop list1 #list1右出
"1"
4.Set(无序集合)
- Redis的Set的string类型的无序集合。
- 集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是O(1)
sadd命令 - 添加一个string元素到key对应的set集合中,成功返回1,如果元素已经在集合中返回0
- sadd key member
- scard:查看set数据中存在的元素个数
- sismember:判断set数据中的是否存在某个元素
- srem:删除某个set数据中的元素
4.1 示例
192.168.1.10:6379> sadd set a #在set中添加a元素,添加成功会输出1,失败会输出0
(integer) 1
192.168.1.10:6379> scard set #查看set表中的元素个数
(integer) 1
192.168.1.10:6379> sismember set a #查看set表中是否存在这个元素,存在输出1,不存在输出0
(integer) 1
192.168.1.10:6379> sadd set b #在set中添加b元素,添加成功会输出1,失败会输出0
(integer) 1
192.168.1.10:6379> srem set b #删除set中的某个元素,删除成功输出1,失败输出0
(integer) 1
192.168.1.10:6379> smembers set #查看set中的所有元素,无序排列呈现
1) "a"
5.zset(sorted set:有序集合)
- Redis zset和set一样也是string类型元素的集合,且不允许重复的成员
- 不同的每个元素都会关联一个double类型的分数。redis正是通过分数来集合中的成员进行从小到大的排序
- zset的成员是唯一的,但分数(score)却可以重复
- zadd命令
- 添加元素到集合,元素在集合中存在则更新对应score
- 使用方法:zadd key score member
- zcard:查询
- zrang:数据排序
5.1 示例
192.168.1.10:6379> zadd zset 10 a #在zset中添加元素值位a,分数为10
192.168.1.10:6379> zrangebyscore zset 0 11 #查看zset中第0位到第5位的值,按照分数从小到大排序
192.168.1.10:6379> zrangebyscore zset 0 11 withscores #查看zset中第0位到第5位的元素与各自的分数,元素在上,分数在下,从小到大排序
四、安装Redis数据库
1.解压redis安装包
[root@server1 ~]# tar zxvf redis-5.0.4.tar.gz
2.配置安装
[root@server1 ~]# cd redis-5.0.4/
[root@server1 redis-5.0.4]# make
[root@server1 redis-5.0.4]# make PREFIX=/usr/local/redis install
更改安装路径可以用make PREFIX=安装路径 install
[root@server1 redis-5.0.4]# cd
[root@server1 ~]# cd /usr/local/redis/
[root@server1 redis]# ll
3.软链接
[root@server1 redis# ln -s /usr/local/redis/bin/* /usr/sbin
[root@server1 redis]# cd
[root@server1 ~]# cd utils/
[root@server1 utils]# ll
4.执行安装脚本文件,查看端口
[root@server1 utils]# ./install_server.sh #执行安装脚本文件
[root@server1 utils]# netstat -anpt | grep redis #查看redis端口是否开启
[root@server1 utils]# cd
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] #选择redis的端口,选择默认端口6379
Selecting default: 6379
Please select the redis config file name [/etc/redis/6379.conf] #redis的配置文件路径
Selected default - /etc/redis/6379.conf
Please select the redis log file name [/var/log/redis_6379.log] #redis的日志的路径
Selected default - /var/log/redis_6379.log
Please select the data directory for this instance [/var/lib/redis/6379] #redis数据保存的路径
Selected default - /var/lib/redis/6379
Please select the redis executable path [] /usr/local/redis/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/redis/bin/redis-server
Cli Executable : /usr/local/redis/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! #安装成功
5.修改,重启配置文件
[root@server1 ~]# vi /etc/redis/6379.conf
[root@server1 ~]# /etc/init.d/redis_6379 restart
安装完成
五、Redis配置策略
1.Redis配置文件
1.配置参数(/etc/redis/6379.conf)
bind:监听的主机地址
port:端口(默认6379)
daemonize yes:启用守护进程
pidfile:指定PID文件
loglevel notice:日志级别
logfile:指定日志文件
2.Redis数据库常用命令
1.redis-cli命令行工具
连接本地数据库
/usr/local/redis/bin/redis-cli
27.0.0.1:6379>
连接远程数据库
redis-cli -h 192.168.1.10 -p 6379
192.168.10.161>
3.Redis命令工具
redis-server :用于启动Redis的工具
redis-benchmark :用于检测Redis在本机的运行效率
redis-check-aof :修复AOF持久化文件
redis-check-rdb :修复RDB持久化文件
redis-cli :是Redis命令行工具
redis-sentinel :是哨兵模式启动的工具
4. redis-benchmark测试工具
基本测试语法为redis-benchmark [option] [option value]
-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.向IP地址为20.0.0.10,端口为6379的Redis服务器发送100个并发连接与10000个请求测试性能
[root@server1 ~]# ps aux | grep redis
[root@server1 ~]# redis-benchmark -h 192.168.1.10 -p 6379 -c 100 -n 10000
-h: 指定服务器主机名
-p:指定服务器端口
-c:指定并发连接数
-n:指定请求数
2.测试存取大小为100字节的数据包的性能
[root@server1 ~]# redis-benchmark -h 192.168.1.10 -p 6379 -q -d 100
-p:指定服务器端口
-p:指定服务器端口
-q:强制退出redis,仅显示query/sec值
-d:以字节的形式指定SET/GET值的数据大小
3.测试本机上Redis服务在进行set与lpush操作时的性能
[root@server1 ~]# redis-benchmark -t set,lpush -n 10000 -q
-t:仅运行以逗号分隔的测试命令列表
-n:指定请求数
-q:强制退出redis,仅显示query/sec值
六、数据库常用命令
除了数据常用的五种类型用法,还有一些常用命令
1.select切换数据库
因为redis有16个子数据库,0-15,我们默认进去的是数据库0,要换别的数据库怎么办?
[root@server1 ~]# redis-cli -h 192.168.1.10 -p 6379 #登录
192.168.1.10:6379> select 1 #切换到数据库1中
OK
192.168.1.10:6379[1]> select 2 #切换到数据库2中
OK
192.168.1.10:6379[2]> keys * #查看数据库1中的数据
(empty list or set)
192.168.1.10:6379[2]> select 0 #切换到原本的数据库中
OK
192.168.1.10:6379> keys * #查看数据库0中的数据
1) "zset"
2) "set"
3) "list1"
4) "list2"
5) "hash"
6) "a"
7) "list3"
2.数据迁移move
192.168.1.10:6379> move name 1
(integer) 1
192.168.1.10:6379> keys *
1) "zset"
2) "set"
3) "list1"
4) "list2"
5) "hash"
6) "a"
7) "list3"
192.168.1.10:6379> select 1
OK
192.168.1.10:6379[1]> keys *
1) "name"
3.高危FLUSHALL
数据库之间虽然互相隔离,但是也有共通之处,FLUSHALL(flushall)删除所有数据库数据
192.168.1.10:6379[1]> FLUSHALL
OK
192.168.1.10:6379[1]> keys *
(empty list or set)
192.168.1.10:6379[1]> select 0
OK
192.168.1.10:6379> keys *
(empty list or set)
4.检测key存在exist
192.168.1.10:6379> set name 5
OK
192.168.1.10:6379> exists name
(integer) 1
192.168.1.10:6379> exists fa
(integer) 0
5.key重命名rename
192.168.1.10:6379> rename name fa
OK
192.168.1.10:6379> get name
(nil)
192.168.1.10:6379> get fa
"5"
6.时间管理
- PTTL 查看剩余时间(毫秒)
- PEXPIRE 设置超时时间
- PERSIST 取消超时时间
192.168.1.10:6379> PTTL boy ##未设置超时时间,永久,为-1
-1
192.168.1.10:6379> PEXPIRE boy 30000 ##设置超时时间30s
1
192.168.1.10:6379> PTTL boy #######查看剩余时间,可以看到倒计时
20390
192.168.1.10:6379> PTTL boy
18881
192.168.1.10:6379> PTTL boy
17410
192.168.1.10:6379> PTTL boy
16294
192.168.1.10:6379> PERSIST boy ####取消超时时间
1
192.168.1.10:6379> PTTL boy
-1
7.随机返回key——RANDOMKEY
192.168.1.10:6379> mset name zhang age 19 score 88 #mset:一次存储多个键值对
OK
192.168.1.10:6379> RANDOMKEY #随机返回key的一个值
"age"
192.168.1.10:6379> RANDOMKEY
"age"
192.168.1.10:6379> RANDOMKEY
"age"
192.168.1.10:6379> RANDOMKEY
"name"
192.168.1.10:6379> RANDOMKEY
"age"
192.168.1.10:6379> RANDOMKEY
"age"
192.168.1.10:6379> RANDOMKEY
"age"
192.168.1.10:6379> RANDOMKEY
"score"