- 简介
- 概述
- 常用数据类型
- String类型操作实践
- incr/incrby
- decr/decrby
- append
- strlen
- mset/mget
- 小节面试分析
- Hash类型应用实践
- hset/hget
- hmset/hmget
- hincrby
- hexists
- hdel
- hkeys/hvals
- hlen
- 小节面试分析
- List类型应用实践
- lpush
- rpush
- del
- linsert
- lset
- lrem
- ltrim
- lpop
- rpop
- llen
- lindex
- rpoplpush
- 小节面试分析
- Set类型应用实践
- sadd
- smembers
- spop
- scard
- smove
- sunion
- 小节面试分析
- 总结(Summary)
Redis作为一种key/value结构的数据存储系统,为了便于对数据进行进行管理,提供了多种数据类型。然后,基于指定类型存储我们项目中产生的数据,例如用户的登陆信息,购物车信息,商品详情信息等等。
常用数据类型Reids中基础数据结构包含字符串、散列,列表,集合,有序集合。工作中具体使用哪种类型要结合具体场景。
String类型操作实践字符串类型是redis中最简单的数据类型,它存储的值可以是字符串,其最大字符串长度支持到512M。基于此类型,可以实现博客的字数统计,将日志不断追加到指定key,实现一个分布式自增iid,实现一个博客的的点赞操作等
incr/incrby当存储的字符串是整数时,redis提供了一个实用的命令 incr,其作用是让当前键值递增,并返回递增后的值。
incr key 按照默认步长(默认为1)进行递增
incrby key decrement 按照指定步长进行递增
语法:incr key
127.0.0.1:6379> set num 1 OK 127.0.0.1:6379> incr num (integer) 2 127.0.0.1:6379> keys * 1) "num" 127.0.0.1:6379> incr num (integer) 3 127.0.0.1:6379>
说明,如果num不存在,则自动会创建,如果存在自动+1。
指定增长系数
语法:INCRBY key increment
127.0.0.1:6379> incrby num 2 (integer) 5 127.0.0.1:6379> incrby num 2 (integer) 7 127.0.0.1:6379> incrby num 2 (integer) 9 127.0.0.1:6379>decr/decrby
减少指定的整数
decr key 按照默认步长(默认为1)进行递减
decrby key decrement 按照指定步长进行递减
127.0.0.1:6379> incr num (integer) 10 127.0.0.1:6379> decr num (integer) 9 127.0.0.1:6379> decrby num 3 (integer) 6 127.0.0.1:6379>append
向尾部追加值。
如果键不存在,则创建该键,其值为写的value,即相当于set key value。
返回值是追加后字符串的总长度。
语法:append key value
127.0.0.1:6379> keys * 1) "test" 127.0.0.1:6379> get test "123" 127.0.0.1:6379> append test "abc" (integer) 6 127.0.0.1:6379> get test "123abc" 127.0.0.1:6379>strlen
字符串长度
返回数据的长度,如果键不存在则返回0。注意,如果键值为空串,返回值也是0。
语法:strlen key
127.0.0.1:6379> get test "123abc" 127.0.0.1:6379> strlen test (integer) 6 127.0.0.1:6379> strlen tnt (integer) 0 127.0.0.1:6379> set tnt "" OK 127.0.0.1:6379> strlen tnt (integer) 0 127.0.0.1:6379> exists tnt (integer) 1 127.0.0.1:6379>mset/mget
同时设置/获取多个键值
语法:
mset key value
mget key
127.0.0.1:6379> flushall OK 127.0.0.1:6379> keys * (empty list or set) 127.0.0.1:6379> mset a 1 b 2 c 3 OK 127.0.0.1:6379> mget a b c 1) "1" 2) "2" 3) "3" 127.0.0.1:6379>小节面试分析
- 博客的字数统计如何实现?(strlen)
- 如何将审计日志不断追加到指定key?(append)
- 你如何实现一个分布式自增id?(incr-雪花算法)
- 如何实现一个博客的的点赞操作?(incr,decr)
Redis散列类型相当于Java中的HashMap,实现原理跟HashMap一致,一般用于存储对象信息,存储了字段(field)和字段值的映射,一个散列类型可以包含最多232-1个字段。
hset/hget赋值/取值
hset命令不区分插入和更新操作,当执行插入操作时hset命令返回1,当执行更新操作时返回0。
语法结构
hset key field value hget key field hmset key field value hmget key field hgetall key
hset 和 hget 赋值和取值
127.0.0.1:6379> hset user username chenchen (integer) 1 127.0.0.1:6379> hget user username "chenchen" 127.0.0.1:6379> hset user username chen (integer) 0 127.0.0.1:6379> keys user 1) "user" 127.0.0.1:6379> hgetall user 1) "username" 2) "chen" 127.0.0.1:6379> 127.0.0.1:6379> hset user age 18 (integer) 1 127.0.0.1:6379> hset user address "xi'an" (integer) 1 127.0.0.1:6379> hgetall user 1) "username" 2) "chen" 3) "age" 4) "18" 3) "address" 4) "xi'an" 127.0.0.1:6379>hmset/hmget
语法结构
hmset key field value hmget key field hgetall key
hmset 和 hmget 设置和获取对象属性
127.0.0.1:6379> hmset person username tony age 18 OK 127.0.0.1:6379> hmget person age username 1) "18" 2) "tony" 127.0.0.1:6379> hgetall person 1) "username" 2) "tony" 3) "age" 4) "18" 127.0.0.1:6379>
注意:上面 hmget 字段顺序可以自行定义
hincrby127.0.0.1:6379> hdecrby article total 1 #执行会出错 127.0.0.1:6379> hincrby article total -1 #没有hdecrby自减命令 (integer) 1 127.0.0.1:6379> hget article total #获取值hexists
属性是否存在
127.0.0.1:6379> hexists killer (error) ERR wrong number of arguments for 'hexists' command 127.0.0.1:6379> hexists killer a (integer) 0 127.0.0.1:6379> hexists user username (integer) 1 127.0.0.1:6379> hexists person age (integer) 1 127.0.0.1:6379>hdel
删除属性
127.0.0.1:6379> hdel user age (integer) 1 127.0.0.1:6379> hgetall user 1) "username" 2) "chen" 127.0.0.1:6379> hgetall person 1) "username" 2) "tony" 3) "age" 4) "18" 127.0.0.1:6379>hkeys/hvals
只获取字段名 hkeys 或字段值 hvals
127.0.0.1:6379> hkeys person 1) "username" 2) "age" 127.0.0.1:6379> hvals person 1) "tony" 2) "18"hlen
获取元素个数
127.0.0.1:6379> hlen user (integer) 1 127.0.0.1:6379> hlen person (integer) 2 127.0.0.1:6379>小节面试分析
- 发布一篇博客需要写内存吗?(需要,hmset)
- 浏览博客内容会怎么做?(hmget)
- 如何判定一篇博客是否存在?(hexists)
- 删除一篇博客如何实现?(hdel)
- 分布式系统中你登录成功以后是如何存储用户信息的?(hmset)
Redis的list类型相当于java中的linkedList,其原理就就是一个双向链表。支持正向、反向查找和遍历等操作,插入删除速度比较快。
经常用于实现热销榜,最新评论等的设计。
| 序号 | 命令 | 作用 | 示例 |
|---|---|---|---|
| 1 | lpush | 在头(左边)部添加多个key值 | lpush names ‘张三’,lpush names ‘李四’ |
| 2 | lrange | 获取指定范围的key的值 | lrange names 0 10 |
| 3 | blpop | 移除并获取第一个元素,并设置阻塞时间 | blpop names 10 |
| 4 | brpop | 移除并获取尾部元素,并设置阻塞时间 | brpop names 10 |
| 5 | lindex | 通过索引获取列表中的key值 | lindex names 1 |
| 6 | linsert | 在张三前|后插入tom值 | linsert names before|after ‘张三’ ‘tom’ |
| 7 | llen | 获取列表长度 | llen names |
| 8 | lpop | 移出并获取第一个元素 | lpop names |
| 9 | lpushx | 将多值插入到已存在的列表头部 | lpushx names lili |
| 10 | lrem | 移除指定个数的值,count表示方向 | lrem ages 2 10 |
| 11 | lset | 修改指定索引的值 | lset ages 1 11 |
| 12 | ltrim | 保留修剪内部的数据 | ltrim ages 1 -1 |
| 13 | rpop | 移出尾部元素,并返回 | rpop ages |
| 14 | rpush | 在尾(右边)部添加多个key值 | rpush ages 14 15 |
| 15 | rpushx | 将多值插入到已存在的列表头部 | rpushx names hahah |
| 16 | rpoplpush | 将尾部的值移到新key中 | rpoplpush names newname |
在 key 对应 list 的头部添加字符串元素
redis 127.0.0.1:6379> lpush mylist "world" "hello" (integer) 2 redis 127.0.0.1:6379> lrange mylist 0 -1 #0表示第一个,-1表示最后一个 1) "hello" 2) "world" redis 127.0.0.1:6379>
其中,Redis Lrange 返回列表中指定区间内的元素,区间以偏移量 START 和 END 指定。 其中 0 表示列表的第一个元素, 1 表示列表的第二个元素,以此类推。 你也可以使用负数下标,以 -1 表示列表的最后一个元素, -2 表示列表的倒数第二个元素,以此类推
rpush在 key 对应 list 的尾部添加字符串元素
redis 127.0.0.1:6379> rpush mylist2 "hello" "world" (integer) 2 redis 127.0.0.1:6379> lrange mylist2 0 -1 1) "hello" 2) "world" redis 127.0.0.1:6379>del
redis 127.0.0.1:6379> del mylistlinsert
在 key 对应 list 的特定位置之前或之后添加字符串元素
redis 127.0.0.1:6379> rpush mylist3 "hello" "world" (integer) 2 redis 127.0.0.1:6379> linsert mylist3 before "world" "there" (integer) 3 redis 127.0.0.1:6379> lrange mylist3 0 -1 1) "hello" 2) "there" 3) "world" redis 127.0.0.1:6379>lset
设置 list 中指定下标的元素值(一般用于修改操作)
redis 127.0.0.1:6379> rpush mylist4 "one" (integer) 1 redis 127.0.0.1:6379> rpush mylist4 "two" (integer) 2 redis 127.0.0.1:6379> rpush mylist4 "three" (integer) 3 redis 127.0.0.1:6379> lset mylist4 0 "four" OK redis 127.0.0.1:6379> lset mylist4 -2 "five" OK redis 127.0.0.1:6379> lrange mylist4 0 -1 1) "four" 2) "five" 3) "three" redis 127.0.0.1:6379>lrem
从 key 对应 list 中删除 count 个和 value 相同的元素
当count>0时,按从头到尾的顺序删除
redis 127.0.0.1:6379> rpush mylist5 "hello" (integer) 1 redis 127.0.0.1:6379> rpush mylist5 "hello" (integer) 2 redis 127.0.0.1:6379> rpush mylist5 "foo" (integer) 3 redis 127.0.0.1:6379> rpush mylist5 "hello" (integer) 4 redis 127.0.0.1:6379> lrem mylist5 2 "hello" (integer) 2 redis 127.0.0.1:6379> lrange mylist5 0 -1 1) "foo" 2) "hello" redis 127.0.0.1:6379>
当count<0时,按从尾到头的顺序删除
redis 127.0.0.1:6379> rpush mylist6 "hello" (integer) 1 redis 127.0.0.1:6379> rpush mylist6 "hello" (integer) 2 redis 127.0.0.1:6379> rpush mylist6 "foo" (integer) 3 redis 127.0.0.1:6379> rpush mylist6 "hello" (integer) 4 redis 127.0.0.1:6379> lrem mylist6 -2 "hello" (integer) 2 redis 127.0.0.1:6379> lrange mylist6 0 -1 1) "hello" 2) "foo" redis 127.0.0.1:6379>
当count=0时,删除全部
redis 127.0.0.1:6379> rpush mylist7 "hello" (integer) 1 redis 127.0.0.1:6379> rpush mylist7 "hello" (integer) 2 redis 127.0.0.1:6379> rpush mylist7 "foo" (integer) 3 redis 127.0.0.1:6379> rpush mylist7 "hello" (integer) 4 redis 127.0.0.1:6379> lrem mylist7 0 "hello" (integer) 3 redis 127.0.0.1:6379> lrange mylist7 0 -1 1) "foo" redis 127.0.0.1:6379>ltrim
保留指定 key 的值范围内的数据
redis 127.0.0.1:6379> rpush mylist8 "one" (integer) 1 redis 127.0.0.1:6379> rpush mylist8 "two" (integer) 2 redis 127.0.0.1:6379> rpush mylist8 "three" (integer) 3 redis 127.0.0.1:6379> rpush mylist8 "four" (integer) 4 redis 127.0.0.1:6379> ltrim mylist8 1 -1 OK redis 127.0.0.1:6379> lrange mylist8 0 -1 1) "two" 2) "three" 3) "four" redis 127.0.0.1:6379>lpop
从 list 的头部删除元素,并返回删除元素
redis 127.0.0.1:6379> lrange mylist 0 -1 1) "hello" 2) "world" redis 127.0.0.1:6379> lpop mylist "hello" redis 127.0.0.1:6379> lrange mylist 0 -1 1) "world" redis 127.0.0.1:6379>rpop
从 list 的尾部删除元素,并返回删除元素:
redis 127.0.0.1:6379> lrange mylist2 0 -1 1) "hello" 2) "world" redis 127.0.0.1:6379> rpop mylist2 "world" redis 127.0.0.1:6379> lrange mylist2 0 -1 1) "hello" redis 127.0.0.1:6379>llen
返回 key 对应 list 的长度:
redis 127.0.0.1:6379> llen mylist5 (integer) 2 redis 127.0.0.1:6379>lindex
返回名称为 key 的 list 中 index 位置的元素:
redis 127.0.0.1:6379> lrange mylist5 0 -1 1) "three" 2) "foo" redis 127.0.0.1:6379> lindex mylist5 0 "three" redis 127.0.0.1:6379> lindex mylist5 1 "foo" redis 127.0.0.1:6379>rpoplpush
从第一个 list 的尾部移除元素并添加到第二个 list 的头部,最后返回被移除的元素值,整个操作是原子的.如果第一个 list 是空或者不存在返回 nil:
rpoplpush lst1 lst1
rpoplpush lst1 lst2
- 如何基于redis实现一个队列结构?(lpush/rpop)
- 如何基于redis实现一个栈结构?(lpush/lpop)
- 如何基于redis实现一个阻塞式队列?(lpush/brpop)
- 如何实现秒杀活动的公平性?(先进先出-FIFO)
- 通过list结构实现一个消息队列(顺序)吗?(可以,FIFO->lpush,rpop)
- 用户注册时的邮件发送功能如何提高其效率?(邮件发送是要调用三方服务,底层通过队列优化其效率,队列一般是list结构)
- 如何动态更新商品的销量列表?(卖的好的排名靠前一些,linsert)
- 商家的粉丝列表使用什么结构实现呢?(若注意顺序,则使用list结构,若不注意顺序,则使用set结构)
Redis的Set类似Java中的HashSet,是String类型的无序集合。集合成员是唯一的,这就意味着集合中不能出现重复的数据。Redis中Set集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是O(1)。
sadd添加元素,重复元素添加失败,返回0
127.0.0.1:6379> sadd name tony (integer) 1 127.0.0.1:6379> sadd name hellen (integer) 1 127.0.0.1:6379> sadd name rose (integer) 1 127.0.0.1:6379> sadd name rose (integer) 0smembers
获取内容
127.0.0.1:6379> smembers name 1) "hellen" 2) "rose" 3) "tony" 127.0.0.1:6379>spop
移除并返回集合中的一个随机元素
127.0.0.1:6379> smembers set1 1) "amoeba" 2) "redis" 3) "rabbitmq" 4) "nginx" 127.0.0.1:6379> spop set1 "rabbitmq" 127.0.0.1:6379> spop set1 "nginx" 127.0.0.1:6379> smembers set1 1) "amoeba" 2) "redis"scard
获取成员个数
127.0.0.1:6379> scard name (integer) 3smove
移动一个元素到另外一个集合中
127.0.0.1:6379> sadd set1 amoeba nginx redis (integer) 3 127.0.0.1:6379> sadd set2 hadopp spark rabbitmq (integer) 3 127.0.0.1:6379> smembers set1 1) "amoeba" 2) "redis" 3) "nginx" 127.0.0.1:6379> smembers set2 1) "hadopp" 2) "spark" 3) "rabbitmq" 127.0.0.1:6379> smove set2 set1 rabbitmq (integer) 1 127.0.0.1:6379> smembers set1 1) "amoeba" 2) "redis" 3) "rabbitmq" 4) "nginx" 127.0.0.1:6379> smembers set2 1) "hadopp" 2) "spark" 127.0.0.1:6379>sunion
两个集合的并集
127.0.0.1:6379> sunion set1 set2 1) "redis" 2) "nginx" 3) "rabbitmq" 4) "amoeba" 5) "hadopp" 6) "spark"小节面试分析
- 朋友圈的点赞功能你如何实现?(sadd,srem,smembers,scard)
- 如何实现一个网站投票统计程序?
- 你知道微博中的关注如何实现吗?
本章节主要是对redis中的常用数据类型存储结构,基本操作进行了分析和实践,结合指令特性理解其应用场景,



