redis 教程
文章目录
1.NoSql入门和概述
原因:一个网站的访问量一般都不大,用单个数据库完全可以轻松应付。
数据存储的瓶颈:
- 数据量的总大小,一个机器放不下
- 数据的索引一个机器的内存放不下时
- 访问量(读写混合)一个实例不能承受
使用redis的原因:
MySQL数据库也经常存储一些大文本字段, 导致数据库表非常的大,在做数据库恢复的时候就导致非常的慢,不容易快速恢复数据库。比如1000万4KB大小的文本就接近40GB的大小,如果能把这些数据从MySQL省去,MySQL将变得非常的小。关系数据库很强大,但是它并不能很好的应付所有的应用场景。MySQL的扩展性差(需要复杂的技术来实现),大数据下IO压力大,表结构更改困难,正是当前使用MySQL的开发人员面临的问题。
NoSQL数据库种类繁多,但是一个共同的特点都是去掉关系数据库的关系型特性,数据之间无关系。以无形之间,在架构的层面上带了可扩展的能力
为什么要去IOE??
- I 指 IBM p 系列小型机,操作系统是 AIX(IBM 专有的 Unix 系统);
- O 指 Oracle 数据库(RDBMS);
- E 指 EMC 中高端 SAN 存储。
linux系统中保存文件 shift+Esc+: 然后输入wq 立即保存文件
2.redis 的使用:
表明redis已经安装成功
2.1 redis的基础
2.2 redis的命令:
2.2.1 key有关的命令
命令 | 说明 |
---|---|
DBSIZE | 返回当前数据库的key的数量 |
keys * | 返回当前库的所有key |
get name | 获取key对应的值 |
set name value | 向数据库中装入数据 |
EXIST name | 判断是否存在key |
move name index | 将key移动至几号库中 |
ttl name | 查看还有多少秒过期 -1表示永不过期 -2 表示已经过期 |
EXPIRE name second | 设置key活的时间(秒) |
type name | 查看key的固定类型 |
2.2.2 String类型的命令
1 .常用的:
命令 | 说明 |
---|---|
STRLEN name | 返回当前key的长度 |
INCR name | 将存储的数字+1 |
decr name | 将存储的数据-1 |
INCRBY name num | 将存储的数字+num |
DECRBY name num | 将存储的数字-num |
getrange | 获取指定区间范围内的值,类似between and的关系(截取) |
setrange | 设置指定区间范围内的值 |
setx name 时间 值 | 存储数据多少秒自动销毁 |
setnx name value | 存储不存在的key值 |
mset name1 value1 name2 value2 … | 存储多个key-value键值对 |
mget name1 name2 name3… | 获取多个key的值 |
msetnx name1 value1 name2 value2 | 存储多个数据 如果存在则失效 |
getset | 先获取再设值 |
flushdb | 释放所有的key |
2.2.3 List 命令
命令 | 含义 |
---|---|
lpush name value1 value2 value3… | 向list集合中左加数据 |
rpush name value1 value2 value3… | 向list集合中右加数据 |
lrange 0 -1 | 左取数据 |
LPOP list_name | 左边取一个数据 返回并删除 |
rpop | 右边取一个数据返回并删除 |
LINDEX list_name num | 根据下表查找数据 |
LLEN KEY | 查询当前list的数量 |
lrem list_name num value | 删除num 个value的值 |
ltrim list_name num1 num2 | 截取num1 至num2 的数据传递给list_name |
rpoplposh list1 list2 | 将list1 的最右边元素赋值给list2 的最左边位置 |
lset list_name index value | 将list 中的下标为index 的数据修改为value |
linsert list brfore/after value1 value2… | 将list中的value1 之前/之后加入 value2只会对第一个数据产生作用 |
他是一个字符串链表,left right都可以插入添加
如果键不存在,创建新的链表
如果键已存在,新增内容
如果值全移除,对应的键也就消失了
链表的操作无论是头和尾效率都极高,但假如是对中间元素进行操作,效率就很惨淡了
2.2.4 set(无重复 无顺序)命令:
命令 | 含义 |
---|---|
sadd | 在set 集合中加入数据 |
smember set_name | 遍历set中的所有数据 |
sismember set value | 查看set集合中是否存在value的值 |
scard set | 获取集合中的元素个数 |
srem key value1 value2 value3 | 删除集合中的vlaue值 |
srandmember set_name num | 随机抽取num个值 |
spop set | 随机抽取一个vlaue |
smove set1 set2 | 将set1 的某个值赋给set2 |
sdiff set1 set2 | 以set2 为参考对set1 做差 |
sinter set1 set2 | set1 set2 中的交集 |
sunion set1 set2 | 将两个集合的并集输出 |
2.2.5 Hash(哈希)
命令 | 含义 | 例子 |
---|---|---|
HSET name 属性 value | 给hash对象加入数据 | HSET USER ID 11 |
HGET name 属性 | 取出hash对象中的数据 | HGET USER NAME |
HMSET name 属性1 value1 属性2 value2 | 命令用于同时将多个 field-value加入 | HMGET USER id name |
HMGET name 属性1 属性2 属性3 | 用于获取hash对象的值 | HMGET NAME 属性1 属性2 属性3 |
HGETALL NAME | 获取hash对象中所有属性的值 | HGETALL NAME |
hdel name 属性 | 删除hash对象中的特定属性 | hdel user name |
hlen name | 获取hash表中字段的数量 | hlen user |
hexists name 属性 | 判断hash表中是否存在字段 | HEXISTS user name |
HKEYS NAME | 查看哈希表中的属性名 | hkeys user |
hvals name | 查看哈希表中的值 | hvals user |
HINCRBY NAME 属性 num | 给hash表中的属性+num | - |
Hincrbyfloat name 属性 float类型的数据 | 给hash表中的属性+num | - |
hsetnx name 属性 num | 命令用于为哈希表中不存在的的字段赋值 | - |
2.2.6 Zset(sorted set)
在set的基础上,加一个score值
之前set是k1 v1 k2 v2 …
现在zset 是k1 score1 v1 score2 v2
命令 | 含义 | 例子 |
---|---|---|
zddd name value1 对象1 value2 对象2 … | 给zset对象添加键值对 | - |
zrange name 0 -1 | 输出zset对象中的数据 | - |
zrange name 0 -1 withscores | 输出zset 对象中的数据带有score 的 | - |
zrangebyscore key 开始score 结束score | 输出zset中从开始score到结束score中的所有数据 | 数据之前可以加( 意思为不包括 |
zrangebyscore name 开始score 结束score limit num1 num2 | 在结果中从第num1 后面的num2个数据输出 | |
zrem key 某score 下对应的value值 | 作用是删除元素 | zrem zset1 v5 |
zcard name | 统计集合中的个数 | zcard zset1 |
zcount name num1 num2 | 统计集合中vlaue 值为num1 到num2 之间的数据 | |
zrank name 对象 | 统计集合中固定属性的值的下标 | |
zscore name 对象 | 查找出集合中对应的对象的值是多少 | |
zrevrank key 对象值 | 逆序获得下标的值 | |
zrevrange name 0 -1 | 逆序输出对象 | |
zrevrangebyscore key 结束score 开始score | 从结束分数到开始分数输出 |
此图是zrangebyscore 的例子:
2.3 配置文件
LIMITS限制:
a. Maxckuebts
b. Maxmemory
c. Maxmemory-policy
d. Maxmemory-samples
设置样本数量,LRU算法和最小TTL算法都并非是精确的算法,而是估算值,所以可以设置样本的大小,redus默认检查这么多个key并选择其中LRU的那个
stop-writes-on-bgsave-error yes(如果配置成no,表示你不在乎数据不一致或者其他的手段发现和控制)
rdbcompression yes(对于存储到磁盘中的快照,可以设置是都进行压缩存储。如果是的话,redis会采用LZF算法进行压缩,如果你不想消耗cpu来进行压缩的话,可与i设置为关闭此功能)
rdbchecksum yes (在存储快照后,还可以让redis使用CRC64算法进行数据校验,但是这样做会增加大约10%的性能消耗,如果希望获取到最大的性能提升,可以关闭此功能)
常用配置:
、
2.4 持久化
2.4.1 rdb(Redis DataBase)
在指定的时间间隔内将内存中的数据集快照写入磁盘,也就是行话讲的snapshot快照,他恢复时是将快照能直接读到内存里
2.4.1.1 含义
Reids会单独创建(fork)一个子进程来进行持久化,会先将数据写入到一个临时文件中,待持久化过程都结束了,再用这个临时文件替换上次持久化好的文件,整个过程中,主进程是不进行任何IO操作的,这就确保了极高的性能
如果需要进行大规模数据的恢复 ,且对于数据恢复的完整性不是非常敏感,那 RDB方式要比AOF方式更加高效。
RDB的缺点是最后一次持久化后的数据可能丢失
2.4.1.2 Fork:
Fork的作用是复制一个与当前进程一样的进程。新进程的所有数据(变量/环境变量,程序计数器等)数值都和原进程一致,但是是一个全新的进程,并作为原进程的子进程
- Rdb:
保存的是dump.rdb文件
当flaushRDB的时候 ,会生成新的domp.rdb文件,但是因为flaushrdb会将缓存迅速灌入磁盘中,所以rdb文件是空的
2.4.1.3 SNAPSHOTTING(快照)
- save:
- save秒钟写操作次数
redes 的RDB是如何备份的?
RDB是整个内存的压缩多的Snapshot,RDB的数据结构,可以配置复合的快照出发条件
默认:
是一分种内改了一万次
或5分钟内改了10次
或15分钟内改了1次 - 禁用:如果想要禁用rdb持久化的策略,只要不设置任何save指令,或者给save指令传入一个空字符串参数也可以
直接进行立即保存,然后更新rdb文件
- save秒钟写操作次数
如何触发RDB快照:
1 . 配置文件中默认的快照配置----冷拷贝后重新使用(分两台机器进行备份)
2 .命令save或者bgsave
- Save:save时只管保存,其他不管,全部阻塞
- BGSAVE:redis会在后台一部进行快照操作
- 快照同时还可以相应客户端请求,可以通过lastsave命令获取最后一次成功执行快照的时间
3 .执行flushall命令,也会产生dump.rdb文件,但是里面是空的,无意义。
2.4.1.4 如何恢复:
将备份文件(dump.rdb)移动到redis安装目录并启动服务即可
CONFIG GET DIR获取目录
2.4.1.5 优势:
适合大规模的数据恢复
对数据完整性和一致性要求不高
2.4.1.6 劣势
在一定记得那个时间做一次备份,所以如果redis意外down掉的话,就会丢失给最后一次快照后的所有修改
fork的时候,内存中的数据被克隆了一份,大致2倍的膨胀性需要考虑
如何停止:
动态所有停止RDB保存规则的方法:redis-cli config set save
2.4.2 AOF
2.4.2.1 含义:
以日志的方式来记录每个写操作,将Redis执行过的所有写指令记录下来(读操作不记录),只许追加文件但不可以改写文件,redis启动之初会读取该文件重新构建数据,换言之,redis重启的话就根据日志我呢见的内容将写指令从前到后执行一次以完成数据的恢复工作。
AOF保存的是appendonly.aof文件,默认关闭
测试的时候将 rdb文件删除,然后进行重启操作,查出来以后 redis库中没有数据,因为aof文件会实时记录下具体操作
2.4.2.2 AOF的启动/修复和恢复
- 进行写入操作(此过程会全部进入aof文件中进行记录)
- 将rdb文件删除,避免影响恢复的源文件
3. 将flushall操作删除,不删除将不会进行恢复,因为恢复的时候做的是全部操作(AOF将会进行忠实的写操作写啥就记录啥)
- redis服务器进行重启操作,进行恢复
如果aof文件被损坏,那么redis服务将不会被启动。
redes服务启动的时候先加载的是aof文件 在加载rdb文件
如果aof文件损坏,那么服务器会自动生成check_aof文件进行恢复
AOF和RDB是可以同时起作用的
aof的配置文件:
- appendonly
- appendfilename
尽量不要改 - Appendfsync
a. always:同步持久化,每次发生数据变更会被立即记录到磁盘 性能较差但是数据完整性比较好
b. Everysec: 出厂默认推荐,异步操作,每秒记录。如果一秒内宕机,有数据丢失
c. no 、
2.4.2.3 Rewrite
优势:
- 每秒同步:appendfsync always 同步持久化 每次发生数据变更会立即记录到磁盘,性能差但是数据完整性强
- 没修改同步:appendfsync everysec 异步操作,每秒记录,如果一秒内宕机会有数据的丢失
- 不同步:appendfsync no
劣势:
1. 相同的数据集的数据而言aof文件要远大于rdb文件,恢复速度慢于rdb
2. Aof运行效率要慢于rdb,每秒同步效率较好,不同步效率和rdb相同
2.4.3 Redis的事务
2.4.3.1 含义:
可以一次执行多个命令,本质是一组命令的集合。一个事务中的所有命令都会序列化。按顺序地串行执行执行而不会被其他命令插入,不许加塞
- 正常执行:
-
放弃事务
-
全体连坐(语法错误)
-
冤头债主(类型导致的错误)
redis对事务的支持时部分支持
-
watch监控
正在监控的事务中,如果在修改的期间 其他进程对数据进行了修改,那么事务就会执行失败
一旦执行了unwatch exec之前家的监控锁都会被取消掉。
事务的三阶段:
- 开启:以MULTI开始一个事务
- 入队:将多个命令入队到事务中,街道这些命令并不会立即执行,而是放到等待执行的事务队列里面
- 执行:由EXEC命令触发事务
三个特性:
部分支持事务,没有会滚
2.4.4 Redis的发布订阅
2.4.4.1 含义:
进程间的一种消息通信模式:发送者发送消息,订阅者接收消息
订阅/发布消息图:
先订阅后发布才能收到消息
- 可以一次性订阅多个,SUBSCRIBE c1 c2 c3
- 消息发布,PUBLISH c2 hello-redis
============================================== - 订阅多个,通配符* PSUBSCRIBE new*
- 收取消息,PUBLISH new1 redis2015
先订阅后发布才可接收到消息
订阅:
发布:
2.4.5 redis的复制(主从复制,读写分离)
2.4.5.1 含义:
也就是我们所说的主从复制,主机数据更新后根据配置和策略,自动同步到备机的master/slaver机制,Master以写为主,Slave以读为主
2.4.5.2 作用
读写分离
容灾恢复
2.4.5.3 如何用
- 拷贝多个redis.conf
- 修改文件配置
主机:
从机1
从机2
主机可写可读
从机只能读不可写
主机宕机后主从机的身份不会改变,从机可以读取数据
从机宕机后身份修改 ,需要重新连接除非写进配置
2.4.5.4 原理:
- Slave启动成功连接到master后会发送一个sync命令
- Master接到命令启动后台的存盘进程,同时手机所有接受到的用于修改数据集命令,在后台进程执行完毕之后,master将传送整个数据文件到slave,以完成一次完全同步
- 全量复制:而slave服务在接受到赎救苦文件数据后,将其存盘并加载到内存中
- 增量复制:Master继续将新的所有手机到的修改名伶一次传给slave,完成同步
第一次全量复制 剩余是增量复制
2.4.5.5 哨兵模式
- 含义:
反客为主的自动版,能够后台监控主机是都故障,如果故障了根据投票数自动将从库转换为主库 - 使用步骤:
- 调整结构:6379 带着80 81
- 自定义下的/myredis目录下新建sentinel.conf文件,名字绝不能错
- 配置哨兵,填写内容
a. sentinel monitor被监控数据库名字(自己起名字)127.0.0.1 6379 1
b. 上面最后一个数字1 表示主机挂掉后salve投票看让谁接替成为主机,得票多的 - 启动哨兵: Redis-sentinel /myredis/sentinel.conf
上述目录依旧各自的实际情况配置,可能目录不同 - 一组的sentinel能同时监控多个
2.4.5.6 缺点
复制的延迟:由于所有的写操作都是参选在Master上操作,然后同步更新到Slave上,所以从Master同步到Slave机器有一定的延迟,当系统很频繁忙的时候,延迟我呢提会更加严重,Slave机器数量的增加也会使这个问题更加严重