【前言:本文主要介绍redis,内容丰富且实用,旨在帮助大家对redis有一个更深入、全面的了解以及在实际工作中更好的应用redis,篇幅较长,建议大家收藏,仔细阅读】
Redis简介
redis是用C语言开发的一个基于内存的、高性能key-value键值对的、开源nosql数据库。目前,redis的key是字符串类型的,但value支持多种数据类型:字符串(string)、哈希(hash)、列表(list)、集合(set)、有序集合(sortedset),通过提供多种键值数据类型来适应不同场景下的存储需求。
Redis应用场景
介绍几种常见的应用:
1.构建队列系统
可以用list可以构建队列系统,使用sorted set甚至可以构建有优先级的队列系统
2.pub、sub发布订阅构建实时消息系统、消息队列
3.计数器应用
redis的命令如INCR,DECR都是原子性的,可以通过这些命令来构建计数器系统
4.分布式集群架构中session共享
Redis特性
1.基于内存存储,数据访问速度快,性能好
根据官方提供的测试数据:50个并发执行100000个请求,读的速度是110000次/s,写的速度是81000次/s【数据仅供参考,根据服务器配置会有不同结果】
2.数据持久化机制
目前支持APF和RDB两种持久化机制
3.支持集群模式,容量可以线性扩展
注意:Redis3.X开始才支持集群模式
4.支持丰富的数据结构
这一点是相比其他缓存工具如memcache比较鲜明的优势
Redis数据结构
首先强调一点,redis的key是字符串类型,但value支持多种数据类型。关于key的定义,有几点建议:
1.key不要太长,太长不仅消耗内存还会降低查找效率。建议不要超过1024个字节
2.key不要太短,要具有可读性
3.在实际项目中,key最好有一个统一的命名规范
下面详细介绍一下redis的value目前支持的数据类型:
string类型
字符串是redis支持的最基础的数据类型,它在redis中是二进制安全的,应用最多。
操作redis的string类型数据常用命令:
set(设置)、get(获取)、getset(获取并设置)、del(删除)
一次性插入或者获取多条数据:
MGET key1 key2
MSET key1 value1 key2 value2 …..
在插入一条string类型数据的同时为它指定一个存活期限:
setex username 10 张三对string类型数据进行增减操作的几个命令:
incr:将指定的key的value原子性的递增1。如果该key不存在,其初始值为0,在incr之后其值为1
decr:将指定的key的value原子性的递减1。如果该key不存在,其初始值为0,在decr之后其值为-1
incrby key increment:将指定的key的value原子性增加increment。如果该key不存在,其初始值为0,在incrby之后,该值为increment
decrby key decrement:将指定的key的value原子性减少decrement,如果该key不存在,其初始值为0,在decrby之后,该值为decrement。
append key value:拼凑字符串。如果该key存在,则在原有的value后追加该值;如果该key不存在,则重新创建一个key/value。
注意:
decr incr decrby incrby 都是原子性操作。进行增减前提是:key可以转换为整型否则报错。相信做过SparkStreaming流式计算统计pv、uv中,中间状态存储会熟悉该特性的应用。
list类型
笔者强调一点:redis中list底层是双端链表结构,这个在面试中经常会问。redis为什么这么快,其实不仅仅是因为基于内存存储,底层还多了很多的优化,这只是其中之一,下图是对双端链表的一个图形描述:
常用的操作命令:
lpush:从头部(左边)插入数据
rpush:从尾部(右边)插入数据
lrange key start end:读取list中指定范围的values。start、end从0开始计数;也可为负数,若为-1则表示链表尾部的元素,-2则表示倒数第二个,依次类推…
lpop:从头部弹出一个元素
rpop:从尾部弹出一个元素
rpoplpush:从一个list的尾部弹出一个元素插入到另一个list。原子性操作,没有key2会创建key2,一旦key1的list元素被取完,key1会被清除
llen key:返回指定的key关联的链表中的元素的数量
list数据类型应用案例:消息队列
比如有这样一个需求:实现一个任务调度系统==>生产者不断产生任务,放入task-queue排队,消费者不断拿出任务来处理,同时放入一个tmp-queue暂存,如果任务处理成功,则清除tmp-queue;否则,将任务弹回task-queue。笔者这里提供一个实现思路,就不贴代码了,其实就是上述API的简单应用:
1.生产者将生产的任务lpush进task-queue中
2.消费者通过rpoplpush将taks-queue中取任务并暂存任务到tmp-queue中
3.如果任务处理成功,tmp-queue通过rpop清除相应任务;任务处理失败,则rpoplpush将任务从tmp-queue中清除并存入task-queue中
4.为了避免消费者程序在处理任务失败之后没有及时将rpoplpush失败的任务时就已经挂掉,可以加入一个管理tmp-queque的角色,以便在这种情况时也能将处理失败的任务lpush进task-queue中。
hash类型
redis中的hash类型可以看成具有map容器,适合存储值对象的信息。如username、password等。
常用命令:
hset key field value:为指定的key设定field/value对(键值对)
hmset key field value [field2 value2 …]:设置key中的多个filed/value
hincrby key field increment:设置key中filed的值增加increment
hexists key field:判断指定的key中的filed是否存在
set类型
无序、无重复元素。和list类型相比,set类型在功能上还存在着一个非常重要的特性,即在服务器端完成多个set之间的聚合计算操作,如并集、交集、差集的计算。由于这些操作均在服务端完成,因此效率极高,而且也节省了大量的网络IO开销。
常用命令:
添加: sadd key values[value1、value2…] [多个value间空格分隔]
删除:srem key members[member1、member2…] 删除set中指定的成员(成员可以是多个)
查询:smembers key 查看指定key的set中的数据
判断:sismember key value [判断参数中指定的成员是否在该set中,1表示存在,0表示不存在或者该key本身就不存在。(无论集合中有多少元素都可以极速的返回结果)]
统计set元素个数:scard key [指定key对应的set的元素数]
srandmember key:随机返回set中的一个成员
sdiff、sunion、sinter:差集、并集、交集
sortedset类型
sortedset中的每一个元素都会有一个分数与之关联,redis正是通过分数来为集合中的元素进行排序,默认正序。注意:sortedset中的数据不能重复,但分数却可以重复。
常用命令:
zadd key score member score2 member2 … :将所有成员以及该成员的分数存放到sorted-set中。如果该元素已经存在则会用新的分数替换原有的分数。返回值是新加入到集合中的元素个数,不包含之前已经存在的元素。(score可以重复,member不可以重复)
zscore key member:返回指定成员的分数zcard key:获取集合中的成员数量
zrem key member[member…]:移除集合中指定的成员,可以指定多个成员
zrange key start end [withscores]:获取集合中脚标为start-end的成员,[withscores]参数表明返回的成员包含其分数。(withscores可选参数)
zrevrange key start stop [withscores]:按照元素分数从大到小的顺序返回索引从start到stop之间的所有元素(包含两端的元素)