文章目录

  • string
  • 存储对象
  • 分布式锁
  • 其他场景
  • hash
  • 对象缓存
  • 购物车
  • list
  • 微博消息和工作号
  • set
  • 微信小程序抽奖
  • 微信点赞,收藏
  • 微博关注模型
  • 电商搜索模型
  • zset
  • 微博排行榜
  • 一些面试题
  • Scan指令



hashmap redis 效率 redis和hashmap_Redis

string

set key value  # 设置一个key value 存在就覆盖
mset key value key1 value1 #批量设置key value 存在就覆盖
get key #根据一个key得到一个value 没有key返回空
get key key1 # 批量获取key
del key # 删除一个
expire key seconds # 给一个key设置一个秒数为seconds的过期时间
incr key # 给一个key原子加1,没有key就新建key+1. value类型不同会报错
decr key # 给一个key原子减1  没有key就新建key-1,可以负数
setnx key value # 当key不存在的时候设置 不然不生效

存储对象

set user:1 value(对象json)
mset user:1:name ck user:1:age 20 #分存每个属性 适合某个字段经常修改

分布式锁

setnx lock true # 返回1代表设置成功 返回0代表设置失败(判断是否加锁成功)
del lock # 解锁
set key vale ex seconds nx # 设置一个key vlue并且给他seconds的失效时间

其他场景

  • 和spring一起做分布式session
  • 利用 incr key做分布式自增id 和 类似一篇文章被点击过多少次

hash

类似java中的 Map<String,Map<String,Object>>

hset person name ck age 18 # 设置一个key为person value为Map(name,ck)(age,18) 返回成功插入的int数量
hsetnx  person name 1 # 尝试在一个key为person中设置value为Map(name,1)只有在name不存在的情况下才能设置
hmset person1 name cyz age 19 sex man- # 设置一个key为person1 value为Map(name,cyz)(age,19)(sex,man) 返回ok
HGET person name # 获取key为person中的 Map(key=mame)的value
HMGET person name age # 批量获取key为person中的 Map(key=name 和 key=age)的value
hdel person name age #删除key为person中的 Map(key=name 和 key=age)的value,如果删光了 最外层的key也会消失
HLEN person2 # 返回key为peron2中有多少个元素 int类型
HGETALL person2 #返回key为person2中所有的key 和 value的值
HINCRBY  person2 age increment #key person2 中的age自增increment的数量

对象缓存

hashmap redis 效率 redis和hashmap_缓存_02


hashmap redis 效率 redis和hashmap_Redis_03


redis集群架构下如果hash中的值过大,不好做多个集群分配。因为只有一个key。

购物车

hashmap redis 效率 redis和hashmap_java_04

list

hashmap redis 效率 redis和hashmap_redis_05

lpush list1 cyz # 从左边插入 可批量
rpush list1 ck # 从右边插入 可批量
lpop list1 # 从左边弹出值 弹出后list中这个值会消失
rpop list1 # 从右边弹出
lrange list1 start end # 从左边获取start到end的元素 
BLPOP  list1  timeout # 阻塞从左边弹出 在timeout的等待时间内
BRPOP  list1  timeout # 阻塞从右边弹出 在timeout的等待时间内

常用的数据结构实现

Stack(栈) = LPUSH + LPOP
Queue(队列)= LPUSH + RPOP
Blocking MQ(阻塞队列)= LPUSH + BRPOP

微博消息和工作号

类似你订阅了一些微博和公众号,如何在订阅消息中获取

hashmap redis 效率 redis和hashmap_redis_06

# 某个公众号号主发送一条新内容
lpush msg:user1Id 1008  #1008为消息的id
# 另一个公众号号主发送一条新内容
lpush msg:user1Id 1009  
# 用户打开消息 接收消息,而且这样自身就是按时间排序
lrange list1 0  2

set

SADD  key  member  [member ...]			//往集合key中存入元素,元素存在则忽略,							若key不存在则新建
SREM  key  member  [member ...]			//从集合key中删除元素
SMEMBERS  key					//获取集合key中所有元素
SCARD  key					//获取集合key的元素个数
SISMEMBER  key  member			//判断member元素是否存在于集合key中
SRANDMEMBER  key  [count]			//从集合key中选出count个元素,元素不从key中删除
SPOP  key  [count]				//从集合key中选出count个元素,元素从key中删除

set 运算操作

SINTER  key  [key ...] 				//交集运算
SINTERSTORE  destination  key  [key ..]		//将交集结果存入新集合destination中
SUNION  key  [key ..] 				//并集运算
SUNIONSTORE  destination  key  [key ...]		//将并集结果存入新集合destination中
SDIFF  key  [key ...] 				//差集运算
SDIFFSTORE  destination  key  [key ...]		//将差集结果存入新集合destination中

hashmap redis 效率 redis和hashmap_hashmap redis 效率_07

微信小程序抽奖

hashmap redis 效率 redis和hashmap_redis_08


srandmember 不删除元素 还可以继续抽

spop 删除元素 中了一次就不能再抽

微信点赞,收藏

hashmap redis 效率 redis和hashmap_java_09

微博关注模型

A 关注的人 ASet-> {B,C,D,E}
B 关注的人 BSet->{A,F,C,D,G}

A和B共同关注的人(求交集)

SINTER A B--> {C, D}

可能认识的人

SDIFF A B ->{A,F G} 去掉自己A

电商搜索模型

hashmap redis 效率 redis和hashmap_hashmap redis 效率_10


也就是求交集

zset

hashmap redis 效率 redis和hashmap_redis_11

微博排行榜

hashmap redis 效率 redis和hashmap_redis_12


七日搜索榜单的计算解释

ZUNIONSTORE hotNews:20190813-20190819  7 
hotNews:20190813  hotNews:20190814... hotNews:20190819

ZUNIONSTORE 求并集指令
hotNews:20190813-20190819 新的key 代表13号~19之间所有的set并集
7:代表有几个元素
hotNews:20190813~hotNews:20190819: 都是key 表示这几个set放进来求并集

一些面试题

Redis是单线程吗?
Redis 的单线程主要是指 Redis 的网络 IO 和键值对读写是由一个线程来完成的,这也是 Redis 对外提供键值存储服务的主要流程。但 Redis 的其他功能,比如持久化、异步删除、集群数据同步等,其实是由额外的线程执行的。
Redis 单线程为什么还能这么快?
因为它所有的数据都在内存中,所有的运算都是内存级别的运算,而且单线程避免了多线程的切换性能损耗问题。正因为 Redis 是单线程,所以要小心使用 Redis 指令,对于那些耗时的指令(比如keys),一定要谨慎使用,一不小心就可能会导致 Redis 卡顿。
Redis 单线程如何处理那么多的并发客户端连接?
Redis的IO多路复用:redis利用epoll来实现IO多路复用,将连接信息和事件放到队列中,依次放到文件事件分派器,事件分派器将事件分发给事件处理器。

Scan指令

假如在redis中有10个key 为 con1~10

hashmap redis 效率 redis和hashmap_redis_13


假如我要查找所有con开头的

hashmap redis 效率 redis和hashmap_缓存_14


如果con开头的有几百万 几千万 keys 的效率非常差。可以采用scan

SCAN cursor [MATCH pattern] [COUNT count]

存放key的存储结构类似于hashMap 有一个桶+链表
cursor: 整数值 hash桶的索引值 一般第一次为0
Match:要匹配的规则
count:遍历key的数量。可能不准

第一次运行

hashmap redis 效率 redis和hashmap_java_15


第二次运行要将他返回的4 放在cursor的位置上

hashmap redis 效率 redis和hashmap_缓存_16

重复第二步直到返回0为止

hashmap redis 效率 redis和hashmap_Redis_17


所有的返回结果拼凑成完整结果

注意:但是scan并非完美无瑕, 如果在scan的过程中如果有键的变化(增加、 删除、 修改) ,那么遍历效果可能会碰到如下问题: 新增的键可能没有遍历到, 遍历出了重复的键等情况, 也就是说scan并不能保证完整的遍历出来所有的键, 这些是我们在开发时需要考虑的