【存储中间件】Redis核心技术与实战(一):Redis入门与应用(常用数据布局 ...

打印 上一主题 下一主题

主题 1045|帖子 1045|积分 3135


个人主页:道友老李
欢迎加入社区:道友老李的学习社区
Redis入门与应用

Redis常用数据布局

Redis提供了一些数据布局供我们往Redis中存取数据,最常用的的有5种,字符串(String)、哈希(Hash)、列表(list)、聚集(set)、有序聚集(ZSET)。
字符串(String)

字符串类型是Redis最基础的数据布局。首先键都是字符串类型,而且其他几种数据布局都是在字符串类型基础上构建的,所以字符串类型能为其他四种数据布局的学习奠基基础。字符串类型的值实际可以是字符串(简单的字符串、复杂的字符串(比方JSON、XML))、数字(整数、浮点数),甚至是二进制(图片、音频、视频),但是值最大不能超过512MB。
(虽然Redis是C写的,C内里有字符串<本质利用char数组来实现>,但是处于种种思量,Redis还是本身实现了字符串类型)
操作下令

set 设置值

set key value

set下令有几个选项:
ex seconds: 为键设置秒级逾期时间。
px milliseconds: 为键设置毫秒级逾期时间。
nx: 键必须不存在,才可以设置成功,用于添加(分布式锁常用)。
xx: 与nx相反,键必须存在,才可以设置成功,用于更新。

从实行结果上看,ex参数和expire下令根本一样。另有一个必要特别注意的地方是如果一个字符串已经设置了逾期时间,然后你调用了set 方法修改了它,它的逾期时间会消失。
而nx和xx实行结果如下

除了set选项,Redis 还提供了setex和 setnx两个下令:
setex key
seconds value
setnx key value
setex和 setnx的作用和ex和nx选项是一样的。也就是,setex为键设置秒级逾期时间,setnx设置时键必须不存在,才可以设置成功。
setex示例:

setnx示例:

由于键foo-ex已存在,所以setnx失败,返回结果为0,键foo-ex2不存在,所以setnx成功,返回结果为1。
有什么应用场景吗?以setnx下令为例子,由于Redis的单线程下令处理机制,如果有多个客户端同时实行setnx key value,根据setnx的特性只有一个客户端能设置成功,setnx可以作为分布式锁的一种实现方案。当然分布式锁没有不是只有一个下令就OK了,其中另有许多的东西要注意,我们反面会用单独的章节来讲述基于Redis的分布式锁。
get 获取值

如果要获取的键不存在,则返回nil(空):

mset 批量设置值

通过mset下令一次性设置4个键值对

mget 批量获取值


批量获取了键a、b、c、d的值:
如果有些键不存在,那么它的值为nil(空),结果是按照传入键的次序返回。
批量操作下令可以有效提高效率,假如没有mget这样的下令,要实行n次get下令具体耗时如下:
n次 get时间=n次网络时间+n次下令时间
利用mget下令后,要实行n次get下令操作具体耗时如下:
n次get时间=1次网络时间+n次下令时间
Redis可以支撑每秒数万的读写操作,但是这指的是Redis服务端的处理能力,对于客户端来说,一次下令除了下令时间还是有网络时间,假设网络时间为1毫秒,下令时间为0.1毫秒(按照每秒处理1万条下令算),那么实行1000次 get下令必要1.1秒(10001+10000.1=1100ms),1次mget下令的必要0.101秒(11+10000.1=101ms)。
Incr 数字运算

incr下令用于对值做自增操作,返回结果分为三种情况:
值不是整数,返回错误。
值是整数,返回自增后的结果。
键不存在,按照值为0自增,返回结果为1。

除了incr下令,Redis提供了decr(自减)、 incrby(自增指定数字)、decrby(自减指定数字)、incrbyfloat(自增浮点数),具体结果请同学们自行尝试。
append追加指令

append可以向字符串尾部追加值

strlen 字符串长度

返回字符串长度

注意:每个中文占3个字节
getset 设置并返回原值

getset和set一样会设置值,但是不同的是,它同时会返回键原来的值

setrange 设置指定位置的字符


下标从0开始计算。
getrange 截取字符串

getrange 截取字符串中的一部门,形成一个子串,必要指明开始和结束的偏移量,截取的范围是个闭区间。

下令的时间复杂度

字符串这些下令中,除了del 、mset、 mget支持多个键的批量操作,时间复杂度和键的个数相干,为O(n),getrange和字符串长度相干,也是O(n),其余的下令根本上都是O(1)的时间复杂度,在速度上还好坏常快的。
利用场景

字符串类型的利用场景很广泛:
缓存功能
Redis 作为缓存层,MySQL作为存储层,绝大部门请求的数据都是从Redis中获取。由于Redis具有支撑高并发的特性,所以缓存通常能起到加速读写和降低后端压力的作用。
计数
利用Redis 作为计数的基础工具,它可以实现快速计数、查询缓存的功能,同时数据可以异步落地到其他数据源。
共享Session
一个分布式Web服务将用户的Session信息(比方用户登录信息)保存在各自服务器中,这样会造成一个问题,出于负载均衡的思量,分布式服务会将用户的访问均衡到不同服务器上,用户革新一次访问可能会发现必要重新登录,这个问题是用户无法容忍的。
为相识决这个问题,可以利用Redis将用户的Session举行集中管理,,在这种模式下只要包管Redis是高可用和扩展性的,每次用户更新或者查询登录信息都直接从Redis中集中获取。
限速
比如,许多应用出于安全的思量,会在每次举行登录时,让用户输入手机验证码,从而确定是否是用户本人。但是为了短信接口不被频繁访问,会限制用户每分钟获取验证码的频率,比方一分钟不能超过5次。一些网站限制一个IP地址不能在一秒钟之内方问超过n次也可以采取类似的思路。
哈希(Hash)

Java里提供了HashMap,Redis中也有类似的数据布局,就是哈希类型。但是要注意,哈希类型中的映射关系叫作field-value,注意这里的value是指field对应的值,不是键对应的值。
操作下令

根本上,哈希的操作下令和字符串的操作下令很类似,许多下令在字符串类型的下令前面加上了h字母,代表是操作哈希类型,同时还要指明要操作的field的值。
hset设值

hset user:1 name lijin

如果设置成功会返回1,反之会返回0。此外Redis提供了hsetnx下令,它们的关系就像set和setnx下令一样,只不外作用域由键变为field。
hget取值

hget user:1 name
如果键或field不存在,会返回nil。

hdel删除field

hdel会删除一个或多个field,返回结果为成功删除field的个数。

hlen计算field个数


hmset批量设值


hmget批量取值


hexists判断field是否存在


若存在返回1,不存在返回0
hkeys获取所有field

它返回指定哈希键所有的field

hvals获取所有value


hgetall获取所有field与value


在利用hgetall时,如果哈希元素个数比较多,会存在阻塞Redis的可能。如果只必要获取部门field,可以利用hmget,如果一定要获取全部field-value,可以利用hscan下令,该下令会渐进式遍历哈希类型,hscan将在反面的章节先容。
hincrby增加

hincrby和 hincrbyfloat,就像incrby和incrbyfloat下令一样,但是它们的作用域是filed。
hstrlen 计算value的字符串长度


下令的时间复杂度

哈希类型的操作下令中,hdel,hmget,hmset的时间复杂度和下令所带的field的个数相干O(k),hkeys,hgetall,hvals和存储的field的总数相干,O(N)。其余的下令时间复杂度都是O(1)。
利用场景

从前面的操作可以看出,String和Hash的操作非常类似,那为什么要弄一个hash出来存储。
哈希类型比较适宜存放对象类型的数据,我们可以比较下,如果数据库中表记载user为:
idnameage1lijin182msb20 1、利用String类型
必要一条条去插入获取。
set user:1:name lijin;
set user:1:age 18;
set user:2:name msb;
set user:2:age 20;
优点:简单直观,每个键对应一个值
缺点:键数过多,占用内存多,用户信息过于分散,不用于生产环境
2、将对象序列化存入redis
set user:1 serialize(userInfo);
优点:编程简单,若利用序列化合理内存利用率高
缺点:序列化与反序列化有一定开销,更新属性时必要把userInfo全取出来举行反序列化,更新后再序列化到redis
3、利用hash类型
hmset user:1 name lijin age 18
hmset user:2 name msb age 20
优点:简单直观,利用合理可减少内存空间消耗
缺点:要控制内部编码格式,不恰当的格式会消耗更多内存
列表(list)

列表( list)类型是用来存储多个有序的字符串,a、b、c、c、b四个元素从左到右组成了一个有序的列表,列表中的每个字符串称为元素(element),一个列表最多可以存储(2^32-1)个元素(4294967295)。

在Redis 中,可以对列表两端插入( push)和弹出(pop),还可以获取指定范围的元素列表、获取指定索引下标的元素等。列表是一种比较机动的数据布局,它可以充当栈和队列的脚色,在实际开发上有许多应用场景。
列表类型有两个特点:
第一、列表中的元素是有序的,这就意味着可以通过索引下标获取某个元素或者某个范围内的元素列表。
第二、列表中的元素可以是重复的。
操作下令

lrange 获取指定范围内的元素列表(不会删除元素)

key start end
索引下标特点:从左到右为0到N-1
lrange 0 -1下令可以从左到右获取列表的所有元素
rpush 向右插入



lpush 向左插入



linsert 在某个元素前或后插入新元素




这三个返回结果为下令完成后当前列表的长度,也就是列表中包含的元素个数,同时rpush和lpush都支持同时插入多个元素。
lpop 从列表左侧弹出(会删除元素)

r
请注意,弹出来元素就没了。
rpop 从列表右侧弹出

rpop将会把列表最右侧的元素d弹出。

lrem 对指定元素举行删除


lrem下令会从列表中找到等于value的元素举行删除,根据count的不同分为三种情况:
count>0,从左到右,删除最多count个元素。
count<0,从右到左,删除最多count绝对值个元素。
count=0,删除所有。




返回值是实际删除元素的个数。
ltirm 按照索引范围修剪列表

比方想保存列表中第0个到第1个元素
ls
lset修改指定索引下标的元素


lindex 获取列表指定索引下标的元素

l
llen 获取列表长度


blpop和brpop阻塞式弹出元素

blpop和brpop是lpop和rpop的阻塞版本,除此之外还支持多个列表类型,也支持设定阻塞时间,单位秒,如果阻塞时间为0,表示一直阻塞下去。我们以brpop为例分析。

A客户端阻塞了(由于没有元素就会阻塞)

A客户端一直处于阻塞状态。此时我们从另一个客户端B实行

A客户端则输出

注意:brpop反面如果是多个键,那么brpop会从左至右遍历键,一旦有一个键能弹出元素,客户端立刻返回。
利用场景

列表类型可以用于比如:
消息队列,Redis 的 lpush+brpop下令组合即可实现阻塞队列,生产者客户端利用lrpush从列表左侧插入元素,多个消费者客户端利用brpop下令阻塞式的“抢”列表尾部的元素,多个客户端包管了消费的负载均衡和高可用性。
文章列表
每个用户有属于本身的文章列表,现必要分页展示文章列表。此时可以思量利用列表,由于列表不光是有序的,同时支持按照索引范围获取元素。
实现其他数据布局
lpush+lpop =Stack(栈)
lpush +rpop =Queue(队列)
lpsh+ ltrim =Capped Collection(有限聚集)
lpush+brpop=Message Queue(消息队列)

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

勿忘初心做自己

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表