redis入门

李子骅老师《Redis入门指南(第二版)》学习笔记

简介

Redis是一个开源的、高性能的、基于键值对的缓存与存储系统。

redis和mysql的区别

区别

类型

存储

读写速度

底层数据结构

时间复杂度

mysql

关系型数据库

磁盘

较慢

B+ tree

O(logn)

redis

非关系型数据库

内存

较快

键值对

O(1)

redis和Mencached的区别

都是非关系型、基于内存的存储系统。

redis支持字符串,散列,列表,集合,有序集,位图,超级日志和空间索引;而Memcached支持字符串和整数。

redis是单线程模型,Memcached支持多线程,理论在多核服务器上Memcached的性能更高一些。

Memcached不支持复制,redis支持主从复制。

安装

Installing Redis | Redis

数据类型

字符串 Strings

Redis字符串是最基本的Redis数据类型,表示字节序列

命令

含义

set key value

赋值

get key

取值

incr key

递增(+1)

incrby key value

增加指定整数

decrby key value

减少指定整数

incrbyfloat key value

增加指定浮点数

append key value

向尾部增加值

strlen key

获取字符串长度

mset key value [ key2 value2 ...]

同时设置多个键值

mget key value [ key2 value2 ...]

同时获得多个键值

列表 Lists

Redis列表是按插入顺序排序的字符串列表。 内部是使用双向链表实现的,所以在列表两端添加元素的时间复杂度为O(1),获取越接近两端的元素速度就越快,代价是通过索引访问元素比较慢。

redis入门_第1张图片

命令

含义

lpush key value [ value ...]

向列表左边增加元素

rpush key value [ value ...]

向列表右边增加元素

lpop key

从列表左边弹出元素

rpop key

从列表右边弹出元素

llen key

获取列表中元素个数

lrange key start stop

获得列表片段(包含两端)
起始索引为0,右边第一个索引为-1

lrem key count value
count>0 从列表左边开始删除前count个值为value的元素
count<0 从列表右边开始删除前|count|个值为value的元素
count=0 删除所有值为value的元素

删除列表中指定值

lindex key index

获得指定索引的元素值

lset key index value

设置指定索引的元素值

ltrim key start stop

删除指定范围外的所有元素

linsert key before/after pivot value

向列表中插入元素

集合 Sets

集合是唯一字符串的无序集合,其行为类似于您喜爱的编程语言(例如,Java HashSet、Python集合等)中的集合。 由于集合类型在redis内部是使用值为空的散列表实现的所以这些操作的时间复杂度都是O(1)

集合与列表的区别

集合

列表

存储内容

至多223-1个字符串

至多223-1个字符串

有序性

唯一性

命令

含义

sadd key member [ member ...]

增加元素

srem key member [ member ...]

删除元素

smembers key

获得集合中的所有元素

sismember key value

判断元素是否在集合中

sdiff key [ key ...]

集合差集运算

sunion key [ key ...]

集合并集运算

sinter key [ key ...]

集合交集运算

scard key

获得集合中元素个数

srandmember key

随机获得集合中元素

spop key

从集合中弹出一个元素

散列 Hashes

散列的键值也是一种字典结构,存储了字段和字段值的映射。 类似于Java的hashmap

redis入门_第2张图片

命令

含义

hset key field value

赋值

hget key field value

取值

hmset / hmget key field value [field1 value1 ...]

赋值/取值多个字段

hexists key field

判断字段是否存在

hsetnx key field value

字段不存在时赋值

hincrby key field num

增加数字

hdel key field [ field1 ...]

删除字段

hkeys key

只获取字段名

hvals key

只获取字段值

hlen key

获得字段数量

hgetall key

获取字段和字段值

有序集合 Sorted Sets

有序集合是唯一字符串的集合,通过每个字符串的关联分数维持顺序

命令

含义

zadd key score member [ score member ...]

增加元素

zscore key member

获得元素分数

zrange / zrevrange key start stop [withscores]

获得排名在某个范围内的元素列表

zrangebyscore key min max [withscores] [limit offset count]

获得指定分数范围的元素

zincrby key increment member

增加某个元素的分数

zcard key

获得集合中元素的数量

zcount key min max

获得指定分数范围内的元素个数

zrem key member [ member ...]

删除一个或多个元素

zremrangebyrank key start stop

按照排名范围删除元素

zremrangebyscore key min max

按照分数范围删除元素

zrank/zrevrank key member

获得元素的排名

Streams

Redis流是一种数据结构,其作用类似于只追加日志。流有助于按照事件发生的顺序记录事件,然后将其联合起来进行处理

Geospatial indexes

Redis地理空间索引对于查找给定地理半径或边界框内的位置非常有用

Bitmaps

Redis位图允许您对字符串执行逐位操作。

Bitfields

Redis位字段有效地编码字符串值中的多个计数器。位字段提供原子获取、设置和增量操作,并支持不同的溢出策略

HyperLogLog

Redis HyperLogLog数据结构提供了大集合基数(即元素数量)的概率估计

进阶

事务

redis中的事务(transaction),是一组命令的集合。

使用multi开始一个事务,exec执行事务

redis入门_第3张图片

错误处理:

1) 语法错误,命令不存在 / 命令参数个数不对 : 执行exec命令后,连正确的命令也不会执行

redis入门_第4张图片

2)运行错误,命令执行时出现的错误:事务里其他的命令都会执行,包括出错命令之后的命令

redis入门_第5张图片

过期时间

redis入门_第6张图片

设置过期时间: expire key 秒

取消过期时间:persist key ; 使用set/getset为键赋值也会清除键的过期时间

只对键值进行操作的命令(incr、lpush、hset、zrem)不会影响过期时间

当服务器内存有限时,如果大量的使用缓存键且过期时间设置的过长就会导致redis占满内存;另一方面如果为了防止redis占用内存过大而将缓存键的过期时间设的太短,就可能导致缓存命中率过低并且大量内存白白的闲置,为此可以限制redis的最大使用内存

设置方法:修改配置文件的maxmemory参数,限制redis最大可用内存大小(单位是字节),当超出了这个限制时redis会根据maxmemory-police参数指定的策略来删除不需要的键直到redis占用的内存小于指定内存

排序

sort

排序列表

redis入门_第7张图片

排序集合

redis入门_第8张图片

redis入门_第9张图片

排序有序集合: 会忽略元素的分数,只针对元素自身的值进行排序

redis入门_第10张图片

by

by参数的语法为by参考键。其中参考键可以是字符串类型或者是散列类型键的某个字段(表示为 键名->字段名),如果提供了by参数,sort命令将不再依据元素自身的值进行排序,而是对每个元素使用元素的值,替换参考键中的第一个* 并获取其值,然后根据该值对元素进行排序

散列类型的键:

redis入门_第11张图片

字符串类型的键:

redis入门_第12张图片

redis入门_第13张图片

get

get参数可以有多个,不影响排序,支持字符串类型和散列类型的键。 他的作用是使sort命令返回的结果不再是元素自身的值,而是get参数重指定的键值

redis入门_第14张图片

redis入门_第15张图片

get # 返回元素本身的值

store

保存排序结果

redis入门_第16张图片

消息通知

任务队列

任务队列顾名思义就是“传递任务的队列”,与任务队列交互的实体有两类,一类是生产者,一类是消费者。生产者会将需要处理的任务放入任务队列中,而消费者不断的从任务队列中读入任务信息并执行

好处:松耦合、易于扩展

利用BRPOP命令,会一直阻塞链接,直到有新元素加入。

格式: brpop 键名 超时时间 。 超市时间单位时秒,为0表示不限制等待时间

redis入门_第17张图片

如上图,实例A处于阻塞状态, 此时在实例B中像queue加入一个元素

redis入门_第18张图片

A马上返回了结果

redis入门_第19张图片

优先级队列

格式:blpop queue:1 queue:2 queue:3 0

解释:如果所有键都没有元素则阻塞;

如果其中有一个键有元素则弹出;

如果多个键有元素则按照从左往右的顺序取第一个键中的一个元素。

发布/订阅模式

发布/订阅模式同样可以实现进程间的消息传递

发布者发消息: publish channel message , 返回值表示收到此条消息的订阅者数量,没有人订阅,则返回0

订阅消息: subscribe channel [ channel ...]

取消订阅消息: unsubscribe channel [ channel ...]

实例A进入订阅状态:

redis入门_第20张图片

实例B发布消息:

redis入门_第21张图片

管道

客户端和redis使用TCP协议链接,执行多个命令时每条都需要等待上一条命令执行完才能执行。

redis对管道(pipelining)提供了支持,通过管道可以一次性发送多条命令,并在执行完后一次性将结果返回,当一组命令中每条命令都不依赖于之前命令的执行结果时可以将这组命令一起通过管道发出。

redis入门_第22张图片

持久化

我们希望redis能将数据从内存中以某种形式同步到硬盘中,使得重启之后可以根据硬盘中的记录恢复数据,这一过程就是持久化。

redis支持两种方式的持久化,一种是RDB方式,另一种是AOF方式

ADB

ADB的方式是通过快照完成的,当符合一定条件时Redis会自动将内存中的所有数据生成一份副本并存储在硬盘上。redis会在以下几种情况对数据进行快照

1) 根据配置规则(redis.conf)进行自动快照

redis入门_第23张图片

2) 用户执行SAVE或BGSAVE命令

执行save时,同步进行快照操作,执行过程会阻塞所有来自客户端的请求

执行bgsave时,异步进行快照操作,使用lastsave获取最近一次快照的时间

3) 执行FLUSHALL命令

会清空所有数据

4) 执行复制(replication)时

设置了主从模式时,redis会在复制初始化时进行自动快照

快照原理:

  1. redis使用fork函数复制一份当前进程(父进程)的副本(子进程)
  2. 父进程继续接收并处理客户端发来的命令,而子进程开始将内存中的数据写入硬盘中的临时文件
  3. 当子进程写入完所有数据后会用该临时文件替换旧的dump.rdb文件,至此一次快照操作完成

优点:

在进行快照的过程中不回修改rdb文件,只有快照结束后才会将旧的文件替换成新的,也就是说任何时候rdb文件都是完整的。rdb文件是经过压缩的二进制格式,占用空间小传输快

缺点:

一旦redis异常退出,就会丢失最后一次快照以后更改的所有数据

AOF

默认是关闭的,开启AOF持久化后每执行一条会更改redis中数据的命令,redis就会将该命令写入硬盘中的AOF文件,默认文件名是appendonly.aof

redis入门_第24张图片

缺点:

在启动时redis会逐个执行AOF文件中的命令将硬盘中的数据载入到内存中,载入的速度相对rdb会慢一些

集群

复制

为了避免单点故障,通常的做法是将数据库复制多个副本以部署在不同的服务器上,这样即使有一台服务器出现故障,其他服务器依然可以继续提供服务,为此redis提供了复制的功能。

主数据库:可以进行读写操作,当写操作导致数据变化时自动将数据同步给从数据库

从数据库:只读,接受主数据库同步过来的数据,一个从数据库只能有一个主数据库,从数据库自己也可作为主数据库

启动一个主redis数据库 redis-server

启动一个从redis数据库 redis-server --port 6380 --slaveof 127.0.0.1 6379

redis实现复制的过程:

  1. 复制初始阶段。从数据库启动后,会向主数据库发送SYNC命令,主数据库收到后开始在后台保存快照(RBD持久化过程),并将快照期间收到的命令缓存起来。当快照完成后,redis会将快照文件和缓存命令发送给从数据库,从数据库收到后进行载入
  2. 复制同步阶段。主数据库执行任何会导致数据变化的命令都会异步的传送给从数据库

通过复制可以实现读写分离,以提高服务器的负载能力。

哨兵

哨兵的作用

  1. 监控主数据库和从数据库是否正常运行
  2. 主数据库出现故障时自动将从数据库转换为主数据库

哨兵是一个独立的进程,可以使用多个哨兵进行监控任务以保证系统足够稳健,哨兵不仅会同时监视主数据库和从数据库,哨兵之间也会相互监督。

实现原理

1)一个哨兵进程启动时会读取配置文件的内容,找到需要监控的主数据库,一个哨兵可同时监视多个redis主从系统

sentinel monitor master-name ip redis-port quonum

2)和主数据库建立连接后会定时执行下面的操作

  • 每十秒哨兵会向主数据库和从数据库发送info命令(实现新节点的自动发现)
  • 每两秒哨兵会向主数据库和从数据库的_sentinel_:hello频道发送自己的信息(与同样监控该数据库的哨兵分享自己的信息)
  • 每一秒哨兵会向主数据库和从数据库和其他哨兵节点发送ping命令(监控节点有无停止服务:主观下线-> 客观下线-> 选举领头哨兵进行故障恢复-> 挑选新的主节点)

你可能感兴趣的:(数据库,redis,数据库,缓存)