手机用户请
横屏
获取最佳阅读体验,REFERENCES
中是本文参考的链接,如需要链接和更多资源,可以关注公众号后回复『知识星球』加入并获取长期知识分享服务。
一个网站演变的过程中,用户量的增加引起了并发量提高,如果不做处理,则频繁的查询数据库,结果是页面显示的慢,服务器、数据库不堪重负。如果网站页面所展示的数据的更新不是特别频繁,想提高页面显示的速度,减轻服务器的负担,此时应该考虑使用缓存。
所以,缓存是介于应用程序和物理数据源之间,其作用是为了降低应用程序对物理数据源访问的频次,从而提高了应用的运行性能。缓存内的数据是对物理数据源中的数据的复制,应用程序在运行时从缓存读写数据,在特定的时刻或事件会同步缓存和物理数据源的数据。
使用缓存有一个原则:越高层次的缓存效果越好。推荐使用页面缓存。
redis是一个key-value存储系统。和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)和zset(有序集合)、Hash(哈希类型的映射表)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。
在此基础上,redis支持各种不同方式的排序。与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。
Redis 是一个高性能的key-value数据库。redis的出现,很大程度补偿了memcached这类key/value存储的不足,在部 分场合可以对关系数据库起到很好的补充作用。它提供了Java,Python,Ruby,Perl,PHP客户端,使用很方便。
速度快
持久化
高可用
为什么这么快?
如何使用?
Redis存储机制分成两种 Snapshot和 AOF。无论是哪种机制,Redis都是将数据存储在内存中。
是将数据先存储在内存,然后当数据累计达到某些设定的伐值的时候,就会触发一次DUMP操作,将变化的数据一次性写入数据文件(RDB文件)。
是将数据也是先存在内存,但是在存储的时候会使用调用 fsync 来完成对本次写操作的日志记录,这个日志揭露文件其实是一个基于 Redis 网络交互协议的文本文件。AOF 调用 fsync 也不是说全部都是无阻塞的,在某些系统上可能出现 fsync 阻塞进程的情况,对于这种情况可以通过配置修改,但默认情况不要修改。
性能
Snapshot 方式的性能是要明显高于 AOF 方式的,原因有两点:
而 AOF 则一般都是工作在实时存储或者准实时模式下。相对来说存储的频率高,效率却偏低。
数据安全
AOF 数据安全性高于 Snapshot 存储,原因:
Snapshot 存储是基于累计批量的思想,也就是说在允许的情况下,累计的数据越多那么写入效率也就越高,但数据的累计是靠时间的积累完成的,那么如果在长时间数据不写入 RDB,但 Redis 又遇到了崩溃,那么没有写入的数据就无法恢复了,但是 AOF 方式偏偏相反,根据 AOF 配置的存储频率的策略可以做到最少的数据丢失和较高的数据恢复能力。说完了性能和安全,这里不得不提的就是在 Redis 中的 Rewrite 的功能,AOF 的存储是按照记录日志的方式去工作的,那么成千上万的数据插入必然导致日志文件的扩大,Redis这个时候会根据配置合理触发Rewrite操作,所谓 Rewrite 就是将日志文件中的所有数据都重新写到另外一个新的日志文件中,但是不同的是,对于老日志文件中对于Key的多次操作,只保留最终的值的那次操作记录到日志文件中,从而缩小日志文件的大小。这里有两个配置需要注意:
auto-aof-rewrite-percentage 100
(当前写入日志文件的大小占到初始日志文件大小的某个百分比时触发Rewrite)auto-aof-rewrite-min-size 64mb
(本次Rewrite最小的写入数据)两个条件需要同时满足。
数据结构
存储
存储
缓存、计数器、分布式锁、分布式ID
计数
Redis hash 是一个 string 类型的 field(字段) 和 value(值) 的映射表,hash 特别适合用于存储对象。 Redis 中每个 hash 可以存储 232 - 1 键值对(40多亿)。
用户信息存储
K-V 存储
命令及描述 |
---|
HDEL key field1 field2 删除一个或多个哈希表字段 |
HEXISTS key field 查看哈希表 key 中,指定的字段是否存在。 |
HGET key field 获取存储在哈希表中指定字段的值。 |
HGETALL key 获取在哈希表中指定 key 的所有字段和值 |
HINCRBY key field increment 为哈希表 key 中的指定字段的整数值加上增量 increment 。 |
HINCRBYFLOAT key field increment 为哈希表 key 中的指定字段的浮点数值加上增量 increment 。 |
HKEYS key 获取所有哈希表中的字段 |
HLEN key 获取哈希表中字段的数量 |
HMGET key field1 field2 获取所有给定字段的值 |
HMSET key field1 value1 field2 value2 同时将多个 field-value (域-值)对设置到哈希表 key 中。 |
HSET key field value 将哈希表 key 中的字段 field 的值设为 value 。 |
HSETNX key field value 只有在字段 field 不存在时,设置哈希表字段的值。 |
HVALS key 获取哈希表中所有值。 |
[HSCAN key cursor MATCH pattern] [COUNT count] 迭代哈希表中的键值对。 |
List 类型是用来存储多个有序的字符串的,列表当中的每一个字符看做一个元素,一个列表当中可以存储有一个或者多个元素,redis 的 List 支持存储
2^32 -1
个元素。
redis 列表是一种比较灵活的链表数据结构,它可以充当队列或者栈的角色。
命令及描述 |
---|
BLPOP key1 key2 timeout 移出并获取列表的第一个元素, 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。 |
BRPOP key1 key2 timeout 移出并获取列表的最后一个元素, 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。 |
BRPOPLPUSH source destination timeout 从列表中弹出一个值,将弹出的元素插入到另外一个列表中并返回它;如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。 |
LINDEX key index 通过索引获取列表中的元素 |
LINSERT key BEFORE|AFTER pivot value 在列表的元素前或者后插入元素 |
LLEN key 获取列表长度 |
LPOP key 移出并获取列表的第一个元素 |
LPUSH key value1 value2 将一个或多个值插入到列表头部 |
LPUSHX key value 将一个值插入到已存在的列表头部 |
LRANGE key start stop 获取列表指定范围内的元素 |
LREM key count value 移除列表元素 |
LSET key index value 通过索引设置列表元素的值 |
LTRIM key start stop 对一个列表进行修剪(trim),就是说,让列表只保留指定区间内的元素,不在指定区间之内的元素都将被删除。 |
RPOP key 移除列表的最后一个元素,返回值为移除的元素。 |
RPOPLPUSH source destination 移除列表的最后一个元素,并将该元素添加到另一个列表并返回 |
RPUSH key value1 value2 在列表中添加一个或多个值 |
RPUSHX key value 为已存在的列表添加值 |
集合类型的数据结构,那么集合类型就比较适合用于聚合分类。 redis 集合(Set)类型和 List 列表类型类似,都可以用来存储多个字符串元素的集合。但是和 List 不同的是 Set 集合当中不允许重复的元素。而且 Set 集合当中元素是
没有顺序的,不存在元素下标
。 redis 的 Set 类型是使用哈希表构造的,因此复杂度是O(1),它支持集合内的增删改查,并且支持多个集合间的交集、并集、差集操作。可以利用这些集合操作,解决程序开发过程当中很多数据集合间的问题。
命令及描述 |
---|
SADD key member1 member2 向集合添加一个或多个成员 |
SCARD key 获取集合的成员数 |
SDIFF key1 key2 返回第一个集合与其他集合之间的差异。 |
SDIFFSTORE destination key1 key2 返回给定所有集合的差集并存储在 destination 中 |
SINTER key1 key2 返回给定所有集合的交集 |
SINTERSTORE destination key1 key2 返回给定所有集合的交集并存储在 destination 中 |
SISMEMBER key member 判断 member 元素是否是集合 key 的成员 |
SMEMBERS key 返回集合中的所有成员 |
SMOVE source destination member 将 member 元素从 source 集合移动到 destination 集合 |
SPOP key 移除并返回集合中的一个随机元素 |
SRANDMEMBER key count 返回集合中一个或多个随机数 |
SREM key member1 member2 移除集合中一个或多个成员 |
SUNION key1 key2 返回所有给定集合的并集 |
SUNIONSTORE destination key1 key2 所有给定集合的并集存储在 destination 集合中 |
[SSCAN key cursor MATCH pattern] [COUNT count] 迭代集合中的元素 |
redis 有序集合也是集合类型的一部分,所以它保留了集合中元素不能重复的特性,但是不同的是,有序集合给每个元素多设置了一个分数,利用该分数作为排序的依据。 有序集合可以利用分数进行从小到大的排序。虽然有序集合的成员是唯一的,但是分数(score)却可以重复。就比如在一个班中,学生的学号是唯一的,但是每科成绩却是可以一样的,redis 可以利用有序集合存储学生成绩快速做成绩排名功能。
有序集合的使用场景与集合类似,但是 set 集合不是自动有序的,而sorted set可以利用分数进行成员间的排序,而且是插入时就排序好。所以当你需要一个有序且不重复的集合列表时,就可以选择 sorted set 数据结构作为选择方案。
命令及描述 |
---|
ZADD key score1 member1 score2 member2 向有序集合添加一个或多个成员,或者更新已存在成员的分数 |
ZCARD key 获取有序集合的成员数 |
ZCOUNT key min max 计算在有序集合中指定区间分数的成员数 |
ZINCRBY key increment member 有序集合中对指定成员的分数加上增量 increment |
ZINTERSTORE destination numkeys key key ... 计算给定的一个或多个有序集的交集并将结果集存储在新的有序集合 destination 中 |
ZLEXCOUNT key min max 在有序集合中计算指定字典区间内成员数量 |
ZRANGE key start stop WITHSCORES 通过索引区间返回有序集合指定区间内的成员 |
ZRANGEBYLEX key min max LIMIT offset count 通过字典区间返回有序集合的成员 |
ZRANGEBYSCORE key min max WITHSCORES LIMIT 通过分数返回有序集合指定区间内的成员 |
ZRANK key member 返回有序集合中指定成员的索引 |
ZREM key member member ... 移除有序集合中的一个或多个成员 |
ZREMRANGEBYLEX key min max 移除有序集合中给定的字典区间的所有成员 |
ZREMRANGEBYRANK key start stop 移除有序集合中给定的排名区间的所有成员 |
ZREMRANGEBYSCORE key min max 移除有序集合中给定的分数区间的所有成员 |
ZREVRANGE key start stop WITHSCORES 返回有序集中指定区间内的成员,通过索引,分数从高到低 |
ZREVRANGEBYSCORE key max min WITHSCORES 返回有序集中指定分数区间内的成员,分数从高到低排序 |
ZREVRANK key member 返回有序集合中指定成员的排名,有序集成员按分数值递减(从大到小)排序 |
ZSCORE key member 返回有序集中,成员的分数值 |
ZUNIONSTORE destination numkeys key key ... 计算给定的一个或多个有序集的并集,并存储在新的 key 中 |
ZSCAN key cursor MATCH pattern COUNT count 迭代有序集合中的元素(包括元素成员和元素分值) |
文本介绍了 Redis 的两种存储模式,AOF 和 Snapshot。简要分析他们的区别和应用场景后,介绍了常用的数据结构和对应支撑的场景。