数据结构论坛

首页 » 分类 » 分类 » Redis数据类型及使用场景
TUhjnbcbe - 2021/8/17 9:19:00
治疗白癜风的医院 http://www.zykyhs.com/
摘要:Redis相比其它的KV数据库,其一大特点是支持丰富的数据类型.它一共支持5种数据类型,下面逐一介绍这5种数据类型及其使用场景...string简介:Strings数据类型是最常用、简单的key-value类型,普通的key/value存储都可以归为此类。value不仅可以是字符串,也可以是数字。因为是二进制安全的,所以你完全可以把一个图片文件的内容作为string来存储。Redis的string可以完全实现目前memcached的功能,并且效率更高。除了提供与Memcached一样的get、set、incr、decr等操作外,Redis还额外提供了下面一些操作:

获取字符串长度

往字符串append内容

设置和获取字符串的某一段内容

设置及获取字符串的某一位(bit)

批量设置一系列字符串的内容

常用命令:set,get,decr,incr,mget等。应用场景:应用Memcached和CKV的所有场景。字符串和数字直接存取。结构化数据需要先序列化,再set到value;相应的,get到value后需要反序列化。可以利用redis的INCR、INCRBY、DECR、DECRBY等指令来实现原子计数的效果。即可以用来实现业务上的统计计数需求。也可用于实现idmaker,即生成全局唯一的id。存放sessionkey,实现一个分布式session系统。Redis的key可以方便地设置过期时间,用于实现sessionkey的自动过期。验证skey时先根据uid路由到对应的redis,如取不到skey,则表示skey已过期,需要重新登录;如取到skey且校验通过则升级此skey的过期时间即可。Setnx或SetNx,仅当key不存在时才Set。可以用来选举Master或实现分布式锁:所有Client不断尝试使用SetNxmastermyName抢注Master,成功的那位不断使用Expire刷新它的过期时间。如果Master挂掉了key就会失效,剩下的节点又会发生新一轮抢夺。借助redis的lua脚本,可以实现更安全的2种分布式锁:一种适用于各进程竞争但总是单个进程获取锁并处理的场景。除非原处理进程挂掉因而锁过期才会被其它进程获取到锁。无须主动解锁。①通过get、expire/pexpire、setnxex

px的lua脚本实现;一种适用于各进程竞争获取锁并处理的场景。②通过setnxex

px获取锁,用完需要通过先get判断再del释放锁,否则在锁过期之前不能获取到锁。

GetSet,设置新值,返回旧值。比如实现一个计数器,可以用GetSet获取计数并重置为0。

GetBit/SetBit/BitOp/BitCount,BitMap的玩法,比如统计今天的独立访问用户数时,每个注册用户都有一个offset,他今天进来的话就把他那个位设为1,用BitCount就可以得出今天的总人数。

Append/SetRange/GetRange/StrLen,对文本进行扩展、替换、截取和求长度,对特定数据格式非常有用。

实现方式:String在redis内部存储默认就是一个字符串,被redisObject所引用,当遇到incr,decr等操作时会转成数值型进行计算,此时redisObject的encoding字段为int。Hash简介:Hash存的是字符串和字符串值之间的映射。Hash将对象的各个属性存入Map里,可以只读取/更新对象的某些属性。这样有些属性超长就让它一边呆着不动,另外不同的模块可以只更新自己关心的属性而不会互相并发导致覆盖冲突。常用命令:hget,hset,hgetall等。应用场景:

存放结构化数据,比如用户信息。在Memcached或CKV中,对于用户信息比如用户的昵称、年龄、性别、积分等,我们需要先序列化后存储为一个字符串的值,这时候在需要修改其中某一项时,通常需要将所有值取出反序列化后,修改某一项的值,再序列化存储回去。这样不仅增大了开销,也不适用于一些可能并发操作的场合(比如两个并发的操作都需要修改积分)。而Redis的Hash结构可以使你像在数据库中Update一个属性一样只修改某一项属性值。

Key是用户ID,value是一个Map,这个Map的key是成员的属性名,value是属性值,这样对数据的修改和存取都可以直接通过其内部Map的Key(Redis里称内部Map的key为field),也就是通过key(用户ID)+field(属性标签)就可以操作对应属性数据了,既不需要重复存储数据,也不会带来序列化和并发修改控制的问题。不过这里需要注意,Redis提供了接口(hgetall)可以直接取到全部的属性数据,但是如果内部Map的成员很多,那么涉及到遍历整个内部Map的操作,由于Redis单线程模型的缘故,这个遍历操作可能会比较耗时,而对其它客户端的请求完全不响应,这点需要格外注意。

可用来建索引。比如User对象,除了id有时还要按name来查询,可以建一个Key为user:name:id的Hash,在插入User对象时(setuser:{"id":,"name":"calvin"}),顺便往这个hash插入一条(hsetuser:name:idcalvin),这时calvin作为hash里的一个key,值为。按name查询的时候,用hgetuser:name:idcalvin就能从名为calvin的key里取出id。假如需要使用多种索引来查找某条数据时可以使用,一个hashkey搞定,避免使用多个stringkey存放索引值。

HINCRBY同样可用于实现idmaker。相对string类型的idmaker每一个类型需要一个key,hash类型的用一个key即可。

实现方式:RedisHash对应Value内部实际就是一个HashMap,这里会有2种不同实现。这个Hash的成员比较少时Redis为了节省内存会采用类似一维数组的方式来紧凑存储,而不会采用真正的HashMap结构。对应的valueredisObject的encoding为zipmap,当成员数量增大时会自动转成真正的HashMap,此时encoding为ht。List简介:List是一个双向链表,支持双向的Pop/Push,江湖规矩一般从左端Push,右端Pop——LPush/RPop,而且还有Blocking的版本BLPop/BRPop,客户端可以阻塞在那直到有消息到来。还有RPopLPush/BRPopLPush,弹出来返回给client的同时,把自己又推入另一个list,LLen获取列表的长度。还有按值进行的操作:LRem(按值删除元素)、LInsert(插在某个值的元素的前后),复杂度是O(N),N是List长度,因为List的值不唯一,所以要遍历全部元素,而Set只要O(log(N))。按下标进行的操作:下标从0开始,队列从左到右算,下标为负数时则从右到左。LSet,按下标设置元素值。LIndex,按下标返回元素。LRange,不同于POP直接弹走元素,只是返回列表内一段下标的元素,是分页的最爱。LTrim,限制List的大小,比如只保留最新的20条消息。复杂度也是O(N),其中LSet的N是List长度,LIndex的N是下标的值,LRange的N是start的值+列出元素的个数,因为是链表而不是数组,所以按下标访问其实要遍历链表,除非下标正好是队头和队尾。LTrim的N是移除元素的个数。常用命令:lpush,rpush,lpop,rpop,lrange等。应用场景:

各种列表,比如twitter的

1
查看完整版本: Redis数据类型及使用场景