一、基本介绍
1.特点
- Redis是NoSQL数据库,不是传统的关系型数据库
- 介绍网站:www.redis.io、www.redis.cn还有 redisdoc.com(API)
- Redis(RE mode Dictionary Server,远程字典服务器),Redis性能非常高,单击能够达到15w qps,通常适合做缓存,也可以持久化
- 是完全开元免费的,高性能的分布式内存数据库,基于内存运行并支持持久化的NoSQL数据库,是最热门的NoSQL数据库之一,也称为数据结构服务器
- 默认端口6379
- Redis安装好后,默认有16个数据库,初始默认使用0号,编号为0~15
2.基本数据类型
1.String
String是redis最基本的类型,以键值对形式出现,一个key对应一个value
- string类型是二进制安全的,除普通的字符串外,还可以存放图片等数据
- 字符串value最大值是512M
- key不能重复
- 默认的value都是字符串类型
2.Hash
- Redis hash是一个键值对集合,是一个string类型的field和value的映射表
- hash特别适合用于存储对象
3.List
- 列表是简单的字符串列表,按照插入顺序排序,可以添加一个元素到列表的头部(左边)或者尾部(右边)
- List底层是一个链表,List的元素是有序的,元素的值可以重复
- lindex,按照索引下标获得元素(从左到右,编号从0开始)
4.Set
- Set是string类型的无序集合
- 底层是HashTable数据结构,Set也是存放很多字符串元素,字符串元素是无序的,而且元素的值不能重复
5.Zset
- Zset(sorted set):有序集合
二、基本语法
1.基本操作
- 切换数据库
select 1 // 选择哪个数据库
- 查看当前数据库的键值对数量
dbsize
- 清空数据库
flushdb // 清空当前数据库
flushall // 清空所有数据库
2.Redis CRUD操作
- 如果操作对应的类型不正确,则会返回一个错误
- 如果对应的key不存在,则会返回nil
1.String操作
- SET key value [EX seconds] [PX milliseconds] [NX|XX]
- EX seconds:键过期的时间,单位为秒
- PX millisenconds:键过期的时间,单位为毫秒
- NX:只在键不存在时才进行设置操作,等同于SETNX key value
- XX:只在键已存在时,才进行操作,等同于SETXX key value
- GET key
- 如果key不存在,返回nil,否则返回key的值
- STRLEN key
返回key存储的字符串值的长度
- key不存在时,返回0
- APPEND key value
key存在且value为字符串,该命令把value追加到现有值的末尾,如果key不存在,就将添加key-value
- 返回最终value的长度
- GETRANGE key start end
返回start-end的子串,包含end,可以包含负数偏移量
- INCR key
为
key
储存的数字值加上一。如果键key
不存在, 那么它的值会先被初始化为0
, 然后再执行INCR
命令。如果键key
储存的值不能被解释为数字, 那么INCR
命令将返回一个错误
- 本操作的值限制在 64 位(bit)有符号数字表示之内
INCR
命令是一个针对字符串的操作。 因为 Redis 并没有专用的整数类型, 所以键key
储存的值在执行INCR
命令时会被解释为十进制 64 位有符号整数- 返回修改后的值
- INCRBY key increment
为
key
储存的数字值加上increment
increment
可以为负值- 在加上增量
increment
之后,key的值
- INCRBYFLOAT key increment
为键 key 储存的值加上浮点数增量 increment
- 在加上增量 increment 之后,key的值
- increment可以为负值
- MSET key value [key value…]
同时为多个key设置值,如果某个给定key已经存在,则会用新值覆盖旧值
- 该操作为原子性操作,所有给定key都会在同一时间内被设置
- 总是返回OK
- MSETNX key value [key value…]
当且仅当所有给定键都不存在时, 为所有给定键设置值。即使只有一个给定键已经存在,
MSETNX
命令也会拒绝执行对所有键的设置操作
- 操作成功返回1,操作失败返回0
2.Hash操作
- HSET hash field value
将hash中field的值设置为value,如果给定的hash不存在,则创建新的,否则覆盖
- 如果创建新的hash则返回1,如果覆盖则返回0
- HSETNX hash field value
只允许创建hash,不允许覆盖
- 操作成功返回1,失败返回0
- HGET hash filed
返回hash的field值
- 如果filed的值不存在,返回nil
- HEXISTS hash field
检查field是否存在于hash中
- filed存在返回1,不存在返回0
- HLEN hash
返回hash中field的数量
- HSTRLEN hash field
返回hash中,给定field关联的值的字符串长度
- HINCRBY hash field increment
为hash中field加上增量increment,可以为负数
- HINCRBYFLOAT key field increment
为hash中field加上浮点数增量increment
- HMSET hash filed value [filed value …]
同时将多个field-value(域-值)对设置到哈希表 key 中。此命令会覆盖哈希表中已存在的域。如果 key不存在,一个空哈希表被创建并执行HMSET操作
- HMGET hash field [filed…]
返回hash中一个或多个给定field的值,如果field不存在,则返回nil
- HKEYS hash
返回hash中的所有field
- HVALS hash
返回hash中所有field的value
- HGETALL hash
返回hash中所有的field和value
- 返回值中一行key一行value
- HDEL hash filed [field…]
删除hash中的一个或多个指定的filed,不存在的field会被忽略
3.List操作
- LPUSH list value [value…]
将一个或多个值插入到列表的头(入栈),如果list不存在,则会创建新的列表
- 返回列表的长度
- LPUSHX list value [value…]
如果list不存在,则什么都不做
- RPUSH list value [value…]
从list的尾部入栈
- RPUSHX list value [value…]
从list的尾部入栈,如果list不存在,则什么都不做
- LPOP list
移除并返回list左元素
- 如果list不存在,返回nil
- RPOP list
移除并返回list右元素
- LREM list count value
根据参数count的值,移除列表中与value相等的元素
- count > 0 : 从表头开始向表尾搜索,移除与 value相等的元素,数量为 count
- count < 0 : 从表尾开始向表头搜索,移除与 value相等的元素,数量为 count的绝对值
- count = 0: 移除表中所有与 value相等的值
- 返回被移除元素的数量
- LLEN list
返回list长度,如果list不存在,则返回0;如果不是列表类型,返回一个错误
- LINDEX list index
返回list中index的元素,可以使用负数
- 如果index超过区间范围,返回nil
- LINSERT list BEFORE|AFTER pivot value
将value插入list中,位于pivot之前或之后
- 执行成功返回列表的长度
- 当pivot不存在时,不执行任何操作,返回-1
- 当list不存在时,不执行任何操作,返回0
- 如果list不是列表,返回一个错误
- LSET list index value
将list中下标为index的元素设置为value
- 操作成功,返回ok
- index超过区间范围,返回错误信息
- LRANGE list start stop
返回list中指定区间的元素,包括stop下标的元素
- 超出下标不会引起错误
- LTRIM list start stop
对list进行修剪,只保留start到stop之间的元素,其余均被删除
- 操作成功,返回ok
- 如果start超过stop,会清空所有列表
- 如果stop超过最大长度,会自动转变为最大长度
4.Set操作
- SADD set member [member]
将一个或多个member元素加入set,如果set不存在,会自动创建
- 重复元素将被忽略
- 如果set不是集合类型,返回错误
- SISMEMEBER set member
判断member是否是set的成员
- 如果是返回1,如果不是,返回0
- SPOP set
移除并返回集合中的一个随机元素
- 当set不存在或set为空时,返回nil
- SRANDMEMBER set [count]
返回set中的随即元素,但并不删除
- 如果
count
为正数,且小于集合基数,那么命令返回一个包含count
个元素的数组,数组中的元素各不相同。如果count
大于等于集合基数,那么返回整个集合。 - 如果
count
为负数,那么命令返回一个数组,数组中的元素可能会重复出现多次,而数组的长度为count
的绝对值。 - 如果集合为空,返回nil,如果提供了count参数,则返回一个数组
- SREM set member [member…]
移除set中的一个或多个member元素,不存在的member会被忽略
- 返回被成功移除的元素的数量,不包括被忽略的元素
- 如果set不是集合类型,则返回错误
- SMOVE source destination member
将member元素从source集合中移动到destination集合中,source中的member会被删除
- 该操作时原子性操作
- 操作成功返回1,失败则返回0
- SCARD set
返回set中的元素数量
- set不存在则返回0
- SMEMBERS set
返回set中的所有元素
- SINTER set [set…]
返回所有集合的交集
- SINTERSTORE destination set [set…]
将集合之间的交集保存在新的destionation集合中,如果destination已经存在,则覆盖
- 返回集合元素数量
- SUNION set [set…]
返回所有集合的并集
- SUNIONSTORE destination set [set…]
将集合之间的并集保存在新的destionation集合中,如果destination已经存在,则覆盖
- 返回集合元素数量
- SDIFF set [set…]
返回所有集合的差集
- SDIFFSTORE destination set [set…]
将集合之间的差集保存在新的destionation集合中,如果destination已经存在,则覆盖
- 返回集合元素数量
5.Zset操作
- ZADD sset score member [[score member] …]
将一个或多个member以及其score加入有序集sset中
- score可以是整数或双精度浮点数
- 返回成功添加的元素数量,不包括那些被更新的,已经存在的元素
- 如果某个member已经是sset的元素了,那么更新这个member的score值
- ZSCORE sset member
返回sset中member的score值
- ZINCRBY sset increment member
为sset中的member添加增量,该increment可以为负值
- 返回member的新score值
- ZCARD sset
返回sset的成员数量
- 当sset不存在时,返回0
- ZCOUNT key min max
返回sset中,score值在min和max区间的成员的数量
- ZRANGE sset start stop [WITHSCORES]
返回指定区间的成员,按score值递增排序
3.调试工具
1.PING
使用客户端向Redis服务器发送一个
PING
,通常用于测试与服务器的连接是否仍然生效,或者用于测量延迟值
- 如果连接正常就返回一个 PONG ,否则返回一个连接错误
2.ECHO
打印一个特定的信息message,测试时使用
3.SLOWLOG
Slow log是Redis用来记录查询执行时间的日志系统
- 查询执行时间指的是不包括像客户端响应(talking)、发送回复等IO操作,而单单是执行一个查询命令所耗费的时间
- 另外,slow log保存在内存里面,读写速度非常快,因此你可以放心地使用它,不必担心因为开启slow log而损害 Redis 的速度。
- CONFIG SET/GET
Slow log 的行为由两个配置参数(configuration parameter)指定,可以通过改写
redis.conf
文件或者用CONFIG GET
和CONFIG SET
命令对它们动态地进行修改
- slowlog-log-slower-than:决定要对执行时间大于多少微妙额的查询进行记录
- slowlog-max-len:决定slow log最多能保存多少条日志,slow log本身是一个FIFO队列,当队列大小超过该值时,最旧的一条日志删除,最新一条日志加入slow log
CONFIG GET slowlog-log-slower-than
1) "slowlog-log-slower-than"
2) "1000"
CONFIG SET slowlog-max-len 1000
"OK"
- SLOW LOG GET [number]
查看SLOW LOG,可以指定多少条
- SLOWLOG LEN
查看当前日志数量
- SLOWLOG RESTET
清空日志
4.MONITOR
实时打印出 Redis 服务器接收到的命令,调试用
- 总是返回ok
三、持久化方式
1.RDB(Redis DataBase)
以指定的时间间隔执行数据集的时间点快照
优点
- 适合灾难性恢复,且能够远程传输到数据中心
- 最大限度地提高Redis性能,因为Redis父进程要持久化,唯一需要做的工作就是分叉一个子进程,它将完成所有其他工作。父进程永远不会执行磁盘I/O或类似操作
- 与AOF相比,允许使用大数据集更快地重新启动
- RDB是Redis数据的非常紧凑的单文件时间点表示。RDB文件非常适合备份
缺点
- 如果对数据的完整性非常敏感,那么RDB就不太适合,因为即使每5分钟都持久化一次,当Redis故障时,仍然会有近5分钟的数据丢失
- RDB需要经常fork(),以便使用子进程在磁盘上持久化。如果数据及很大,fork()会很耗时,如果数据及很大且CPU性能不好,可能会导致Redis停止服务客户端一段时间
2.AOF(Append Only File)
记录服务器接收到的每个写入操作。然后,可以在服务器启动时重新播放这些操作,重建原始数据集。使用与Redis协议本身相同的格式记录命令
优点
- 默认的AOF持久化策略是每秒钟fsync一次(fsync是指把缓存中的写指令记录到磁盘中),因为在这种情况下,Redis仍然可以保持很好的处理性能,即使Redis故障,也只会丢失最近1秒钟的数据
- AOF日志是一个仅追加不允许改写的日志,在停电时不会出现查找或损坏问题。即使由于某种原因(磁盘已满或其他原因),日志以半写命令结束,redis-check-aof工具也能够轻松修复
- AOF以易于理解和解析的格式包含一个接一个的所有操作的日志。您甚至可以轻松导出AOF文件。例如,即使您意外地使用FLUSHALL命令刷新了所有内容,只要在此期间没有重写日志,您仍然可以通过停止服务器、删除最新命令并重新启动Redis来保存数据集。
缺点
- 通常比RDB文件大
- 根据确切的fsync策略,AOF可能比RDB慢。一般来说,将fsync设置为每秒一次的情况下,性能仍然很高,并且禁用fsync时,即使在高负载下,它也应该与RDB一样快。尽管如此,即使在巨大的写入负载的情况下,RDB也能够提供关于最大延迟的更多保证
3.RDB+AOF
RDB和AOF也可以同时使用
四、主从同步
1.用法
-
像MySQL一样,Redis是支持主从同步的,而且也支持一主多从以及多级从结构。
-
主从结构,一是为了纯粹的冗余备份,二是为了提升读性能,比如很消耗性能的SORT就可以由从服务器来承担。
-
Redis的主从同步是异步进行的,这意味着主从同步不会影响主逻辑,也不会降低Redis的处理性能。
主从架构中,可以考虑关闭主服务器的数据持久化功能,只让从服务器进行持久化,这样可以提高主服务器的处理性能。
在主从架构中,从服务器通常被设置为只读模式,这样可以避免从服务器的数据被误修改。但是从服务器仍然可以接受CONFIG等指令,所以还是不应该将从服务器直接暴露到不安全的网络环境中。如果必须如此,那可以考虑给重要指令进行重命名,来避免命令被外人误执行。
2.主从同步
1.为什么需要主从同步
- 在使用Redis服务的时候如果使用单机服务,一旦单机服务宕机了,那么可能导致整个系统处于不可用状态,或者当系统的访问量大了以后单机的Redis服务成功了整个系统的瓶颈,这时候就到了主从复制展示伸手的时候了。主从复制可以帮我们完成以下功能:
- 数据冗余:主从复制实现了数据的热备份,是持久化之外的一种数据冗余方式
- 故障恢复:当主节点出现问题时,可以由从节点提供服务,实现快速的故障恢复;实际上是一种服务的冗余
- 负载均衡:在主从复制的基础上,配合读写分离,可以由主节点提供写服务,由从节点提供读服务(即写Redis数据时应用连接主节点,读Redis数据时应用连接从节点),分担服务器负载;尤其是在写少读多的场景下,通过多个从节点分担读负载,可以大大提高Redis服务器的并发量
- 高可用基石:主从复制还是哨兵和集群能够实施的基础,因此说主从复制是Redis高可用的基础
2.主从同步流程
1)建立连接
1. 当从库执行了replicaof ip port
命令之后从服务器保存主服务器的ip和porti信息
2. 从服务器和主服务器建立socket
连接
3. 从服务器发送ping
命令,并且接收主服务器的pong
命令,如果没有接收到pong
命令则从新建立连接
4. 如果主服务器设置了访问密码则进行权限校验,如果权限校验通过则开始进行数据同步
2)确定同步方式
1. 从服务器发送psync runid offset
命令到主服务器,第一次同步的时候由于还没有主服务器的runid
,所以使用?代替
2. 主服务器收到psync命令之后首先判断runid是否和自己的runid一致,如果不一致或者为?,则进行全量同步,主服务器返回给从服务器fullresync响应,如果runid和主服务器一致则判断offset是否还在repl_backlong_buffer缓冲区的范围内,如果不在该缓冲区的范围内了,则进行全量同步,主服务器返回给从服务器fullresync响应,如果在缓冲区范围内则进行增量同步,主服务器返回给从服务器continue响应。如果主服务器详情的是fullresync则还会带上当前服务器runid和目前主库的复制进度offset
3.全量同步
- 当主服务器响应给从服务器fullresync响应之后,主服务器开始执行bgsave命令,生成RDB文件,并且在rdb文件生成完之后会把整个rdb文件发送给从服务器,从服务器接收到rdb文件之后会清空自己的数据库,然后把rdb文件读取到自己的数据库中。由于主服务器在生成rdb文件的时候是不阻塞的,主服务器还可以继续向外提供服务,这时候为了保证主从服务器的数据一致性,主服务器需要把从开始执行bgsave命令到发送rdb文件到从服务器和从服务器把RDB文件恢复到内存中这段时间的所有写命令保存下来然后发给从服务器执行,保存这些写命令的空间就是replication_buffer。他是专门用来保存主服务器在生成rdb文件的时候的写命令的
- 如果在主服务器生成RDB到从服务器根据RDB文件把数据恢复到内存中这段时间产生的写命令太多导致replication_buffer保存不了会导致主服务器主动断开主从连接,主服务器会释放掉相关数据,这时候会重新开始主从复制.如果replication_buffer太小会导致这个过程无限循环.所以推荐把replication_buffer设置的大一些,防止出现这种情况
4.增量同步
- 当全量同步完成之后,由于从服务器已经拿到了主服务器的runid和offset,这时候主从服务器之间开始进行增量复制。增量复制的时候主服务器并不是同步的把所有的写命令直接发送给从服务器而是把写命令缓存到一个叫repl_backlog_buffer的空间中,然后集中把写命令和offset发送给从服务器,从服务器在接收到命令执行完成之后会把执行了的命令的offset发送给主服务器,这样主服务器可以根据从服务器返回的offset判断哪些命令还没有执行,然后决定下次发送给从服务器的命令和offset
- repl_backlog_buffer是一个环形空间,时间久了新写入的数据会把之前写入的数据覆盖掉,如果从服务器返回的offset不在这个环形空间中,则主服务器会判定数据不一致,然后触发一次全量同步
- repl_backlog_buffer还用在了当主从服务器之间断开连接重新连接之后,从服务器发送psync命令,并且带了runid和offset参数,如果主服务器发现offset还在环形空间中,则不会进行全量服务,而是返回continue继续增量复制。
5.无盘复制
- 通常来讲,一个完全重新同步需要在磁盘上创建一个RDB文件,然后加载这个文件以便为从服务器发送数据。如果使用比较低速的磁盘,这种操作会给主服务器带来较大的压力。特别是当系统正在进行 AOF 的 fsync 操作时如果发生快照,fsync 将会被推迟执行,这就会严重影响主节点的服务效率。所以从 Redis 2.8.18 版开始支持无盘复制。所谓无盘复制是指主服务器直接通过套接字将快照内容发送到从节点,生成快照是一个遍历的过程,主节点会一边遍历内存,一边将序列化的内容发送到从节点,从节点还是跟之前一样,先将接收到的内容存储到磁盘文件中,再进行一次性加载
五、事务处理
1.MULTI
标记一个事务块的开始。事务块内的多条命令会按照先后顺序被放进一个队列当中,最后由EXEC命令原子性(atomic)地执行
redis> MULTI # 标记事务开始
OK
redis> INCR user_id # 多条命令按顺序入队
QUEUED
redis> INCR user_id
QUEUED
redis> INCR user_id
QUEUED
redis> PING
QUEUED
redis> EXEC # 执行
1) (integer) 1
2) (integer) 2
3) (integer) 3
4) PONG
2.EXEC
执行所有事务块内的命令
- 假如某个(或某些) key 正处于WATCH命令的监视之下,且事务块中有和这个(或这些) key 相关的命令,那么 命令只在这个(或这些) key 没有被其他命令所改动的情况下执行并生效,否则该事务被打断(abort)
- 事务块内所有命令的返回值,按命令执行的先后顺序排列
- 当操作被打断时,返回空值 nil
3.DISCARD
取消事务,放弃执行事务块内的所有命令
- 如果正在使用 WATCH命令监视某个(或某些) key,那么取消所有监视,等同于执行命令UNWATCH
- 返回值为OK
4.WATCH key [key…]
监视一个(或多个) key ,如果在事务执行之前这个(或这些) key 被其他命令所改动,那么事务将被打断
- 返回值为OK
- 相当于一个乐观锁,CAS(check and set)
5.UNWATCH
取消WATCH命令对所有 key 的监视
- 如果在执行WATCH命令之后,EXEC命令或 DISCARD命令先被执行了的话,那么就不需要再执行 UNWATCH了
- 因为 EXEC命令会执行事务,因此 WATCH命令的效果已经产生了;而 DISCARD命令在取消事务的同时也会取消所有对 key 的监视,因此这两个命令执行之后,就没有必要执行UNWATCH了