Redis之基本介绍

基本介绍html

  Redis是一种key-value存储形式的非关系型数据库,也是一个强大的内存型存储系统,可是它比传统的Memcached 更灵活,支持更多的数据类型,同时也能够持久化。据官方数据表示Redis读的速度是110000次/s,写的速度是81000次/s 。并且Redis支持数据持久化,众多数据结构存储,master-slave模式数据备份等多种功能。java

支持的数据类型web

  先经过一张图了解下Redis内部内存管理中是如何描述这些不一样数据类型的:redis

  首先Redis内部使用一个redisObject对象来表示全部的key和value,redisObject最主要的信息如上图所示:type表明一个value对象具体是何种数据类型,encoding是不一样数据类型在redis内部的存储方式,好比:type=string表明value存储的是一个普通字符串,那么对应的encoding能够是raw或者是int,若是是int则表明实际redis内部是按数值型类存储和表示这个字符串的,固然前提是这个字符串自己能够用数值表示,好比:"123" "456"这样的字符串。sql

    这里须要特殊说明一下vm字段,只有打开了Redis的虚拟内存功能,此字段才会真正的分配内存,该功能默认是关闭状态的。经过上图咱们能够发现Redis使用redisObject来表示全部的key/value数据是比较浪费内存的,固然这些内存管理成本的付出主要也是为了给Redis不一样数据类型提供一个统一的管理接口,实际做者也提供了多种方法帮助咱们尽可能节省内存使用。数据库

Stringapi

  String数据结构是简单的key-value类型,value其实不只是String,也能够是数字。缓存

  经常使用命令:get、set、incr、decr、mget等。ruby

  应用场景String是最经常使用的一种数据类型,普通的key/ value 存储均可以归为此类,便可以彻底实现目前 Memcached 的功能,而且效率更高。还能够享受Redis的定时持久化,操做日志及 Replication等功能。除了提供与 Memcached 同样的get、set、incr、decr 等操做外,Redis还提供了下面一些操做:数据结构

  • 获取字符串长度
  • 往字符串append内容
  • 设置和获取字符串的某一段内容
  • 设置及获取字符串的某一位(bit)
  • 批量设置一系列字符串的内容

Hash

  在Memcached中,咱们常常将一些结构化的信息打包成hashmap,在客户端序列化后存储为一个字符串的值,好比用户的昵称、年龄、性别、积分等,这时候在须要修改其中某一项时,一般须要将全部值取出反序列化后,修改某一项的值,再序列化存储回去。这样不只增大了开销,也不适用于一些可能并发操做的场合(好比两个并发的操做都须要修改积分)。而Redis的Hash结构可使你像在数据库中Update一个属性同样只修改某一项属性值。

经常使用命令:hget,hset,hgetall 等。

应用场景:

咱们简单举个实例来描述下Hash的应用场景,好比咱们要存储一个用户信息对象数据,包含如下信息:

用户ID为查找的key,存储的value用户对象包含姓名,年龄,生日等信息,若是用普通的key/value结构来存储,主要有如下2种存储方式:

 

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

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

那么Redis提供的Hash很好的解决了这个问题,Redis的Hash实际是内部存储的Value为一个HashMap,并提供了直接存取这个Map成员的接口,以下图:

 

  也就是说,Key仍然是用户ID, value是一个Map,这个Map的key是成员的属性名,value是属性值,这样对数据的修改和存取均可以直接经过其内部Map的Key(Redis里称内部Map的key为field), 也就是经过 key(用户ID) + field(属性标签) 就能够操做对应属性数据了,既不须要重复存储数据,也不会带来序列化和并发修改控制的问题。很好的解决了问题。

    这里同时须要注意,Redis提供了接口(hgetall)能够直接取到所有的属性数据,可是若是内部Map的成员不少,那么涉及到遍历整个内部Map的操做,因为Redis单线程模型的缘故,这个遍历操做可能会比较耗时,而另其它客户端的请求彻底不响应,这点须要格外注意。

List 

经常使用方法:

  Lists 就是链表,略有数据结构知识的人都应该能理解其结构。使用Lists结构,咱们能够轻松地实现最新消息排行等功能。Lists的另外一个应用就是消息队列,能够利用Lists的PUSH操做,将任务存在Lists中,而后工做线程再用POP操做将任务取出进行执行。Redis还提供了操做Lists中某一段的api,你能够直接查询,删除Lists中某一段的元素。

  Redis的list是每一个子元素都是String类型的双向链表,能够经过push和pop操做从列表的头部或者尾部添加或者删除元素,这样List便可以做为栈,也能够做为队列。

 

Sets

Sets 就是一个集合,集合的概念就是一堆不重复值的组合。利用Redis提供的Sets数据结构,能够存储一些集合性的数据。

Set是集合,是String类型的无序集合,set是经过hashtable实现的,概念和数学中个的集合基本相似,能够交集,并集,差集等等,set中的元素是没有顺序的。

经常使用方法:

Sorted Sets

 和Sets相比,Sorted Sets增长了一个权重参数score,使得集合中的元素可以按score进行有序排列,好比一个存储全班同窗成绩的Sorted Sets,其集合value能够是同窗的学号,而score就能够是其考试得分,这样在数据插入集合的时候,就已经进行了自然的排序。能够用Sorted Sets来作带权重的队列,好比普通消息的score为1,重要消息的score为2,而后工做线程能够选择按score的倒序来获取工做任务。让重要的任务优先执行。 

 经常使用方法:

java中jedis操做不一样数据类型的经常使用命令

 

pub/sub

发布订阅,相似于消息队列mq。能够选择对某个Key进行订阅,一旦这个key发布了一些消息,则全部订阅了这个Key的对象就能够收到这个消息。主要能够用在实时消息系统上,例如聊天之类的。

Transactions

NoSQL不支持事务,可是经过提供了打包执行的功能,即这个包里面的全部命令必需要一块儿执行,此外还能够锁定某个Key,在打包执行命令时若是检测到这个Key发生了变化,则直接回滚。

持久化方案

redis默认开启的RDB持久化方式,可是若是开始了AOF方式,那么在系统重启时优先冲AOF文件中回复数据

Redis只RDB持久化和AOF持久化

数据淘汰策略

  长期将Redis做为缓存使用,不免会遇到内存空间存储瓶颈,当Redis内存超出物理内存限制时,内存数据就会与磁盘产生频繁交换,使Redis性能急剧降低。此时如何淘汰无用数据释放空间,存储新数据就变得尤其重要了。对此,Redis在生产环境中,采用配置参数maxmemory 的方式来限制内存大小。当实际存储内存超出maxmemory 参数值时会执行配置的淘汰策略。Redis 肯定驱逐某个键值对后,会删除这个数据,并将这个数据变动消息发布到本地(AOF 持久化)和从机(主从链接)。可是咱们要注意redis的删除策略和淘汰策略是有区别的。

  • volatile-lru:从设置过时时间的数据集(server.db[i].expires)中挑选出最近最少使用的数据淘汰。没有设置过时时间的key不会被淘汰,这样就能够在增长内存空间的同时保证须要持久化的数据不会丢失。
  • volatile-ttl:除了淘汰机制采用LRU,策略基本上与volatile-lru类似,从设置过时时间的数据集(server.db[i].expires)中挑选将要过时的数据淘汰,ttl值越大越优先被淘汰。
  • volatile-random:从已设置过时时间的数据集(server.db[i].expires)中任意选择数据淘汰。当内存达到限制没法写入非过时时间的数据集时,能够经过该淘汰策略在主键空间中随机移除某个key。
  • allkeys-lru:从数据集(server.db[i].dict)中挑选最近最少使用的数据淘汰,该策略要淘汰的key面向的是全体key集合,而非过时的key集合。
  • allkeys-random:从数据集(server.db[i].dict)中选择任意数据淘汰。
  • no-enviction:禁止驱逐数据,也就是当内存不足以容纳新入数据时,新写入操做就会报错,请求能够继续进行,线上任务也不能持续进行,采用no-enviction策略能够保证数据不被丢失,这也是系统默认的一种淘汰策略。
  • allkeys-lfu 从数据集(server.db[i].dict)中挑选使用频率最小的数据淘汰,该策略要淘汰的key面向的是全体key集合,而非过时的key集合。
  • volatile-lfu 从设置过时时间的数据集(server.db[i].expires)中挑选出使用频率最小的数据淘汰。没有设置过时时间的key不会被淘汰,这样就能够在增长内存空间的同时保证须要持久化的数据不会丢失

 

Redis内存淘汰策略,看这一篇就够了!

Redis数据过时和淘汰策略详解

Redis中LRU淘汰策略的深刻分析

Redis的缓存淘汰策略LRU与LFU

 

优缺点

 优势:

  • 速度快,由于数据存在内存中,相似于HashMap,HashMap的优点就是查找和操做的时间复杂度都是O(1)
  • 支持丰富数据类型,支持string,list,set,sorted set,hash
  • 支持事务,操做都是原子性,所谓的原子性就是对数据的更改要么所有执行,要么所有不执行
  • 丰富的特性:可用于缓存,消息,按key设置过时时间,过时后将会自动删除

 缺点:

redis和memcached的区别

  • memcached全部的值均是简单的字符串,redis做为其替代者,支持更为丰富的数据类型
  • redis的速度比memcached快不少,由于redis经过hasfMap存对象,因此再存取时不须要序列化和反序列化。
  • Memecache把数据所有存在内存之中,断电后会挂掉,数据不能超过内存大小。redis能够持久化其数据
  • value的大小:redis最大能够达到1GB,而memcache只有1MB
  • 使用底层模型不一样:它们之间底层实现方式 以及与客户端之间通讯的应用协议不同;
  • Redis 是单线程,多路复用方式提升处理效率。Memcached 是多线程的,经过CPU线程切换来提升处理效率。

使用注意点

  • Master写内存快照,save命令调度rdbSave函数,会阻塞主线程的工做,当快照比较大时对性能影响是很是大的,会间断性暂停服务,因此Master最好不要写内存快照。Master AOF持久化,若是不重写AOF文件,这个持久化方式对性能的影响是最小的,可是AOF文件会不断增大,AOF文件过大会影响Master重启的恢复速度。Master最好不要作任何持久化工做,包括内存快照和AOF日志文件,特别是不要启用内存快照作持久化,若是数据比较关键,某个Slave开启AOF备份数据,策略为每秒同步一次。
  • 若是数据比较重要,某个Slave开启AOF备份数据,策略设置为每秒同步一次
  • 为了主从复制的速度和链接的稳定性,Master和Slave最好在同一个局域网内
  • 尽可能避免在压力很大的主库上增长从库
  • 主从复制不要用图状结构,用单向链表结构更为稳定,即:Master <- Slave1 <- Slave2 <- Slave3…
  • 这样的结构方便解决单点故障问题,实现Slave对Master的替换。若是Master挂了,能够马上启用Slave1作Master,其余不变。

使用场景

String 

适用场景:适合最简单的k-v存储,相似于memcached的存储结构,短信验证码,配置信息等,就用这种类型来存储。

案例:1.微博数,粉丝数,

hash

适用场景:通常key为ID或者惟一标示,value对应的就是详情了。如商品详情,我的信息详情,新闻详情等。

案例:1.存储部分变动数据,如用户信息等

List

适用场景:由于list是有序的,比较适合存储一些有序且数据相对固定的数据。如省市区表、字典表等。由于list是有序的,适合根据写入的时间来排序,如:最新的***,消息队列等

案例:

  1.在Redis中咱们的最新微博ID使用了常驻缓存,这是一直更新的。可是咱们作了限制不能超过5000个ID,所以咱们的获取ID函数会一直询问Redis。只有在start/count参数超出了这个范围的时候,才须要去访问数据库。咱们的系统不会像传统方式那样“刷新”缓存,Redis实例中的信息永远是一致的。SQL数据库(或是硬盘上的其余类型数据库)只是在用户须要获取“很远”的数据时才会被触发,而主页或第一个评论页是不会麻烦到硬盘上的数据库了。

取最新N个数据的操做:
记录前N个最新登录的用户Id列表,超出的范围能够从数据库中得到。
//把当前登陆人添加到链表里
ret = r.lpush("login:last_login_times", uid)

//保持链表只有N位
ret = redis.ltrim("login:last_login_times", 0, N-1)

//得到前N个最新登录的用户Id列表
last_login_list = r.lrange("login:last_login_times", 0, N-1)

Sets

适用场景:能够简单的理解为ID-List的模式,如微博中一我的有哪些好友,set最牛的地方在于,能够对两个set提供交集、并集、差集操做。例如:查找两我的共同的好友等。

案例:

  1.在微博应用中,能够将一个用户全部的关注人存在一个集合中,将其全部粉丝存在一个集合。Redis还为集合提供了求交集、并集、差集等操做,能够很是方便的实现如共同关注、共同喜爱、二度好友等功能,对上面的全部集合操做,你还可使用不一样的命令选择将结果返回给客户端仍是存集到一个新的集合中。

使用:

交集,并集,差集:(Set)
//book表存储book名称

set book:1:name    ”The Ruby Programming Language”

set book:2:name     ”Ruby on rail”

set book:3:name     ”Programming Erlang”

//tag表使用集合来存储数据,由于集合擅长求交集、并集

sadd tag:ruby 1

sadd tag:ruby 2

sadd tag:web 2

sadd tag:erlang 3

//即属于ruby又属于web的书?

 inter_list = redis.sinter("tag.web", "tag:ruby")

//即属于ruby,但不属于web的书?

 inter_list = redis.sdiff("tag.ruby", "tag:web")

//属于ruby和属于web的书的合集?

 inter_list = redis.sunion("tag.ruby", "tag:web")

获取某段时间全部数据去重值,这个使用Redis的set数据结构最合适了,只须要不断地将数据往set中扔就好了,set意为集合,因此会自动排重。

 Sorts sets

适用场景:是set的加强版本,增长了一个score参数,自动会根据score的值进行排序。比较适合相似于top 10等不根据插入的时间来排序的数据。

案例:排行榜应用,取TOP N操做

使用:

//将登陆次数和用户统一存储在一个sorted set里

zadd login:login_times 5 1

zadd login:login_times 1 2

zadd login:login_times 2 3

ZADD key score member

//当用户登陆时,对该用户的登陆次数自增1

ret = r.zincrby("login:login_times", 1, uid)

//那么如何得到登陆次数最多的用户呢,逆序排列取得排名前N的用户

ret = r.zrevrange("login:login_times", 0, N-1)

ZREVRANGE key start stop [WITHSCORES]

Redis集群

Redis三种主从模式的基本介绍

  • 主从复制
  • 哨兵模式
  • Redis-Cluster集群

 

学习连接

redis经点应用场景

redis经典场景

redis经典适用场景

redis的安装

redis的命令大全

redis持久化配置过程

redis在Java中的经常使用命令

Redis的Cluster集群的搭建

相关文章
相关标签/搜索