第二天
内容概要
- 哈希类型
- 列表类型
- 集合类型
- 有序集合
- 慢查询
- pipline与事务
- 发布订阅
- Bitmap位图
- HyperLogLog
哈希类型
-
hget, hset,hdelhget key field # 获取hash key对应的field的value时间复杂度为o(l) -
hset key field value设置hash key对应的field的value值时间复杂度为o(1) -
hdel key field删除hash key对应的field的值 时间复杂度为o(1)
hset user:1:info age 23
hset user:1:info name lqz
hgetall user:1:info
hdel user:1:info age
-
hexists,hlen判断hash key 是否存在field 时间复杂读为o(1) -
hlen key 获取hash key field的数量 时间复杂度为o(1) -
hexists user:1:info name hlen user:1:info 返回数量 -
hmget key field1 field2 ...fieldN # 批量获取 hash key的一批field对应的值 时间复杂度是o(n) hmset key field1 value1 field2 value2 # 批量设置hash key的一批field value 时间复杂度是o(n) -
hgetall、hvals、hkeyshgetall key # 返回hash key 对应的所用field和value 时间复杂度是o(n) hvals key # 返回hash key 对应的所有field的value 时间复杂度是o(n) hkey key # 返回hash key对应的所有field 时间复杂度是o(n) 小心使用hgetall计算网站每个用户主页的访问量
hincrby user:1:info pageview count缓存mysql的信息,直接设置hash格式
-
其他操作
hset, hincrby, hincrbyfloat hset key field value # 设置hash key对应field的 # value(如果field已存在,则失败),时间复杂度o(1) hincrby key field intCounter # hash key 对应的field的value自增intCouter 时间复杂度o(1) hincrbyfloat key field floatCounter # hincrby 浮点数 时间复杂度o(1)
列表类型
插入操作
rpush 从右侧插入
rpush key value1 value2 ... valueN
时间复杂度为o(1~n)
lpush 从左测插入
linsert
linsert key before|after value newValue
#从元素value的前或后插入newValue 时间复杂度o(n),需要遍历列表
linsert listkey before b java
linsert listkey after b php
# 删除操作
lpop key # 从列表左侧弹出一个item 时间复杂度o(1)
rpop key # 从列表右侧弹出一个item 时间复杂度o(1)
lrem key count value
# 根据count值, 从列表中删除所有value相同的项 时间复杂度o(n)
1 count>0 从左到右,删除最多count个value相等的项
2 count<0 从右向左,删除最多Math.abs(count)个value相等的项
3 count=0 删除所有value相等的项
lrem listkey 0 a # 删除列表中所有值a
lrem listkey -1 c # 从右侧删除1个c
ltrim key start end # 按照索引范围修剪列表o(n)
ltrim listkey 1 4 # 只保留下表1--4的元素
# 查询操作
lrange key start end # 包含end获取列表指定索引范围所有item o(n)
lrange listkey 0 2
lrange listkey 1 -1 # 获取第一个位置倒数第一个位置的元素
lindex key index # 获取列表指定索引的item o(n)
lindex listkey 0
lindex listkey -1
llen key # 获取列表长度
# 修改操作
lset key index newValue # 设置列表指定索引值为newValue o(n)
lset listkey 2 ppp # 把第二个位置设为ppp
实战
实现timeLine功能,时间轴,微博关注的人,按时间轴排列,在列表中放入关注的人的微博的即可
其他操作
blpop key timeout
# lpop的阻塞版,timeout是阻塞超时 时间,timeout=0为不阻塞o(1)
brpop key timeout
# rpop的阻塞版,timeout是阻塞超时时间,timeout=0 不阻塞o(1)
要实现栈的功能
lpush+lpop
实现队功能
lpush+rpop
固定大小的列表
lpush+ltrim
消息队列
lpush+brpop
集合类型
sadd key element
# 向集合key添加elemnt 如果element存在,添加失败 o(1)
srem key element
# 从集合中的element移除掉 o(1)
scard key # 计算集合大小
sismember key element # 判断element是否在集合中
srandmember key count
# 从集合中随机取出count个元素,不会破坏集合中的元素
spop key # 从集合中随机弹出一个元素
smembers key
# 获取集合中所有元素,无需,小心使用,会阻塞住
sdiff user:1follow user:2:follow
# 计算user:1:follow 和 user:2:follow的差集
sunion user:1:follow user:2:follow
# 计算user:1:follow和user:2:follow的并集
sdiff|sinter|suion + store destkey...
# 将差集,交集,并集结果保存在destkey集合中
应用场景
去重场景
抽奖系统:通过spop来弹出用户的id,活动取消,直接删除,点赞,点踩,喜欢等,用户如果点了赞,就把用户id放到该条记录的集合中
标签:给用户/文章等添加标签,sadd user:1:tags 标签1 标签2 标签3
给标签添加用户,关注该标签的人有哪些
共同好友:集合间的操作
有序集合(zset)
特点:不能重复 有一个分值字段,来保证顺序
key score value
user:ranking 1 lqz
user:ranking 99 lqz2
user:ranking 88 lqz3
集合有序集合
集合:无重复元素,无序,element
有序集合:无重复元素,有序,element+score
列表和有序集合
列表:可以重复,有序,element
有序集合:无重复元素,有序,element+score
API使用
zadd key score element # score可以重复,可以多个同时添加,element不能重复 o(logn)
zrem key element # 删除元素,可以多个同时删除o(1)
zscore key element # 获取元素的分数o(1)
zincrby key increScore element # 增加或减少元素的分数o(1)
zrank key element # 返回element元素的排名(从小到大排)
zrank key 0 -1 # 返回排名,不带分数 o(log(n)+m) n是元素个数,m是要获取的指
zrange player:rank 0 -1 withscores # 返回排名,带分数
zrangebyscore key minScore maxScore
# 返回指定分数范围内的升序元素 o(log(n)+m) n是元素个数, m是要获取的值
zrangebyscore adscore 90 210 withscores
# 获取90分到210分的元素
zcount key minScore maxScore
# 返回有序集合内在指定分数范围内的个数o(log(n)+m)
zremrangebyrank adscore 1 2
删除升序排名中1到2的元素
zremrangebyscore key minScore maxScore
删除指定分数内的升序元素o(log(n)+m)
zremrangebyscore adscore 90 100
删除分数90到210之间的元素
实战
排行榜:音乐排行榜,销售榜,关注榜,游戏排行榜
其他操作
zrevrank # 返回某个元素从高到低排序顺序
zrevrank adscore lqz 返回lqz 按分数降序排名
zrevrange # 从高到低排序取一定范围
zrevrangebyscore # 返回指定分数范围内的降序元素
zinterstore # 对两个有序集合交集
zunionstore # 对两个有序集合求并集
慢查询
单线程架构,命令一个个执行,会有长慢命令,造成整个redis的阻塞
redis提供一种方式,可以记录长慢命令【放到慢查询队列中】,用于后续的排查修改工作
配置慢查询
-slowlog-max-len:慢查询队列的长度
slowly-log-slower-than:超过多少微妙,就算命令们就会记录到慢查询队列中
实战
config set slowlog-log-slower-than 0
config set slowlog-max-len 100
config rewrite
# 写了永久生效,如果不写,只是暂时生效
# 查看慢查询队列
slowlog len # 获取慢查询队列长度
slowlog reset # 清空慢查询队列
slowlog get # 获取慢查询队列的所有命令
pipeline与事务
Redis的pipline(管道)功能在命令行中没有,但redis是支持pipline的,而且在各个语言版的client中都有相应的实现(Redis模块)
将一批命令:批量打包,在redis服务端批量计算(执行),然后把结果批量返回1次pipeline(n条命令)=1次网络时间+n次命令时间
import redis
pool = redis.ConnectionPool(host='127.0.0.1', port=6379)
r = redis.Redis(connection_pool=pool)
# 创建pipline
pipe = r.pipeline(transaction=True)
# 开启事务
pipe.multi()
pipe.set("name", "lqz")
# 其他代码,可能出现异常
pip.set('role','nb')
pipe.execute()
redis原生实现事务 实现事务mutil
1 mutil 开启事务,放到管道中一次性执行
multi # 开启事务
set name lqz
set age 18
exec
2 模拟实现乐观锁 watch+multi实现乐观锁
在开启事务之前,先watch
watch age
multi
decr age
exec
另一台机器
multi
decr age
exec 先执行,上面的执行就会失败(乐观锁,被watch的事务不会执行成功)
发布订阅
发布订阅是 观察者模式:只要订阅了某个东西,这个东西发送变化,我们就能收到
发布者发布了消息,所有的订阅者都可以收到,就是生成者消费者模型(后订阅了,无法获取历史消息)
一个客户端发送消息
publish lqz hello # 只要订阅者,客户端发送消息,所有订阅者都能收到
另外两个客户端,订阅频道,等待接收消息
subscribe lqz
查看两个客户端,订阅频道,等待接收消息
subscribe lqz
查看某个频道有几个订阅者
pubsub numsub lqz
列出活跃的频道
pubsub channels
发布订阅和消息队列
发布订阅数全收到,消息队列有个抢的过程,只有一个抢到
Bitmap位图
Bitmap位图:是字符串类型,但是以二进制形式存储的,获取,设置某个二进制位的
set hello big
getbit hello 0/1/2 返回比特位是0或1
setbit hello 7 1 把第7,也就是8个比特位设置为1
big就变成了cit
bitcount hello 0 1 字节数 返回8
独立用户统计
假设:1亿用户,5千万活跃用户 统计今天活跃用户是多选 用户iduserid是整形,32位
int32 类型 4个字节表示一个数字---》正负 2的31次方-1的范围
方式一:登录,把id放到集合中---》统计集合大小
方式二:登录,操作位图,把id对应的数字设置为1,以后统计1的个数
HyperLogLog
redis中支持这种算法,基于HyperLogLog算法:极小的空间完成独立数量统计很类似与布隆过滤器
pfadd key element # 向hyperloglog添加元素,可以同时添加多个
pfcount key # 计算hyperloglog 独立总数
pfadd uuids "uuid1" "uuid2" "uuid3" # 向uuids添加3个uuid
pfcount uuids # 返回4
# 也可以做独立用户统计

浙公网安备 33010602011771号