这是我参与「第三届青训营 -后端场」笔记创作活动的第3篇笔记
常用的命令总结
keys *
ttl key
pttl key
type key
exists key
expire key 整数 秒
pexpire key 整数 毫秒
rename key newkey
del key
unlink key 后台删除指定key
string
set
get
mset
mget
append key value
incr key
incrby key num
incrbyfloat key 0.7
decr key
getrange key [start] [end] 截取字符串
strlen key
setnx key "faker" 如果key不存在,创建key set if not exist
msetnx k1 v1 k2 v2 具有原子性,要么一起成功,要么一起失败
setex key time value ----- set with expire
Expire为key设置过期时间 Setex为key设置value值,并且设置过期时间 区别Setex是一个原子操作:设置值与设置过期时间两个动作, 会在同一时间完成 在Redis缓存中
链表操作
lpush key value
rpush key value
lpop key 返回并删除链表头部元素
lrange key [start] [stop] 返回链表中 [start, stop]中的元素
lindex key [index] 通过下标获得key中的某一个值
llen key
lrem list [个数] [value] 精准匹配
127.0.0.1:6379> LPUSH list one # 将一个值或者多个值,插入到列表头部 (左)
(integer) 1
127.0.0.1:6379> LPUSH list two
(integer) 2
127.0.0.1:6379> LPUSH list three
127.0.0.1:6379> LRANGE list 0 -1
1) "three"
2) "three"
3) "two"
127.0.0.1:6379> lrem list 1 three
(integer) 1
127.0.0.1:6379> LRANGE list 0 -1
1) "three"
2) "two"
127.0.0.1:6379> Lpush list three
(integer) 3
127.0.0.1:6379> lrem list 2 three
(integer) 2
127.0.0.1:6379> LRANGE list 0 -1
1) "two"
rpoplpush 将原列表的最后一个元素移除,把这个元素移动到新的列表中
rpoplpush [原列表] [新列表]
lset 将列表中指定的下标值替换为另一个值
注意:
如果这个列表不存在则会报错
如果指定的下标不存在值,也会报错
lset key [index] value
linsert 将某个具体的value2插入到value1前面或后面
linsert key before [value1] [value2]
linsert key after [value1] [value2]
set
set 中的值不能重复
sadd myset value
smembers myset 查看set集合中的所有值
sismember meyset value 判断某一个值是不是在set集合中
srem myset value 移除set集合中的指定元素
scard myset 获取set集合中的个数
srandmember myset 随机抽选一个元素
spop myset 随机删除一个set集合中的元素
sdiff set1 set2 差集
sinter set1 set2 交集
sunion set1 set2 并集
sunionstore destination key1 key2 ... 将key1 与 key2 并集集合存在destination
hash
hset myhash key1 value
hget myhash key1
hmget
hgetall myhash 获取全部的数据
hdel myhash key1 删除hash指定key字段
hlen myhash 获取hash表的字段数量
hexists myhash key1 判断hash 中指定字段是否存在
hkeys myhash 只获得所有field
hvals myhash 只获得所有value
hsetnx myhash key1 value 如果不存在则可以设置,如果存在则不能设置
zset
zset 会按 score 进行排序
zadd myzset score member
zadd myzset score1 member1 score2 member2
zrangebyscore myzset -inf +inf 显示全部member 从小到大
zrevrange myzset 0 -1 从大到小排序
zrangebyscore myzet -inf +inf withscores 显示全部用户并且附带成绩
zrem myzset member
zcard myset 获取有序集合中的个数
zcount myset 1 100 在[1,100]这个区间里面有多少个成员
bitmap
-
位存储
统计用户信息,活跃,不活跃,登陆不登陆这两种状态。
他的数据结构是位图,用1位来表示两种状态,分别额外为0,1
setbit key [num] value
getbit key num
bitcount key 统计个数
Geospatial 地理位置
geoadd key [经度] [纬度] name1
geopos key name1 获得name1的经度和纬度
geodist key name1 name2 km 查看name1与name2直线距离
- m 米
- km 千米
- mi 英里
- ft 英尺
georadius 以给定的经纬度为中心,找到某一半径内的元素
georadius key [110] [30] 1000 km
以110,30这个经纬度为中心,寻找方圆1000km内的name
GEO底层的实现原理其实就是Zset,我们可以使用Zset来操作geo
事务
- 事务中的所有命令会被序列化,按序执行,在执行过程中不会被其他客户端发送来的数据打断
- 队列中的命令在事务没有提交之前不会被实际执行
- redis在EXEC之前有语法错误,redis会检查出来并自动放弃事务
- redis在调用EXEC后有条语句执行有错误,那么只有这一条语句有问题,其他语句能正常执行
原子性定义:
一个事务(transaction)中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节。事务在执行过程中发生错误,会被恢复(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。
watch
悲观锁:
- 认为什么时候都会出现问题,无论做什么都会加锁
乐观锁:
- 认为什么时候都不会出现问题,所以不会上锁,更新数据的时候判断一下,在此期间是否有人修改过这个数据
watch 监控一个变量,当这个变量发生变化时,exec无法执行成功,我们需要unwatch,在watch,如果此时没有线程修改,那么我们可以exec成功
订阅
subscribe [频道名] 订阅一个或者多个频道
publish [频道名] [消息] 将消息发送到指定的频道上
unsubscribe [频道名] 退订指定的频道
布隆算法
如何存一个数:
根据存的值计算hash-》在对应下标的存储数组进行标记,当有人查询这个变量,则会查看这个数组
只能存储的数据大小为0----数组长度-1
存在错误:因为存在hash碰撞
如何避免错误:加大数组的长度
降低错误率:增加hash函数的个数 将值传给多个hash函数,等到多个值,只有这多个值都为1,则表示存了数据了
控制hash个数,否则适得其反,如下如,当hsh过多时,传过来的值,直接把数组填满了,那么下次来数据则全表示存了
redis 与mysql之间有个过滤器,而过滤器一般嵌入在ngix里面
根据数量n以及bit数组长度m,得到hash函数的个数
k = (m/n)(ln2)
根据预估计数量n,以及误码率fpp,bit数组大小m
m = - (n*lnfpp)/(ln2)^2
redis 缓存雪崩
-
缓存穿透
用户想要查询一个数据,发现redis内存数据库没有,也就是缓存没有命中,于是向持久层数据库查询。发现也没有,于是本次查询失败。当用户很多的时候,缓存都没有命中,于是都去请求持久层数据库。这给持久层数据库造成很大的压力,这时候就相当于出现了缓存穿透。
-
缓存击穿
是指一个key非常热点,在不停的扛着大并发,大并发集中对这一个点进行访问,当这个key在失效的瞬间,持续的大并发就穿破缓存,直接请求数据库,就像在一个屏障上凿开一个洞。
当某个key在过期的瞬间,有大量请求并发访问,这类数据一般是热点数据,由于缓存过期, 会同时访问数据库来查询最新数据,并且回写缓存,会导使数据库瞬间压力过大。
-
缓存雪崩
缓存雪崩,是指在某一个时间段,缓存集中过期失效。redis宕机。
产生雪崩的愿意之一, 比如在写本文的时候,马上就要到双十二零点,很快就会迎来一波抢购,这波商品时间比较集中的放入了缓存,假设缓存一个小时。那么到了凌晨一点钟的时候,这批商品的缓存就都过期了。而对这批商品的访问查询,都落到了数据库上,对于数据库而言,就会产生周期性的压力波峰。于是所有的请求都会达到存储层,存储层的调用量会暴增,造成存储层也会挂掉的情况。
其实集中过期,倒不是非常致命,比较致命的缓存雪崩,是缓存服务器某个节点宕机或断网。因为自然形成的缓存雪崩,一定是在某个时间段集中创建缓存,这个时候,数据库也是可以顶住压力的。无非就是对数据库产生周期性的压力而已。而缓存服务节点的宕机,对数据库服务器造成的压力是不可预知的,很有可能瞬间就把数据库压垮