Redis是一个使用ANSI C编写的开源、支持网络、基于内存、可选持久性的键值对存储数据库。从2015年6月开始,Redis的开发由Redis Labs赞助,而2013年5月至2015年6月期间,其开发由Pivotal赞助。在2013年5月之前,其开发由VMware赞助。根据月度排行网站DB-Engines.com的数据显示,Redis是最流行的键值对存储数据库。
Redis主要有这几部分知识,五大数据类型,持久化方式,发布订阅,主从复制+哨兵。
Redis的安装
centos安装redis
1 | wget http://download.redis.io/releases/redis-6.0.5.tar.gz |
centos 设置redis开启自启动
1 | sudo vim /usr/lib/systemd/system/redis.service |
redis开启远程连接(redis.conf)
1 | ## redis.conf 的一些配置 |
五大数据类型
redis中的数据都是以key/value的形式存储的,五大数据类型主要是指value的数据类型。
String字符串
最基础的数据类型,需要注意的是redis中的字符串大小上限是512M。
APPEND
使用APPEND命令时,如果key已经存在,则会直接在value后追加值,如果key不存在,则会先创建一个value为空字符串的key,然后再追加。
1 | 127.0.0.1:6379> get k1 |
GET
GET命令用来获取对应key的value,如果key不存在则返回nil。
1 | 127.0.0.1:6379> get k1 |
GETRANGE
GETRANGE用来返回key所对应的value的子串,子串由start和end决定,从左往右计算,如果下标是负数,则从右往左计算,其中-1表示最后一个字符,-2是倒数第二个…
1 | 127.0.0.1:6379> getrange k1 1 3 |
GETSET
GETSET命令可以用来获取key所对应的value,并对key进行重置。
1 | 127.0.0.1:6379> get k2 |
SETRANGE
SETRANGE用来覆盖一个已经存在的key的value。
1 | 127.0.0.1:6379> setrange k2 2 range |
SETEX
SETEX用来给key设置value,同时设置过期时间,等效于先给key设置value,再给key设置过期时间。
1 | 127.0.0.1:6379> setex k4 5 v4 |
SETNX
SETNX是 SET if Not eXists的简写,SET命令在执行时,如果key已经存在,则新值会覆盖掉旧值,而对于SETNX命令,如果key已经存在,则不做任何操作,如果key不存在,则效果等同于SET命令。
1 | 127.0.0.1:6379> setnx k4 v4v4 |
List列表
LIST是一个简单的字符串列表,按照插入顺序进行排序,可以从头尾插入或弹出。
LPUSH
将一个或多个值value插入到列表key的表头,如果有多个value值,那么各个value值按从左到右的顺序依次插入到表头。
1 | 127.0.0.1:6379> lpush l1 v1 v2 v3 v4 v5 |
LRANGE
返回列表key中指定区间内的元素,区间以偏移量start和stop指定,下标(index)参数start和stop都以0为底,即0表示列表的第一个元素,1表示列表的第二个元素,以此类推。我们也可以使用负数下标,以-1表示列表的最后一个元素, -2 表示列表的倒数第二个元素,以此类推。
1 | 127.0.0.1:6379> lrange l1 0 -1 |
RPUSH
RPUSH与LPUSH的功能基本一致,不同的是RPUSH的中的value值是按照从右到左的顺序依次插入。
1 | 127.0.0.1:6379> rpush l1 v6 v7 |
RPOP
RPOP命令可以移除并返回列表key的尾元素。
1 | 127.0.0.1:6379> rpop l1 |
LPOP
LPOP和RPOP类似,不同的是LPOP移除并返回列表key的头元素。
1 | 127.0.0.1:6379> lpop l1 |
LINDEX
LINDEX命令可以返回列表key中,下标为index的元素,正数下标0表示第一个元素,也可以使用负数下标,-1表示倒数第一个元素。
1 | 127.0.0.1:6379> lrange l1 0 -1 |
Hash键值对
HASH类似于Java中的Map,是一个键值对集合,在redis中可以用来存储对象。
HSET
HSET命令可以用来设置key指定的哈希集中指定字段的值。
1 | 127.0.0.1:6379> hset hk1 k1 v1 k2 v2 k3 v3 k4 v4 k5 v5 |
HGET
HGET命令可以用来返回key指定的哈希集中该字段所关联的值。
1 | 127.0.0.1:6379> hget hk1 k1 |
HDEL
HDEL命令可以从key指定的哈希集中移除指定的域,在哈希集中不存在的域将被忽略。
1 | 127.0.0.1:6379> hdel hk1 k1 |
HSETNX
HSETNX命令只在key指定的哈希集中不存在指定的字段时,设置字段的值,如果字段已存在,该操作无效果。
1 | 127.0.0.1:6379> hsetnx hk1 k1 v11 |
HVALS
HVALS命令可以返回key指定的哈希集中所有字段的值。
1 | 127.0.0.1:6379> hvals hk1 |
HKEYS
HKEYS命令可以返回key指定的哈希集中所有字段的名字。
1 | 127.0.0.1:6379> hkeys hk1 |
HGETALL
HEXISTS命令可以返回hash里面field是否存在。
1 | 127.0.0.1:6379> hgetall hk1 |
HLEN
HSTRLEN可以返回hash指定field的value的字符串长度,如果hash或者field不存在,返回0。
1 | 127.0.0.1:6379> hlen hk1 |
Set集合
SET是String类型的无序集合,不同于LIST,SET中的元素不可以重复。
SADD
SADD命令可以添加一个或多个指定的member元素到集合的key中,指定的一个或者多个元素member如果已经在集合key中存在则忽略,如果集合key不存在,则新建集合key,并添加member元素到集合key中。
1 | 127.0.0.1:6379> sadd sk1 v1 v2 v3 v3 v4 |
SREM
SREM命令可以在key集合中移除指定的元素,如果指定的元素不是key集合中的元素则忽略。如果key集合不存在则被视为一个空的集合,该命令返回0。
1 | 127.0.0.1:6379> srem sk1 v5 |
SISMEMBER
SISMEMBER命令可以返回成员member是否是存储的集合key的成员。
1 | 127.0.0.1:6379> sismember sk1 v4 |
SCARD
SCARD命令可以返回集合存储的key的基数(集合元素的数量)。
1 | 127.0.0.1:6379> scard sk1 |
SMEMBERS
SMEMBERS命令可以返回key集合所有的元素。
1 | 127.0.0.1:6379> smembers sk1 |
SPOP
SPOP命令的用法和SRANDMEMBER类似,不同的是,SPOP每次选择一个随机的元素之后,该元素会出栈,而SRANDMEMBER则不会出栈,只是将该元素展示出来。
1 | 127.0.0.1:6379> spop sk1 |
SDIFF
SDIFF可以用来返回一个集合与给定集合的差集的元素。
1 | 127.0.0.1:6379> smembers sk1 |
SDIFFSTORE
SDIFFSTORE命令与SDIFF命令基本一致,不同的是SDIFFSTORE命令会将结果保存在一个集合中。
1 | 127.0.0.1:6379> sdiffstore sk3 sk2 sk1 |
SINTER
SINTER命令可以用来计算指定key之间元素的交集。
1 | 127.0.0.1:6379> smembers sk2 |
SUNION
SUNION可以用来计算两个集合的并集。
1 | 127.0.0.1:6379> sunion sk1 sk3 |
ZSet有序集合
ZSET和SET一样,也是STRING类型的元素的集合,不同的是ZSET中的每个元素都会关联一个double类型的分数,ZSET中的成员都是唯一的,但是所关联的分数可以重复。
ZADD
ZADD命令可以将所有指定成员添加到键为key的有序集合里面。添加时可以指定多个分数/成员(score/member)对。 如果指定添加的成员已经是有序集合里面的成员,则会更新该成员的分数(scrore)并更新到正确的排序位置。
1 | 127.0.0.1:6379> zadd zk1 10 v1 20 v2 30 v3 40 v4 10 v5 |
ZSCORE
ZSCORE命令可以返回有序集key中,成员member的score值。
1 | 127.0.0.1:6379> zscore zk1 v1 |
ZRANGE
ZRANGE命令可以根据index返回member,该命令在执行时加上withscores参数可以连同score一起返回。
1 | 127.0.0.1:6379> zrange zk1 0 -1 |
ZCOUNT
ZCOUNT命令可以返回有序集key中,score值在min和max之间(默认包括score值等于min或max)的成员。
1 | 127.0.0.1:6379> zcount zk1 10 30 |
ZRANGEBYSCORE
ZRANGEBYSCORE命令可以按照score范围范围元素,加上withscores可以连score一起返回。
1 | 127.0.0.1:6379> zrangebyscore zk1 10 30 |
ZRANK
ZRANK命令可以返回有序集key中成员member的排名。其中有序集成员按score值递增(从小到大)顺序排列。排名以0为底,即score值最小的成员排名为0。
1 | 127.0.0.1:6379> zrank zk1 v2 |
ZREM
ZREM命令可以从集合中弹出一个元素。
1 | 127.0.0.1:6379> zrem zk1 v1 v2 |
Key相关命令
DEL命令
通过DEL命令我们可以删除一个已经存在的key。
1 | 127.0.0.1:6379> keys * |
DUMP命令
DUMP命令可以序列化给定的key,并返回序列化之后的值。
1 | 127.0.0.1:6379> dump k4 |
EXISTS
EXISTS命令用来检测一个给定的key是否存在。
1 | 127.0.0.1:6379> keys * |
TTL命令
TTL命令可以查看一个给定key的有效时间。
1 | 127.0.0.1:6379> ttl k4 |
EXPIRE命令
EXPIRE命令可以给key设置有效期,在有效期过后,key会被销毁。
1 | 127.0.0.1:6379> expire k4 120 |
PERSIST命令
PERSIST命令表示移除一个key的过期时间,这样该key就永远不会过期。
1 | 127.0.0.1:6379> persist k4 |
KEYS 命令
KEYS命令可以获取满足给定模式的所有key。
1 | KEYS *(*表示所有的key,*也可以是一个正在表达式) |
发布订阅
**SUBSCRIBE **
订阅频道
1 | 127.0.0.1:6379> subscribe c1 c2 c3 |
**PUBLISH **
发布消息
1 | 127.0.0.1:6379> PUBLISH c1 "hello redis!" |
**PSUBSCRIBE **
1 | 127.0.0.1:6379> PSUBSCRIBE c* |
事务
不同于关系型数据库,redis中的事务出错时没有回滚,对此,官方的解释如下:
Redis 命令只会因为错误的语法而失败(并且这些问题不能在入队时发现),或是命令用在了错误类型的键上面:这也就是说,从实用性的角度来说,失败的命令是由编程错误造成的,而这些错误应该在开发的过程中被发现,而不应该出现在生产环境中。因为不需要对回滚进行支持,所以 Redis 的内部可以保持简单且快速。
MULTI
开启事物
EXEC
结束事物并执行
WATCH
事务中的WATCH命令可以用来监控一个key,通过这种监控,我们可以为redis事务提供(CAS)行为。 如果有至少一个被WATCH监视的键在EXEC执行之前被修改了,那么整个事务都会被取消,EXEC返回nil-reply来表示事务已经失败。
事物中的异常行为
redis中事务的异常情况总的来说分为两类:
1.进入队列之前就能发现的错误,比如命令输错;(拒绝执行并自动放弃这个事务)
2.执行EXEC之后才能发现的错误,比如给一个非数字字符加1;(执行产生错误,其他命令继续执行)
持久化
整体上来说,redis持久化有两种方式,快照持久化和AOF,在项目中我们可以根据实际情况选择合适的持久化方式,也可以不用持久化,这关键看我们的redis在项目中扮演了什么样的角色。
快照持久化
redis可以在某个时间点上对内存中的数据创建一个副本文件,副本文件中的数据在redis重启时会被自动加载,我们也可以将副本文件拷贝到其他地方一样可以使用。
如何配置快照持久化(redis.conf)
1 | save 900 1 # 900秒内至少一个key变更 |
手动创建快照
SAVE
save命令是一个阻塞命令,在这个命令执行完成之前,不在处理其他请求,其他请求将被挂起。
BGSAVE
bgsave命令会fork一个子进程,用这个子进程将快照写入硬盘,而父进程则继续处理客户端发来的请求。
自动创建快照时机
- 当条件满足时,如900秒内有一个key被操作,redis会触发bgsave命令进行备份;
- 当我们执行shutdown命令时,redis会执行save命令进行备份操作,备份完成后关闭服务器;
- 在主从模式中,当从机第一次连接上主机后会发一条sync命令来开始一次复制操作,此时主机会开始一次bgsave操作,并在bgsave操作结束后向从机发送快照数据实现数据同步;
AOF持久化
与快照持久化不同,AOF持久化是将被执行的命令写到aof文件末尾,在恢复时只需要从头到尾执行一遍写命令即可恢复数据,AOF在redis中默认也是没有开启的,需要我们手动开启,开启方式为将redis.conf中的修改appendonly属性值为yes。
aof配置(redis.conf)
1 | appendonly yes # 开启aof持久化 |
最佳实践
- 如果redis只做缓存服务器,那么可以不使用任何持久化方式;
- 同时开启两种持久化方式,redis重启时优先载入aof文件来恢复原始的数据。rdb更适合用于备份数据库,快速重启,不会有aof可能潜在的bug,但是aof数据会更加完整;
- 因为rdb文件只用作后备用途,建议只在slave上持久化rdb文件,而且只要15分钟备份一次就够了,只保留save 900 1这条规则;
- 如果开启aof,一是会带来持续的io,二是rewrite过程中产生的新数据写到新文件造成的阻塞几乎不可避免。所以只要硬盘允许,尽量减少rewrite的频率,重写的基础可以设置5G以上。
- 如果不开启aof,紧靠master-slave replication也可以实现高可用性。能省掉一大笔io,也减少了rewrite带来的系统波动。代价是master/slave同时倒掉,会丢失十几分钟的数据。
主从复制
主从复制可以在一定程度上扩展redis性能,redis的主从复制和关系型数据库的主从复制类似,从机能够精确的复制主机上的内容。实现了主从复制之后,一方面能够实现数据的读写分离,降低master的压力,另一方面也能实现数据的备份。
配置方式
启动三个实例
1
2
3[root@localhost redis-4.0.8]# redis-server redis6379.conf
[root@localhost redis-4.0.8]# redis-server redis6380.conf
[root@localhost redis-4.0.8]# redis-server redis6381.conf连接服务
1
redis-cli -h IP -p 端口 --raw //登陆redis服务器时,增加参数 --raw(避免命令行中文乱码)
从机上执行slaveof
1
slaveof 127.0.0.1 6379
查看每个实例当前状态
1
INFO replication
主从复制注意点
- 如果主机运行一段时间了,从机连接上来,会备份主机所有的数据;
- 主从复制后,master可读可写,slave可读不可写;
- 主从结构运行中,主机不行挂掉,重启之后,他依然是主机;
主从复制原理
1 | 1.slave启动成功连接到master后会发送一个sync命令。 |
哨兵模式
sentinel.conf
1 | sentinel monitor mymaster 127.0.0.1 6379 1 |
启动哨兵
1 | redis-sentinel sentinel.conf |
注意点
当master挂掉之后,哨兵会重新选举一个slave当master,之前的master重启之后,也只能当slave了。
由于所有的写都是在master上操作的,master和slave会有一定的延迟,当系统繁忙,slave机器较多时问题会更严重,所以我们可以通过集群来进一步提示redis性能。