个人随笔
目录
Redis五种数据类型
2019-07-15 23:11:22

在没有redis之前,客户端访问后端应用时,当并发大的时候,存储层如mysql是支撑不了的,可能会将存储层mysql压死,存储层一旦宕机,整个应用就完了。为了很高效的加速应用的读写速度,同时也可以降低后端负载在一定程度上可以通过AOF和RDB机制保证在一定的情况下(如缓存层宕机)快速恢复数据为应用提供服务。缓存层可以通过主从复制+哨兵或集群实现高可用。

一、Redis简介

Redis(REmote DIctionary Server)是一个开源的使用ANSI C语言编写的基于内存亦可持久化的日志型,key-value数据库,并提供了多种语言。它通常被称为数据结构服务器,因为值可以是string,hash,list,set,zset.

Redis采用了单线程架构和I/O多路复用模型来实现高性能的内存数据库服务,Redis执行命令的速度非常快,官方给出的数字是读写性能可以达到10万/秒。

二、Redis为何这么快

在单线程的架构下为什么能如此快呢?主要有四点原因:

  1. redis的所有数据是存放在内存中的
  2. redisC语言实现的,C语言实现的程序距离操作系统更近
  3. Redis使用了单线程架构,预防了多线程可能产生的竞争问题,例如,CPU频繁切换,资源竞争等问题。
  4. Redis源代码非常少,可以说是精打细磨的。

三、基本数据结构

1、字符串(String)

可以是字符串(简单的字符串、复杂的字符串(例如JSON、XML))、数字(整数、浮点数),甚至是二进制(图片、音频、视频),但是值最大不能超过512MB。

命令

添加元素

  1. //ex:秒级过期时间,nx:键不存在时才能设置成功,xx键存在时才能设置成功
  2. set key value [ex seconds] [px milliseconds] [nx|xx]

获取值

  1. get key

批量设置值

  1. mset key value [key value ...]
  2. mset a 1 b 2 c 3 d 4

批量获取值

  1. mget key [key ...]
  2. mget a b c d

计数

  1. incr key

追加值

  1. append key value

字符串长度

  1. strlen key

设置并返回原值

  1. getset key value

设置指定位置的字符

  1. setrange key offeset value
  2. //例子
  3. set redis pest
  4. setrange redis 0 b
  5. get redis
  6. 结果:"best"

获取部分字符串

  1. getrange key start end

内部编码

  1. int 长整型
  2. embstr 短字符(<=39字节)
  3. raw 长字符(>39)

使用场景

1、缓存

  1. // 定义键
  2. userRedisKey = "user:info:" + id;
  3. // 从 Redis 获取值
  4. value = redis.get(userRedisKey);
  5. if (value != null) {
  6. // 将值进行反序列化为 UserInfo 并返回结果
  7. userInfo = deserialize(value);
  8. return userInfo;
  9. }

2、计数:点赞,视频播放量,每播放一次就+1

  1. long incrVideoCounter(long id) {
  2. key = "video:playCount:" + id;
  3. return redis.incr(key);
  4. }

3、接口防刷:验证码登录,公司一般的验证码等发短信功能都是调用的第三方接口,如果被有心之人利用了,会给公司造成一定的损失,所以简单的解决方法就是限流

  1. phoneNum = "138xxxxxxxx";
  2. key = "shortMsg:limit:" + phoneNum;
  3. // SET key value EX 60 NX
  4. isExists = redis.set(key,1,"EX 60","NX");
  5. if(isExists != null || redis.incr(key) <=5){
  6. // 通过
  7. }else{
  8. // 限速
  9. }
2、哈希(hash)

哈希类型是指键值本身又是一个键值对结构,value={{field1,value1},…{fieldN,valueN}}

命令

  1. //设置值
  2. hset key field value
  3. //获取值
  4. hget key field
  5. //删除field
  6. hdel key field [field ...]
  7. //计算field个数
  8. hlen key
  9. //批量设置或获取field-value
  10. hmset key field value [field value ...]
  11. hmget key field [field ...]
  12. //判断field是否存在
  13. hexists key field
  14. //获取所有field
  15. hkeys key
  16. //获取所有value
  17. hvals key
  18. //获取所有的field-value
  19. hgetall key
  20. //以某种形式自增
  21. hincrby key field
  22. hincrbyfloat key field
  23. //计算value的字符串长度
  24. hstrlen key field

内部编码

  1. ziplist:当field个数不超过hash-max-ziplist-entries(默认为512个)时,并且没有大value(64个字节以上算大)
  2. hashtable:ziplist的两个条件只要有一个不符合就会转换为hashtable

使用场景

  1. 存储用户信息
  2. 原生string:直观,占用键多
  3. 序列化字符串:序列化后好操作,每次都需要反序列化和序列化所有字段
  4. 哈希类型:简单直观,减少内存空间的使用
3、列表(list)

用来存储多个有序的字符串,列表中的每个字符串称为元素(element),一个列表最多可以存储2^32 -1个元素。

命令

  1. //从右边插入元素
  2. rpush key value [value ...]
  3. //从左边插入元素
  4. lpush key value [value ...]
  5. //向某个元素前或者后插入元素
  6. linsert key before|after pivot value
  7. //获取指定范围内的元素列表
  8. lrange key start end
  9. //获取列表指定索引下标的元素
  10. lindex key index
  11. //获取列表长度
  12. llen key
  13. //从列表左侧弹出元素
  14. lpop key
  15. //从列表右侧弹出
  16. rpop key
  17. //删除指定元素,count>0从左到右,count<0从右到左,count=0,删除所有
  18. lrem key count value
  19. //按照索引范围修剪列表
  20. ltrim key start end
  21. //修改指定索引下标的元素:
  22. lset key index newValue
  23. //阻塞式弹出
  24. //列表为空,则按照设置的timeout值进行阻塞
  25. //列表不为空,则会立即返回
  26. blpop key [key ...] timeout
  27. brpop key [key ...] timeout

内部编码

  1. ziplist(压缩列表):当列表的元素个数小于list-max-ziplist-entries配置(默认512个),同时列表中每个元素的值都小于list-max-ziplist-value配置时(默认64字节),Redis会选用ziplist来作为列表的内部实现来减少内存的使用。
  2. linkedlist(链表):当列表类型无法满足ziplist的条件时,Redis会使用linkedlist作为列表的内部实现。

使用场景

  1. 消息队列:Redislpush+brpop命令组合即可实现阻塞队列
4、集合(set)

用来保存多个的字符串元素,但和列表类型不一样的是,集合中不允许有重复元素,并且集合中的元素是无序的,不能通过索引下标获取元素。

命令

添加元素

  1. sadd key element ...
  2. sadd myset a b c

删除元素

  1. srem key element [element ...]
  2. //返回成功删除元素个数
  3. srem myset a b

计算元素个数

  1. scard key

判断元素是否在集合中

  1. sismember key element

随机从集合返回指定个数元素

  1. srandmember key [count]

从集合随机弹出元素

  1. spop key

获取所有元素

  1. smembers key

多个集合求交集

  1. sinter key [key ...]

多个集合求并集

  1. suinon key [key ...]

求多个集合的差集

  1. sdiff key [key ...]

将交集、并集、差集的结果保存

  1. sinterstore destination key [key ...]
  2. suionstore destination key [key ...]
  3. sdiffstore destination key [key ...]

内部编码

  1. intset(整数集合):当集合中的元素都是整数且元素个数小于set-max-intset-entries配置(默认512个)时,Redis会选用intset来作为集合的内部实现,从而减少内存的使用。
  2. hashtable(哈希表):当集合类型无法满足intset的条件时,Redis会使用hashtable作为集合的内部实现。

使用场景

  1. 给用户添加标签
  2. 抽奖,生成随机数,集合不能存放相同的元素,因此随机pop出一个元素,可以作为中奖的号码社交需求:可以给用户推荐有相同兴趣的人,用于交友。
5、有序集合(zset)

不能有重复的元素,而且还可以排序,它和列表使用索引下标作为排序依据不同的是,它给每个元素设置一个分数(score)作为排序的依据。

命令

添加成员

  1. zadd key score member
  2. zadd user:ranking 251 tom

计算成员个数

  1. zcard key
  2. zcard user:ranking

计算某个成员的分数,如果成员不存在,则返回nil

  1. zscore key member
  2. zscore user:ranking tom

计算成员的排名,zrank是分数从低到高,zrevrank从高到低

  1. zrank key member
  2. zrevrank key member

删除成员

  1. zrem key member
  2. //将成员mike从有序集合user:ranking中删除
  3. zrem user:ranking mike

增加成员的分数

  1. zincrby key increment member
  2. //给tom增加了9分,分数变为了260分
  3. zincrby user:ranking 9 tom

返回指定排名范围的成员

  1. //从低到高返回
  2. zrange key start end [withscores]
  3. //从高到低返回
  4. zrevrange key start end [withscores]
  5. //返回排名最低的是三个成员
  6. zrange user:ranking 0 2 withscores
  7. 1) "kris"
  8. 2) "1"
  9. 3) "frank"
  10. 4) "200"
  11. 5) "tim"
  12. 6) "220"

返回指定分数范围的成员

  1. zrangebyscore key min max [withscores] [limit offset count]
  2. zrevrangebyscore key max min [withscores] [limit offset count]

返回指定分数范围成员个数

  1. zcount key min max

删除指定排名内的升序元素

  1. zremrangebyrank key start end

删除指定分数范围的成员

  1. zremrangebyscore key min max

求两个集合交集

  1. zinterstore destination numkeys key [key ...] [weights weight [weight ...]]
  2. [aggregate sum|min|max]
  3. //求交集,结果保存到user:ranking:1_inter_2
  4. zinterstore user:ranking:1_inter_2 2 user:ranking:1
  5. user:ranking:2

求并集

  1. zunionstore destination numkeys key [key ...] [weights weight [weight ...]]
  2. [aggregate sum|min|max]
  3. //求并集
  4. zunionstore user:ranking:1_union_2 2 user:ranking:1
  5. user:ranking:2

内部编码

  1. ziplist(压缩列表):当有序集合的元素个数小于zset-max-ziplist-entries配置(默认128个),同时每个元素的值都小于zset-max-ziplist-value配置(默认64字节)时,Redis会用ziplist来作为有序集合的内部实现,ziplist可以有效减少内存的使用。
  2. skiplist(跳跃表):当ziplist条件不满足时,有序集合会使用skiplist作为内部实现,因为此时ziplist的读写效率会下降。

使用场景

  1. 用户点赞数排行
  2. 排行榜
  3. 展示用户信息及用户分数(例如学校中按学生分数排序)
 754

啊!这个可能是世界上最丑的留言输入框功能~


当然,也是最丑的留言列表

有疑问发邮件到 : suibibk@qq.com 侵权立删
Copyright : 个人随笔   备案号 : 粤ICP备18099399号-2