redis总结

来源:互联网 发布:老人去世六年无人知 编辑:程序博客网 时间:2024/05/22 04:42

redis的缓存处理


转载:http://blog.csdn.net/ghostlv/article/details/51281073

当将redis作为缓存服务器时, 需要处理过期缓存问题. 
LRU是redis唯一支持的缓存处理方式. 
对于缓存方面的设置包括两个参数, 一个是最大缓存数量, 另一个是缓存策略.

最大缓存数量

参数名为, “maxmemory”, 在配置文件”/etc/redis.conf”中设置. 
当这个参数设置为0时, 表示内存无限制. 
但是对于32位操作系统, 最大内存使用为3GB, 当超过这个数额, 将采取缓存替换策略.

缓存回收策略

当redis的使用达到上限时, redis将采取回收策略. 
redis的回收策略通过”maxmemory-policy”参数的设置. 
这个参数可以设置的值为:

  • noeviction:返回错误当内存限制达到并且客户端尝试执行会让更多内存被使用的命令(大部分的写入指令,但DEL和几个例外)
  • allkeys-lru: 尝试回收最少使用的键(LRU),使得新添加的数据有空间存放。
  • volatile-lru: 尝试回收最少使用的键(LRU),但仅限于在过期集合的键,使得新添加的数据有空间存放。
  • allkeys-random: 回收随机的键使得新添加的数据有空间存放。
  • volatile-random: 回收随机的键使得新添加的数据有空间存放,但仅限于在过期集合的键。
  • volatile-ttl: 回收在过期集合的键,并且优先回收存活时间(TTL)较短的键,使得新添加的数据有空间存放。

当没有键满足回收的条件时, 策略volatile-lru, volatile-random以及volatile-ttl就和noeviction 差不多了。 
redis的缓存命中率, 可以通过”RedisINFO”获得.

一般的经验规则:

  • 使用allkeys-lru策略:当你希望你的请求符合一个幂定律分布,也就是说,你希望部分的子集元素将比其它其它元素被访问的更多。如果你不确定选择什么,这是个很好的选择。.
  • 使用allkeys-random:如果你是循环访问,所有的键被连续的扫描,或者你希望请求分布正常(所有元素被访问的概率都差不多)。
  • 使用volatile-ttl:如果你想要通过创建缓存对象时设置TTL值,来决定哪些对象应该被过期。

allkeys-lru 和 volatile-random策略对于当你想要单一的实例实现缓存及持久化一些键时很有用。不过一般运行两个实例是解决这个问题的更好方法。 
为了键设置过期时间也是需要消耗内存的,所以使用allkeys-lru这种策略更加高效,因为没有必要为键取设置过期时间当内存有压力时。

近似LRU算法

redis的LRU算法并不是完整的LRU算法, 只是一种近似的LRU算法. 
这种算法对少量的keys进行采样, 然后选择合适键进行淘汰. 
redis中有一个参数”maxmemory-samples”可以设置取样的数量. 
配合”RedisINFO”可以调试多次, 用于寻找最优的参数设置.

事务

使用MULTI命令开始事务, 使用EXEC命令执行这个事务. 
当执行事务时出现错误, 对于2.6以前的版本, redis只执行如对成功的命令. 
对于2.6之后的版本, redis会记录执行失败的任务, 当执行EXEC时, 如果队列中出现错误, redis直接放弃这个事务. 
redis不支持回滚技术.

DISCARD命令用于清空事务队列中的命令. 
WATCH命令可以为redis提供欢乐锁(check-and-set), 在事务中对某个变量设置了欢乐锁, 
这个参数被多个进程修改时, 事务将执行失败. 
通常用这种方式处理竞争问题. 
使用UNWATCH可以取消所有参数的监视.

redis持久化

Redis 提供了不同级别的持久化方式:

  • RDB持久化方式能够在指定的时间间隔能对你的数据进行快照存储.
  • AOF持久化方式记录每次对服务器写的操作,当服务器重启的时候会重新执行这些命令来恢复原始的数据,AOF命令以redis协议追加保存每次写的操作到文件末尾.Redis还能对AOF文件进行后台重写,使得AOF文件的体积不至于过大.
  • 如果你只希望你的数据在服务器运行的时候存在,你也可以不使用任何持久化方式.
  • 你也可以同时开启两种持久化方式, 在这种情况下, 当redis重启的时候会优先载入AOF文件来恢复原始的数据,因为在通常情况下AOF文件保存的数据集要比RDB文件保存的数据集要完整.
  • 最重要的事情是了解RDB和AOF持久化方式的不同,让我们以RDB持久化方式开始:

RDB的优点

  • RDB是一个非常紧凑的文件,它保存了某个时间点得数据集,非常适用于数据集的备份,比如你可以在每个小时报保存一下过去24小时内的数据,同时每天保存过去30天的数据,这样即使出了问题你也可以根据需求恢复到不同版本的数据集.
  • RDB是一个紧凑的单一文件,很方便传送到另一个远端数据中心或者亚马逊的S3(可能加密),非常适用于灾难恢复.
  • RDB在保存RDB文件时父进程唯一需要做的就是fork出一个子进程,接下来的工作全部由子进程来做,父进程不需要再做其他IO操作,所以RDB持久化方式可以最大化redis的性能.
  • 与AOF相比,在恢复大的数据集的时候,RDB方式会更快一些.

RDB的缺点

  • 如果你希望在redis意外停止工作(例如电源中断)的情况下丢失的数据最少的话,那么RDB不适合你.虽然你可以配置不同的save时间点(例如每隔5分钟并且对数据集有100个写的操作),是Redis要完整的保存整个数据集是一个比较繁重的工作,你通常会每隔5分钟或者更久做一次完整的保存,万一在Redis意外宕机,你可能会丢失几分钟的数据.
  • RDB 需要经常fork子进程来保存数据集到硬盘上,当数据集比较大的时候,fork的过程是非常耗时的,可能会导致Redis在一些毫秒级内不能响应客户端的请求.如果数据集巨大并且CPU性能不是很好的情况下,这种情况会持续1秒,AOF也需要fork,但是你可以调节重写日志文件的频率来提高数据集的耐久度.

AOF 优点

  • 使用AOF 会让你的Redis更加耐久: 你可以使用不同的fsync策略:无fsync,每秒fsync,每次写的时候fsync.使用默认的每秒fsync策略,Redis的性能依然很好(fsync是由后台线程进行处理的,主线程会尽力处理客户端请求),一旦出现故障,你最多丢失1秒的数据.
  • AOF文件是一个只进行追加的日志文件,所以不需要写入seek,即使由于某些原因(磁盘空间已满,写的过程中宕机等等)未执行完整的写入命令,你也也可使用redis-check-aof工具修复这些问题.
  • Redis 可以在 AOF 文件体积变得过大时,自动地在后台对 AOF 进行重写: 重写后的新 AOF 文件包含了恢复当前数据集所需的最小命令集合。 整个重写操作是绝对安全的,因为 Redis 在创建新 AOF 文件的过程中,会继续将命令追加到现有的 AOF 文件里面,即使重写过程中发生停机,现有的 AOF 文件也不会丢失。 而一旦新 AOF 文件创建完毕,Redis 就会从旧 AOF 文件切换到新 AOF 文件,并开始对新 AOF 文件进行追加操作。
  • AOF 文件有序地保存了对数据库执行的所有写入操作, 这些写入操作以 Redis 协议的格式保存, 因此 AOF 文件的内容非常容易被人读懂, 对文件进行分析(parse)也很轻松。 导出(export) AOF 文件也非常简单: 举个例子, 如果你不小心执行了 FLUSHALL 命令, 但只要 AOF 文件未被重写, 那么只要停止服务器, 移除 AOF 文件末尾的 FLUSHALL 命令, 并重启 Redis , 就可以将数据集恢复到 FLUSHALL 执行之前的状态。

AOF 缺点

  • 对于相同的数据集来说,AOF 文件的体积通常要大于 RDB 文件的体积。
  • 根据所使用的 fsync 策略,AOF 的速度可能会慢于 RDB 。 在一般情况下, 每秒 fsync 的性能依然非常高, 而关闭 fsync 可以让 AOF 的速度和 RDB 一样快, 即使在高负荷之下也是如此。 不过在处理巨大的写入载入时,RDB 可以提供更有保证的最大延迟时间(latency)。

快照

除了上面两种持久化方式不同, redis还提供了快照功能. 
用户可以设置快照时间或者限定修改次数进行自动快照, 或者使用SAVE和BGSAVE进行快照.

分块

redis有两种不同的分块方式, 
一种是3.0之前提供的, 使用Sentinel实现, 这种方式只是一种实验性. 
另一种是3.0之后版本提供的, 分片技术.

sentinel

sentinel工具用于监视redis节点, 然后判断主从情况.

cluster

redis支持分片功能, 但是不支持同时处理多个keys问题. 
redis集群并没有使用一致性hash, 而是引入哈希槽概念. 
Redis 集群有16384个哈希槽,每个key通过CRC16校验后对16384取模来决定放置哪个槽.集群的每个节点负责一部分hash槽.

集群中也包含了主从复制模型, 从节点对主节点进行复制, 主节点之间进行分片.

配置集群

最简单的配置文件:

port 7000cluster-enabled yescluster-config-file nodes.confcluster-node-timeout 5000appendonly yes

集群的启动至少需要三个主节点, 如果要加入主从复制的功能, 就需要引入至少六个节点, 三个为主节点, 三个为从节点.

为每个节点设置一个配置文件, 用于启动redis. 
启动时, 因为nodes.conf不存在, 每个节点会重新分配一个新的ID.

接着使用集群创建脚本创建集群:

redis-trib.rb create --replicas 1 node-list

–replicas参数为备份节点的个数. 
redis-trib.rb后面的参数可以分为start, create, stop, reshard, add-node, del-node. 
分别用于启动, 创建, 停用集群, 重新分块, 添加节点, 删除节点.

redis常用数据结构

redis常用的数据结构包括:

  • String
  • Hash
  • List
  • Set
  • Sorted set

String

常用命令

set,get,decr,incr,mget 等。

实现方式

String在redis内部存储默认就是一个字符串,被redisObject所引用,当遇到incr,decr等操作时会转成数值型进行计算,此时redisObject的encoding字段为int。

Hash

常用命令

hget,hset,hgetall 等。

使用

第一种方式将用户ID作为查找key,把其他信息封装成一个对象以序列化的方式存储,这种方式的缺点是,增加了序列化/反序列化的开销,并且在需要修改其中一项信息时,需要把整个对象取回,并且修改操作需要对并发进行保护,引入CAS等复杂问题。

第二种方法是这个用户信息对象有多少成员就存成多少个key-value对儿,用用户ID+对应属性的名称作为唯一标识来取得对应属性的值,虽然省去了序列化开销和并发问题,但是用户ID为重复存储,如果存在大量这样的数据,内存浪费还是非常可观的。

实现方式

上面已经说到Redis Hash对应Value内部实际就是一个HashMap,实际这里会有2种不同实现,这个Hash的成员比较少时Redis为了节省内存会采用类似一维数组的方式来紧凑存储,而不会采用真正的HashMap结构,对应的value redisObject的encoding为zipmap,当成员数量增大时会自动转成真正的HashMap,此时encoding为ht。

可以使用下面的参数进行设置

  • hash-max-zipmap-entries 实例数最大额度
  • hash-max-zipmap-value 每个成员值长度额度

List

常用命令

lpush,rpush,lpop,rpop,lrange等。

应用场景

Redis list的应用场景非常多,也是Redis最重要的数据结构之一,比如twitter的关注列表,粉丝列表等都可以用Redis的list结构来实现,比较好理解,这里不再重复。

实现方式

Redis list的实现为一个双向链表,即可以支持反向查找和遍历,更方便操作,不过带来了部分额外的内存开销,Redis内部的很多实现,包括发送缓冲队列等也都是用的这个数据结构。

通过设置下面参数, 用于切换紧凑和实际列表:

  • list-max-ziplist-entries 实例数量额度
  • list-max-ziplist-value 每个实例长度的额度

Set

常用命令

sadd,spop,smembers,sunion 等。

应用场景

Redis set对外提供的功能与list类似是一个列表的功能,特殊之处在于set是可以自动排重的,当你需要存储一个列表数据,又不希望出现重复数据时,set是一个很好的选择,并且set提供了判断某个成员是否在一个set集合内的重要接口,这个也是list所不能提供的。

实现方式

set 的内部实现是一个 value永远为null的HashMap,实际就是通过计算hash的方式来快速排重的,这也是set能提供判断一个成员是否在集合内的原因。

通过设置下面参数, 进行切换紧凑和实际集合:

  • set-max-intset-entries 实例最大额度
  • set-max-intset-value 每个实例大小额度

Sorted set

常用命令

zadd,zrange,zrem,zcard等

使用场景

Redis sorted set的使用场景与set类似,区别是set不是自动有序的,而sorted set可以通过用户额外提供一个优先级(score)的参数来为成员排序,并且是插入有序的,即自动排序。当你需要一个有序的并且不重复的集合列表,那么可以选择sorted set数据结构,比如twitter 的public timeline可以以发表时间作为score来存储,这样获取时就是自动按时间排好序的。

实现方式

Redis sorted set的内部使用HashMap和跳跃表(SkipList)来保证数据的存储和有序,HashMap里放的是成员到score的映射,而跳跃表里存放的是所有的成员,排序依据是HashMap里存的score,使用跳跃表的结构可以获得比较高的查找效率,并且在实现上比较简单。

转载:http://blog.csdn.net/ghostlv/article/details/51281073

0 0
原创粉丝点击