redis
数据类型
key
Redis中key按"object-type: id:field"格式设计的原因
它是基于key-value的,比如要按照id查询或者名字查询怎么办呢,答案是自己建立索引。最基础的方式就是你上面说的“object-type: id:field ”。查01号学生 : person:01
命令
命令 | 描述 |
---|---|
key * | 查看有多少 |
exists key | 判断某个key是否存在 |
move key 2 | 把当前库的key移到2库 |
expire key 秒钟 | 为给定的key设置过期时间 |
ttl key | 查看还有多少秒过期,-1表示永不过期,-2表示已过期 |
type key | 查看你的key是什么类型 |
String
命令集
命令 | 描述 |
---|---|
SET key value | 设置指定 key 的值 |
GET key | 获取指定 key 的值 |
INCR key | 将 key 中储存的数字值加一 |
DECR key | 将 key 中储存的数字值减一 |
DEL key | 删除指定 key 的值 |
MSET key value [key value …] | 同时设置一个或多个 key-value 对 |
MGET key1 [key2…] | 获取所有(一个或多个)给定 key 的值 |
SETEX key seconds value | 将值 value 关联到 key ,并将 key 的过期时间设为 seconds (以秒为单位) |
select num | 切换库 (num为库的下标,默认0) |
FLUSHAL | 删除所有的库 |
FLUSHDB | 删除当前库 |
应用场景
**·**存储值
用户的session,token,系统状态值等等;
**·**常规计数
文章浏览数,关注数,收藏数等等的加减操作;
List
命令集
命令 | 描述 |
---|---|
LPUSH key value | 向指定的左边(头部)添加一个新元素 |
RPUSH key value | 向指定的右边(尾部)添加一个新元素 |
LRANGE key start stop | 获取列表指定范围内的元素 |
RPOP key | 移除列表的最后一个元素,返回值为移除的元素 |
LPOP key | 移出并获取列表的第一个元素 |
BLPOP key1 [key2 ] timeout | 移出并获取列表的第一个元素, 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止 |
BRPOP key1 [key2 ] timeout | 移出并获取列表的最后一个元素, 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止 |
应用场景
数据列表
在博客系统中,你可为每篇博客设置一个List,往List中插入评论内容。用LRANGE可对结果分页。由于内存容量的限制,一般的做法是缓存第一页或者前几页评论内容,当点击查看更多时去查询数据库,这样既能节省内存,有能给用户更好的体验。
消息队列
在队列的众多实现中,链表实现就是其中一种,所以,基于链表实现的Redis List能够作为队列使用就不足为奇了。而且还是一个双端队列,并且支持阻塞。
生产者—消费者模型
redis提供了阻塞式访问 BRPOP 和 BLPOP 命令,来实现生产者和消费者模型。
Hash
(哈希,类似java里的Map) Map<String,Object>
命令集
命令 | 描述 |
---|---|
HSET key field value | 将哈希表 key 中的字段 field 的值设为 value |
HGET key field | 获取存储在哈希表中指定字段的值 |
HMSET key field1 value1 [field2 value2 ] | 同时将多个 field-value (域-值)对设置到哈希表 key 中 |
HMGET key field1 [field2] | 获取所有给定字段的值 |
应用场景
**·**存储对象
例如可以用来存储用户信息,商品信息等。
Set
命令集
命令 | 描述 |
---|---|
SADD key member1 [member2] | 向集合添加一个或多个成员 |
SISMEMBER key member | 判断 member 元素是否是集合 key 的成员 |
SREM key member1 [member2] | 移除集合中一个或多个成员 |
SUNION key1 [key2] | 返回所有给定集合的并集 |
SDIFF key1 [key2] | 返回给定所有集合的差集 |
SINTER key1 [key2] | 返回给定所有集合的交集 |
应用场景
**·**表示对象间的关系
例如某宝店铺的关注用户,宝贝的收藏用户等等。
下面表示用户1,2, 5, 77四个用户关注了店铺1000:
sadd shop:1000:user 1 2 5 77
(integer) 4
有时候我们可能还需要他们的逆关系:用户关注的所有店铺:
sadd user:1:shop 1000
(integer) 1
sadd user:2:shop 1000
(integer) 1
sadd user:5:shop 1000
(integer) 1
sadd user:77:shop 1000
(integer) 1
当然,我们可能还需要用户1,2, 5, 77关注了的所有店铺:
sinter user:1:shop user:2:shop user:5:shop user:77:shop
… results here …
Zset(sorted set:有序集合)
redis zset 和set 一样也是string 类型元素的集合,且不允许重复的成员。 不同的是每个元素都会关联一个double类型的分数。 redis正是通过分数来为集合中的成员进行从小到大的排序。zset的成员是唯一的,但分数(score)却可以重复。
命令集
命令 | 描述 |
---|---|
ZADD key score1 member1 [score2 member2] | 向有序集合添加一个或多个成员,或者更新已存在成员的分数 |
ZRANGE key start stop [WITHSCORES] | 通过索引区间返回有序集合指定区间内的成员 |
ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT] | 通过分数返回有序集合指定区间内的成员 |
ZREM key member [member …] | 移除有序集合中的一个或多个成员 |
ZRANK key member | 返回有序集合中指定成员的索引 |
应用场景
·排行榜
Sorted Set十分适合做排行榜,特别是小规模的数据,比如top5,top10等等
redis的持久化
两种持久化方式
- rdb 在指定的时间间隔内将内存中的数据集快照写入磁盘也就是行讲的snapshot快照,它恢复是是将快照文件直接读到内存里。
是什么:redis会单独创建fork一个进程来进行持久化,会先将数据写入到 一个临时文件中,待持久化过程都结束了,再用这个临时文件替换上次持久化好的文件。整个过程中,主进程是不进行任何IO操作的,这就确保了极高的性能如果需要进行大规模数据的恢复,且对于数据恢复的完整性不是非常敏感,那RDB方式要比AOF方式更加的高效。RDB的缺点是最后一次持久化后的数据可能丢失。- aof appendfsync的always:同步持久化,每次发生数据变更会被立即记录到磁盘性能较差但数据完整性比较好。
everysec:出厂默认推荐,异步操作,每秒记录,如果一秒跌机,有数据丢失
修复:redis-check-aof --fix进行修复
rewrite:
是什么: AOF采用文件追加方式,文件会越来越大为避免出现此种情况,新增了重写机制,但AOF文件的大小超过了所设定的阀值时,redis就会启动AOF文件的内容压缩,只保留可以恢复数据的最小指令集,可以使用命令bgrewriteaof
原理:AOF文件持续增长而过大时,会fork出一条新进程来将文件重写(也是先写临时文件最后再rename),遍历新进程的内存中数据,每条记录有一条的set语句。重写aof文件的操作,并没有呢读取旧的aof文件,而是将整个内存中的数据库内容用命令的方式重写了一个新的aof文件,这点和快照有点类似
- aof appendfsync的always:同步持久化,每次发生数据变更会被立即记录到磁盘性能较差但数据完整性比较好。
redis的事务
是什么:可以一次执行多个命令,本质是一组命令的集合。一个事务中所有命令都会序列化,按顺序的串行化执行而不会被其它命令插入,不许加塞一个队列中,一次性、顺序性、排他性的执行一些列
watch监控:
悲观锁:每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿数据就会block直到它拿到锁, 传统的关系型数据库里边就用到了很多这种锁机制,比喻行锁,表锁等,读锁,写锁,都是在做操作之前先上锁。
乐观锁:每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有会更新这个数据,可以使用版本号机制。乐观锁适用于多度的应用类型,这样可以提高吞吐量,
乐观锁策略:提交版本必须大于记录当前版本才能执行更新。
3阶段:开启:以MULTI开始一个事务
入队:将多个命令入队到事务中,接到这些命令并不会立即执行,而是放到等待执行的事务队列里面
执行:由EXEC命令触发事务
主从复制
主机数据更新后根据配置和策略,自动同步到备机的master/slave机制,master以写为主,slave以读为主
使用:1.配从(库)不配主(库)
2.从库配置:slaveof主库Ip主库端口,每次与master断开之后,都需要重新连接,除非你配置redis.conf文件 info replication
3.修改配置文件 拷贝多个redis.conf文件
sentinel(哨兵模式) :调整结构,6379带着80/81
自定义/myredis目录下新建sentinel.conf文件,名字不能错
配置哨兵,填写内容:sentinel monitor被监控数据库名字(自己起名字)127.0.0.1 6379 1
最后一个数字1,表示主机挂掉后salve投票看让谁接替成为主机,得票数多成为主机
启动哨兵:redis-sentinel/myredis/sentinel.conf
复制
Redis默认使用异步复制,其特点是低延迟和高性能。异步复制就意味着在故障转移期间,有丢失数据的风险。
在 Redis 复制的基础上,使用和配置主从复制非常简单,能使得从 Redis 服务器(Slave)能精确得复制主 Redis 服务器(Master)的内容。每次当 Slave 和 Master 之间的连接断开时, Slave 会自动重连到 Master 上,并且无论这期间 Master 发生了什么, Slave 都将尝试让自身成为 Master 的精确副本。
复制的运行依靠三个主要的机制:
1.当一个 Master 实例和一个 Slave 实例连接正常时, Master 将自身数据集的改变以命令流的方式保持对 Slave 的更新,包括客户端的写入、key 的过期或被逐出等等。
2.当 Master 和 Slave 之间的连接断开之后,因为网络问题、或者是主从连接超时, Slave 重新连接上 Master 并会尝试进行部分重同步:这意味着它会尝试只获取在断开连接期间内丢失的命令流。
3.当无法进行部分重同步时, Slave 会请求进行全量重同步。这会涉及到一个更复杂的过程,Master 需要创建所有数据的快照,将之发送给 Slave ,之后在数据集更改时持续发送命令流到 Slave 。
当 Master 关闭持久化时,复制的安全性
在使用 Redis 复制功能的设置中,强烈建议在 Master 和 Slave 中启用持久化。当不可能启用时,例如由于磁盘性能而导致的延迟问题,应该通过设置避免maste故障后自动重启。
Master 关闭持久化,然后连接一个 Slave ,其配置为RDB或者 AOF。但是,这个设置必须小心处理,因为重新启动的 Master 程序将从一个空数据集开始:如果一个 Slave 试图与它同步,那么这个 Slave 也会被清空。
在配置后,主机Master可负责读写服务,从机slave只负责读。Redis 提高这种配置方式,为的是让其支持数据的弱一致性,即最终一致性。
Redis主从复制可以根据是否是全量分为全量同步和增量同步。
全量同步:
Redis全量复制一般发生在Slave初始化阶段,这时Slave需要将Master上的所有数据都复制一份。
增量同步:
Redis增量复制是指Slave初始化后开始正常工作时主服务器发生的写操作同步到从服务器的过程。
增量复制的过程主要是主服务器每执行一个写命令就会向从服务器发送相同的写命令,从服务器接收并执行收到的写命令。