首页 > 数据库 >redis的使用

redis的使用

时间:2024-09-14 11:25:00浏览次数:1  
标签:Redis 元素 redis value 列表 key 使用 集合

一、数据类型
1、字符串类型String
1)赋值:SET key value。如set hello world
2)取值:GET key。如get hello。返回是world
3)自增:INCR key。就是Mysql的AUTO_INCREMENT。每次执行INCR key时,该key的值都会+1.若key不存在,则先建立一个0,然后+1,返回1。
    如果值不是整数则报错。该操作是原子操作。
4)自减:DECR key。将指定key的值减少1.如DECR num,就是num-1
5)自增N:INCRBY key increment用来给指定key的值加increment。如INCRBY num 5就是num+5
6)自减N:DECRBY key increment用来给指定key的值减increment。如DECRBY num 5就是num-5
7)增加浮点数:INCRBYFLOAT key increment。
8)向尾部追加:APPEND key value。如set test:key 123 append test:key 456 get test:key就是123456
9)获取长度:STRLEN key。
10)同时给多个key 赋值:MSET title 这是标题 description 这是描述 content 这是内容。
11)同时获取多个key的值:MGET title description content
12)位操作之获取:GETBIT key offset。如字符a在redis中的存储为01100001(ASCII为98),那么GETBIT key 2就是1,GET key 0就是0。
13)位操作之设置:SETBIT key offset value。如字符a在redis中的存储为01100001(ASCII为98),那么SETBIT key 6 0,SETBIT key 5 1
    那么get key得到的是b。因为取出的二进制为01100010。
14)位操作之统计:BITCOUNT key [start] [end]:BITCOUNT key用来获取key的值中二进制是1的个数。而BITCOUNT key start end则是用来
    统计key的值中在第start和end之间的子字符串的二进制是1的个数(好绕啊)。
15)位操作之位运算:BITOP operation resultKey key1 key2。operation是位运算的操作,有AND,OR,XOR,NOT。resultKey是把运算结构
    存储在这个key中,key1和key2是参与运算的key,参与运算的key可以指定多个。

2、应用场景
缓存功能:字符串最经典的使用场景,redis最为缓存层,Mysql作为储存层,绝大部分请求数据都是redis中获取,由于redis具有支撑高并发特性,所以缓存通常能起到加速读写和降低 后端压力的作用。
计数器:许多运用都会使用redis作为计数的基础工具,他可以实现快速计数、查询缓存的功能,同时数据可以一步落地到其他的数据源。如:视频播放数、粉丝数、微博数就是使用redis作为计数的基础组件。
共享session:出于负载均衡的考虑,分布式服务会将用户信息的访问均衡到不同服务器上,用户刷新一次访问可能会需要重新登录,为避免这个问题可以用redis将用户session集中管理,在这种模式下只要保证redis的高可用和扩展性的,每次获取用户更新或查询登录信息都直接从redis中集中获取。
限速:处于安全考虑,每次进行登录时让用户输入手机验证码,为了短信接口不被频繁访问,会限制用户每分钟获取验证码的频率。

二、列表类型List
  1、类型定义
  Redis对链表(Linked-list)结构的支持使得其在键值存储的世界独树一帜,一个列表结构可以有序地存储多个字符串。

  使用list时,value就是一个string数组,操作这组string时,可以像对待栈一样使用pop和push操作,但是这个栈两端都能进行操作;也可以像对待数组一样使用一个index参数来操作。list的操作命令略杂,主要分为两类:L开头的和R开头的,L代表LEFT或者LIST,进行一些从列表左端进行的操作,或者一些与端无关的操作;R代表RIGHT,进行一些从列表右端进行的操作。

复制代码
1)向头部插入:LPUSH key value1 value2...。返回增加后的列表长度。
2)向尾部插入:RPUSH key value1 value2...。返回增加后的列表长度。
3)从头部弹出:LPOP key。返回被弹出的元素值。该操作先删除key列表的第一个元素,再将它返回。
4)从尾部弹出:RPOP key。返回被弹出的元素值。
5)列表元素个数:LLEN key。key不存在返回0。
6)获取列表的子列表:LRANGE start end。返回第start个到第end个元素的列表。包含start和end。支持负数索引。-1表示最后一个元素,-2表示倒数
    第二个元素。
7)删除列表中指定值:LREM key count value。删除key这个列表中,所有值为value的元素,只删除count。如果有count+1个,那么就保留最后一个。
    count不存在或者为0,则删除所有的。如果count大于0,则删除从头到尾的count个,如果count小于0,则删除从尾到头的count个。
8)获取指定索引值:LINDEX key index。如LINDEX key 0就是列表的第一个元素。index可以是负数。
9)设置索引和值:LSET key index value。这个操作只是修改指定key且指定index的值。如果index不存在,则报错。
10)保留片段,删除其它:LTRIM key start end。保留start到end之间的所有元素,含start和end。其他全部删除。
11)向列表插入元素:LINSERT key BEFORE/AFTER value1 value2。从列表头开始遍历,发现值为value1时停止,将value2插入,根据BEFORE
    或者AFTER插入到value1的前面还是后面。
12)把一个列表的一个元素转到另一个列表:RPOPLPUSH list1 list2。将列表list1的右边元素删除,并把该与元素插入到列表list2的左边。原子操作。
复制代码
  2、应用场景
  消息队列: redis的lpush+brpop命令组合即可实现阻塞队列,生产者客户端是用lupsh从列表左侧插入元素,多个消费者客户端使用brpop命令阻塞时的“抢”列表尾部的元素,多个客户端保证了消费的负载均衡和高可用性。

文章列表:每个用户都有属于自己的文章列表,现在需要分页展示文章列表,此时可以考虑使用列表,列表不但有序同时支持按照索引范围获取元素。
使用列表技巧:

lpush+lpop=Stack(栈)
lpush+rpop=Queue(队列)
lpush+ltrim=Capped Collection(有限集合)
lpush+brpop=Message Queue(消息队列)
3、实现原理
列表类型内部使用双向链表实现。
  其内部数据结构为:

          

  value对象内部以linkedlist或者ziplist来实现:

当list的元素个数和单个元素的长度比较小的时候,Redis会采用ziplist(压缩列表)来实现来减少内存占用。
否则就会采用linkedlist(双向链表)结构。
  redis3.2之后,采用的一种叫quicklist的数据结构,实现ziplist和双向链表的二者结合,quicklist仍然是一个双向链表,只是列表的每个节点都是一个ziplist。

三、集合Set
  1、类型定义
  Redis的集合Set和列表List都可以存储多个字符串,但是列表可以存储多个相同的字符串,而集合则通过使用散列表来保证自己存储的每个字符串都是不相同的。Redis使用无序的方式存储元素。

  集合类型是为了方便对多个集合进行操作和运算。集合中每个元素不同且没有顺序的概念,每个元素都是且只能是一个字符串。常用操作是对集合插入、删除、判断等操作。时间复杂度尾O(1)。可以进行交集、并集、差集运算。集合类型在redis中的存储是一个值为空的散列表(这些散列表只有键,但是没有与键相关的值)。

复制代码
1)增加:SADD key value。
2)删除:SREM key value。
3)获取指定集合的所有元素:SMEMBERS key。
4)判断某个元素是否存在:SISMEMBER key value。
5)差集运算:SDIFF key1 key2...。对多个集合进行差集运算。
6)交集运算:SINNER key1 key2...。对多个集合进行交集运算。
7)并集运算:SUNION key1 key2...。对多个集合进行并集运算。
8)获取集合中元素个数:SCARD key。返回集合中元素的总个数。
9)对差集、交集、并集运算的结果存放在一个指定的key中:SDIFFSTORE storekey key1 key2。对key1和key2求差集,结果存放在key为storekey的
    集合中。SINNERSTORE和SUNIONSTORE类似。
10)获取集合中的随即元素:SRANDMEMBER key [count]。参数count可选,如果count不存在,则随即一个。count大于0,则是不重复的count个元素。
    count小于0,则是一共|count|个元素,可以重复。
11)随即弹出一个元素:SPOP key。随即从集合中弹出一个元素并删除,将该元素的值返回。
复制代码
  2、应用场景  
标签(tag):集合类型比较典型的使用场景,如一个用户对娱乐、体育比较感兴趣,另一个可能对新闻感兴趣,这些兴趣就是标签,有了这些数据就可以得到同一标签的人,以及用户的共同爱好的标签,这些数据对于用户体验以及曾强用户粘度比较重要。
使用技巧:

sadd=tagging(标签)
spop/srandmember=random item(生成随机数,比如抽奖)
sadd+sinter=social Graph(社交需求)
  3、实现原理
底层数据结构以intset或者值为空的hashtable来存储。

四、散列Hash
  1、类型定义
  Redis的散列可以存储多个键值对之间的映射,和字符串一样,存储的Redis是以字典(关联数组)的形式存储的,一个key对应一个value。在字符串类型中,value只能是一个字符串。那么在散列类型,也叫哈希类型中,value对应的也是一个字典(关联数组)。那么就可以理解,Redis的哈希类型/散列类型中,key对应的value是一个二维数组。但是字段的值只可以是字符串。也就是说只能是二维数组,不能有更多的维度。

  散列的值既可以是字符串也可以是数字值,并且用户可以对散列存储的数字值进行自增操作以及自减操作。

复制代码
1)赋值:HSET key field value。如hset user name lane。hset user age 23
2)取值:HGET key field。如hget user name,得到的是lane。
3)同一个key多个字段赋值:HMSET key field1 value1 field2 value2...
4)同一个KEY多个字段取值:HMGET key field1 fields2...
5)获取KEY的所有字段和所有值:HGETALL key。如HGETALL user得到的是name lane age 23。每个返回都是独立的一行。
6)字段是否存在:HEXISTS key field。存在返回1,不存在返回0
7)当字段不存在时赋值:HSETNX key field value。如果key下面的字段field不存在,则建立field字段,且值为value。如果field字段存在,则不执行
    任何操作。它的效果等于HEXISTS + HSET。但是这个命令的优点是原子操作。再高的并发也不会怕怕。
8)自增N:HINCREBY key field increment。同字符串的自增类型,不再阐述。
9)删除字段:DEL key field1 field2...删除指定KEY的一个或多个字段。
10)只获取字段名:HKEYS key。与HGETALL类似,但是只获取字段名,不获取字段值。
11)只获取字段值:HVALS key。与HGETALL类似,但是只获取字段值,不获取字段名。
12)获取字段数量:HLEN key。
复制代码
  2、应用场景
缓存HashMap结构型数据
模拟数据库关联查询
  由于Hash的value值就是一个HashMap数据结构,相对于字符串序列化缓存信息更加直观,并且在更新操作上更加便捷,所以常常用于用户信息等管理。

  哈希类型和关系型数据库有所不同,哈希类型是稀疏的,而关系型数据库是完全结构化的,关系型数据库可以做复杂的关系查询,而redis去模拟关系型复杂查询开发困难,维护成本高。

  3、实现原理
  Redis 中的 Hash和 Java的 HashMap 更加相似,都是数组+链表的结构.当发生 hash 碰撞时将会把元素追加到链表上.值得注意的是在 Redis的Hash中value只能是字符串,如图所示:

          

  源码如下:

复制代码
struct dictht {
dictEntry **table; //entry 数组
long size; //数组长度
long used //数组中的元素个数
...
}
struct dictEntry{
void *key; //hash 的 key
void *val; //hash 的 value
dictEntry *next; //下一个dictEntry 链表结构
}
复制代码
  在 Java 中 HashMap 扩容是个很耗时的操作,需要去申请新的数组,为了追求高性能,Redis 采用了渐进式 rehash 策略.这也是 hash 中最重要的部分。那么什么是渐进式呢?

  在 hash 的内部包含了两个hashtable,一般情况下只是用一个。如图所示:

            

  在扩容的时候 rehash 策略会保留新旧两个 hashtable 结构,查询时也会同时查询两个 hashtable,Redis会将旧 hashtable 中的内容一点一点的迁移到新的 hashtable 中,当迁移完成时,就会用新的 hashtable 取代之前的.当 hashtable 移除了最后一个元素之后,这个数据结构将会被删除.如图所示:
               
  数据搬迁的操作放在 hash 的后续指令中,也就是来自客户端对 hash 的指令操作.一旦客户端后续没有指令操作这个 hash.Redis就会使用定时任务对数据主动搬迁。

正常情况下,当 hashtable 中元素的个数等于数组的长度时,就会开始扩容,扩容的新数组是原数组大小的 2 倍.如果 Redis 正在做 bgsave(持久化) 时,可能不会去扩容,因为要减少内存页的过多分离(Copy On Write).但是如果 hashtable 已经非常满了,元素的个数达到了数组长度的 5 倍时,Redis 会强制扩容.
当hashtable 中元素逐渐变少时,Redis 会进行缩容来减少空间占用,并且缩容不会受 bgsave 的影响,缩容条件是元素个数少于数组长度的 10%.
五、有序集合类型ZSet
  1、类型定义
  有序集合和散列一样,都用于存储键值对:有序集合的键被称为成员(member),每个成员都是各不相同的,而有序集合的值则被称为分值(score),分值必须是浮点数,有序集合是Redis里面唯一一个既可以根据成员访问元素,又可以根据分值以及分值的排序来访问元素的结构。

  集合类型是无序的,每个元素是唯一的。那么有序集合就是有序的,每个元素是唯一的。有序集合类型和集合类型的差别是,有序集合为每个元素配备了一个属性:分数。有序集合就是根据分数来排序的。有序集合是使用散列表和跳跃表实现的。所以和列表相比,操作中间元素的速度也很快。时间复杂度尾O(log(N))。Redis数据类型中的有序集合类型比Redis数据类型中的列表类型更加耗费资源。

复制代码
1)增加:ZADD key sorce1 value1 sorce2 value2...。
2)获取分数:ZSCORE key value。获取key的有序集合中值为value的元素的分数。
3)获取排名在某个范围内的元素列表:ZRANFGE key start stop [WITHSCORE]。获取排名在start和end之间的元素列表,包含start和end2个元素。
    每个元素一行。如果有WITHSCORE参数,则一行元素值,一行分数。时间复杂度为O(LOGn+m)。如果分数相同,则0<0<A<Z<a<z。
4)获取指定分数范围的元素:ZRANGEBYSCORE key min max [WITHSCORE] [LIMIT offset count]。获取分数在min和max之间的元素列表。含两头。
    每个元素一行。如果有WITHSCORE参数,则一行元素值,一行分数。如果min大于max则顺序反转。
5)为某个元素增加分数:ZINCRBY key increment value。指定的有序集合的值为value的元素的分数+increment。返回值后更改后的分数。
6)获取集合中元素的数量:ZCARD key。
7)获取指定分数范围内的元素个数:ZCOUNT key min max。
8)删除一个或多个元素:ZREM key value1 value2...
9)根据排名范围删除元素:ZREMRANGEBYRANK key start end。删除排名在start和end中的元素。
10)按照分数范围删除元素:ZREMRANGEBYSCORE key min max。
11)获得元素排名(正序):ZRANK key value。获取value在该集合中的从小到大的排名。
12)获得元素排名(倒序):ZREVRANK key value。获取value在该集合中从大到小的排名。
13)有序集合的交集:ZINTERSTORE storekey key1 key2...[WEIGHTS weight [weight..]] [AGGREGATE SUM|MIN|MAX]。用来计算多个集合的交集,
    结果存储在storekey中。返回值是storekey的元素个数。AGGREGATE为SUM则storekey集合的每个元素的分数是参与计算的集合分数和。MIN是参
    与计算的分数最小值。MAX是参与计算分数最大值。WEIGHTS 设置每个集合的权重,如WEIGHTS 1 0.1。那么集合A的每个元素分数1,集合B的每
    个元素分数
0.1
14)有序集合的并集:ZUNIONSTORE storekey key1 kye2...[WEIGHTS weight [weight..]] [AGGREGATE SUM|MIN|MAX]
复制代码
  2、应用场景
显示最新评论:score就是一个有序生成的不断增长的序列号,因此可以获取最新多少条评论。
获取Top N系列:有序集合经典使用场景。例如视频网站需要对用户上传的视频做排行榜,榜单维护可能是多方面:按照时间、按照播放量、按照获得的赞数等。
做交集、差集
  3、实现原理
内部是以ziplist或者skiplist+hashtable来实现。
  skiplist,也就是跳跃表,跳跃表是一种随机化的数据结构,在查找、插入和删除这些字典操作上,其效率可比拟于平衡二叉树(如红黑树),如下图:

        
六、特殊名词
  1、压缩列表ziplist
  压缩表(ziplist)是列表键(3.2之前的版本)和哈希键的底层实现之一。

  作为哈希键的实现底层条件:当一个哈希键只包含少量的键值对,并且每个键值对的键和值要么是小整数数值要么就是长度较短的字符串时,Redis就会使用压缩列表来作为哈希键的底层实现。

  压缩列表是Redis为了节约内存而开发的,由一系列特殊编码的连续内存块组成的顺序型数据结构。一个压缩列表可以包含任意多个节点(entry),每个节点保存一个字节数组或者一个整数值。

2、跳跃表SkipList
  跳跃表是一种可以对有序链表进行近似二分查找的数据结构,redis在两个地方用到了跳跃表,一个是实现有序集合,另一个是在集群节点中用作内部数据结构。

  跳跃表(skiplist)是一种有序数据结构,它通过在每个节点中维持多个指向其他节点的指针,从而达到快速访问节点的目的。跳跃表支持平均O(logN)、最坏O(N)复杂度的节点查找,还可以通过顺序性操作来批量处理节点。在大部分情况下,跳跃表的效率可以和平衡树相媲美,并且因为跳跃表的实现比平衡树要来得更为简单,所以有不少程序都使用跳跃表来代替平衡树。

Redis使用跳跃表作为有序集合键的底层实现之一,如果一个有序集合包含的元素数量比较多,又或者有序集合中元素的成员(member)是比较长的字符串时,Redis就会使用跳跃表来作为有序集合键的底层实现。

和链表、字典等数据结构被广泛地应用在Redis内部不同,Redis只在两个地方用到了跳跃表,一个是实现有序集合键,另一个是在集群节点中用作内部数据结构,除此之外,跳跃表在Redis里面没有其他用途。

  跳跃表的结构如下图所示:

标签:Redis,元素,redis,value,列表,key,使用,集合
From: https://www.cnblogs.com/velloLei/p/18413599

相关文章

  • Redis之pipeline与事务
    前言    Redis使用的是单reactor网络模型,也就是io多路复用+非阻塞io的异步处理流程(注册事件,在事件循环callback处理事件)。我们可以将每个连接抽象看成一个pipe,哪个pipe中的数据先满就先处理。注意,单reactor指的是acceptor只有一个,而工作线程在6.0版本之前只有一个,也就......
  • Mastering openFrameworks_第五章_使用视频
    使用视频使用视频镜头是一种简单的方式来添加动态图层的交互式项目场景。而视频处理是现代计算机视频艺术的基础。本章将涵盖openFrameworks项目中播放、分层和处理视频的基本和高级主题:播放视频文件处理视频帧径向和水平狭缝扫描效果正在处理来自摄像机的实时视频视频......
  • GIS进阶-Openlayers、Vue+Openlayers、Leaflet、Geoserver、PostGis、Java集成Geotool
    场景作为一名非专业GIS开发者,在日常企业级开发中遇到GIS领域相关业务需求时,参考资料较少,各种体系生态不明确。往往因为错过了好多大神封装好的工具、借口、三方框架、api等白白浪费时间。最主要的是此专栏会持续更新,毕竟GIS的知识体系远不止如此,后续会持续记录、共同积累、共同......
  • Golang中命名参数的高级使用技巧与实例分析
    Golang是一门以简洁、高效著称的编程语言,因其强大的并发处理能力和灵活的语法设计,被广泛应用于各种开发场景。在Golang中,参数传递是日常编程中不可或缺的部分,而命名参数的使用则能够提升代码的可读性和维护性。本文将探讨Golang中命名参数的高级使用技巧,并通过实例进行分析,帮助开......
  • Redis解决"Warning: Using a password with .....may not be safe"
    Redis的命令行工具redis-cli可以连接、访问Redis数据库,在没有设置密码验证的情况下,我们可以无需密码直接访问Redis数据库,如下所示./redis-cli127.0.0.1:6379>127.0.0.1:6379>pingPONG127.0.0.1:6379>我们连接到本地的Redis服务并执行ping命令,该命令用于检测Redis服务是否启动,......
  • redis集群的搭建
    一、创建节点文件夹因为集群至少要6个节点,所有创建6个文件夹mkdir700{0,1,2,3,4,5}二、复制配置文件到每个创建的文件夹cpredis.conf700{0,1,2,3,4,5}三、修改每个配置文件的端口等信息绑定服务器的IP:bind0.0.0.0或者注释掉#bind0.0.0.0关闭保护模式用于公网访......
  • 迅为RK3588开发板/核心板 | 在高性能处理器上如何使用GPIO
    GPIO基本概念GPIO,即General-PurposeInput/Output,指的是可以由软件控制的通用输入输出引脚。每个GPIO引脚可以配置为输入或输出,用来读取外部设备的状态(如按键)或控制外设(如LED、马达等)GPIO应用领域GPIO作为嵌入式设备中不可或缺的接口,在以下多个领域有广泛应用:●智能家居:用于控制和......
  • Android开发使用WebSocket时如何构建数据通讯框架
    前言之前我们介绍过服务端使用WebSocket如何设计数据框架,现在我们看看客户端如何与它通讯。如果光说要用WebSocket做一个例子,相信很多小伙伴都能搞通,网上这么多资料。随便拿一个过来,调通就行了。不过,做出来与把它做好是两码事。我们的目标是,不但要把数据调通,还要把它梳理完善......
  • 怎么安装使用PbootCMS网站模板
    安装和使用PBootCMS网站模板的过程主要包括以下几个步骤:1.下载模板访问PBootCMS官网或其他可信来源下载你所需的模板文件。确认下载的模板兼容你的PBootCMS版本。2.上传模板将下载好的模板文件上传到你的服务器或虚拟主机。通常模板文件会被压缩,上传之后需要解压到正确......
  • 【随记】服务器安装并配置jupyter notebook,并使用vscode扩展进行连接
    重新新建虚拟环境(如果使用的是miniconda),安装好需要使用的第三方库进入环境后condainstalljupyter为当前环境安装jupyter服务使用python3进入命令行交互,输入以下命令配置登陆密钥fromjupyter_server.authimportpasswdpasswd()运行结束后会返回一串hash后的密钥数......