结语
小编也是很有感触,如果一直都是在中小公司,没有接触过大型的互联网架构设计的话,只靠自己看书去提升可能一辈子都很难达到高级架构师的技术和认知高度。向厉害的人去学习是最有效减少时间摸索、精力浪费的方式。
我们选择的这个行业就一直要持续的学习,又很吃青春饭。
虽然大家可能经常见到说程序员年薪几十万,但这样的人毕竟不是大部份,要么是有名校光环,要么是在阿里华为这样的大企业。年龄一大,更有可能被裁。
送给每一位想学习Java小伙伴,用来提升自己。
本文到这里就结束了,喜欢的朋友可以帮忙点赞和评论一下,感谢支持!
虽说是字符型,但是实际上我们也可以那它来存储整数、浮点甚至二进制类型
常量命令及说明
-
SET key value [EX seconds|PX milliseconds|EXAT timestamp|PXAT milliseconds-timestamp|KEEPTTL] [NX|XX] [GET]
官方说明 O(1) -
EX seconds,在seconds秒后过期
-
PX milliseconds,在milliseconds毫秒后过期
-
EXAT timestamp,在以秒计算的时间戳后过期
-
PXAT milliseconds-timestamp,在以毫秒计算的时间戳后过期
-
KEEPTTL,保留set之前的过期时间,因为一般来说,string类型的value在再次被set后会清除过期时间,KEEPTTL会保留之前的过期时间,保证过期时间不会因为这次set而被清空
-
NX,如果key不存在,才能set成功
-
XX,如果key存在,才能set成功
-
GET,返回这次set之前当前key的值,这个参数取代了
GETSTE
命令 -
setex key seconds value
官方说明 O(1) 设置key的值为value,并且在seconds秒后过期 -
SETNX key value
官方说明 O(1) short for “SET if Not eXists”. -
MSET key value [key value ...]
官方说明 O(n) 批量设置key的值,这个还是有使用场景的,批量设置虽然是O(n),但是节约了网络IO -
MGET key [key ...]
官方说明 O(n) 批量获取一堆key的值,使用场景同样是解决网络io,但是请求的key如果超级多,也会造成阻塞 -
INCR key
官方说明 O(1) key++再返回,如果key不存在,那么会先创建一个=0的key 然后再++,也就是直接返回1,这个可以做分布式环境的原子计数器。 -
DECR key
官方说明 O(1) 跟上面那个相反 这个是减减操作,如果key不存在,那会直接返回-1 -
INCRBY key increment
官方说明 O(1) 可以设置每次加几的累加器 -
DECRBY key decrement
官方说明 O(1) 可以设置每次减几的累减器 -
APPEND key value
官方说明 O(1) 为key以字符的形式拼接上value,如果key不存在,第一次拼接之后,key的值等于value的值,需要注意的是,一个中文的汉字算3个长度,也就是说"1我"
的长度为4 -
STRLEN key
官方说明 返回字符串的长度,如果key不存在,那就返回0,如果包含汉字,那一个汉字算3个长度。 -
SETRANGE key offset value
官方说明 O(1) 从offset开始修改key的值,offset从0开始计算,如果key本身不存在,同时offset不等于0,那么前面会用空格补全 -
GETRANGE key start end
官方说明 O(n) 返回key的start到end的值,相当于字符串截取,从左到右截取时,从0开始计算位置。从右到左截取时从-1开始计数,getrange k1 0 -1
=get k1
应用场景及注意事项
-
value的最大值是512M
-
一般用来做共享session的存储
-
使用
INCR
和DECR
可以实现原子计数器,从而还可以实现限流的功能 -
从时间复杂度上看,大部分命令都是O(1)的,可以放心使用,但是像del、mset、mget、getrange这些都是O(n)的,使用时需要确认好应用场景以及使用方式。
首先,画个图理解一下哈希这种数据结构,当执行hget时,我们可以从redis中获取到一个哈希表,这个哈希表中的键用field来标识,值用value来表示。
常用命令
-
HSET key field value [field value ...]
官方说明 如果只设置一个field的value,那么时间复杂度就是O(1),如果设置多个,那就是O(n)了 -
HGET key filed
官方说明 O(1) 从key对应的哈希表中获取filed的值 -
HGETALL key
官方说明 O(n) 获取key对应的哈希表的所有内容,如果这个哈希表很大,那很可能造成redis阻塞 -
HSCAN key cursor [MATCH pattern] [COUNT count]
官方说明 O(n) 虽然说这个也是O(n)的,但是由于HSCAN是分批次的同时可以指定返回条数,所以会好很多
应用场景及注意事项
- 从时间复杂度上说:hdel、hmget、hmset、set都跟field的个数有关,而hkeys、hgetall、hvals都跟field的总数有关。
public class User {
String name;
int age;
String id;
}
hset user:1 name 张三 age 12 id fdjskla
这样做的优点是简单直观,使用合理可减少内存空间的消耗,缺点是需要控制ziplist与hashtable两种编码的转换,而且hashtable会消耗更多的内存。同样是上面的例子,我们也可以使用字符串来存储,字符串存储有两种方案:
set user:1:name 张三
set user:1:age 12
set user:1:id fdjskla
优点:简单直观,每一个key对应一个值
缺点:键数过多,占用内存多,user信息过于分散,一般不用于生产环境
set user:1 serialize(userInfo);
优点:编码简单,如使用序列化合理内存使用率高
缺点:序列化与反序列化有一定开销,更新属性时需要吧userInfo全部取出来进行反序列化,更新后再序列化到redis
列表用来存储多个有序的字符串,一个列表可以存放2的32次方-1个元素,一般来说,列表的操作是区分从左到右,还是从右到左的
常用命令
-
RPUSH key element [elements...]
官方说明 O(n) 从右侧(right)开始push数据到list中,相当于我们常用的add操作。push几个,时间复杂度就是O(几) -
LPUSH key element [elements...]
官方说明 O(n) 从左侧(left)开始push数据到list中,相当于add(0,element)。这样也是,push的数据越多,时间复杂度越高 -
LRANGE key start end
官方说明 O(S+N) 需要注意的是,这里的L并不是left的意思,而是指list,LRANGE的具体用法与GETRANGE类似,这里就不说了。 -
LINSERT key BEFORE|AFTER pivot element
官方说明 O(n) 这里的L也是指list意思。意思是在某一个元素的前面或后面插入另一个元素,时间复杂度取决于pivot
的位置。 -
LPOP key [count]
官方说明 O(n) 从左侧(left)弹出count个元素,count的默认值为1,时间复杂度取决于要返回的元素的个数。 -
RPOP key [count]
官方说明 O(n) 从右侧(right)弹出count个元素,count的默认值为1,时间复杂度取决于要返回的元素的个数 -
LREM key count element
官方说明 O(n+m) 这里的L是list的意思,当count>0,列表从头到位查找并删除元素,当count<0时,列表从尾到头遍历并删除元素,当count=0时,删除列表中的所有element。时间复杂度取决于列表中元素个数n和要删除的元素个数m -
LSET key index element
官方说明 O(n) 这里的L也是list的意思,当index>=0时,代表从头到尾定位并设置元素,当index<=-1时,代表从尾到头定位并设置元素,感觉这个就是LPUSH+RPUSH的结合,如果index=0或index=-1,则时间复杂度为1。 -
LINDEX key index
官方说明 O(n) 返回列表中index位置的元素,这样也是根据index是否大于0来区分检索方向的。 -
LLEN key
官方说明 O(1) 返回key对应的列表的元素个数,如果key已存在,但是不是列表,那么会抛出异常,如果key不存在或key是个空列表,那么会返回0。 -
BLPOP key [keys...] timeout
官方说明 O(n) 阻塞式(blocking)LPOP,如果key不存在,或者key指向的list为空,则当前命令会阻塞timeout秒,当timeout=0时,代表阻塞无限久。redis 6.0以后,timeout是double类型而不再是int。当同时存在多个监听的key时,如果有一个key对应的列表不为空,那么就会返回那个列表中的元素,如果所有的列表都为空,那么就会阻塞。 -
BRPOP key [keys...] timeout
官方说明 O(n) 阻塞式(blocking)RPOP
应用场景
-
队列的阻塞式特性可以当做简单的消息中间件
-
生产者—>消费者
在这个模型中,生产者执行rpush list:1 id1 id2 id3
, 消费者执行blpop list:1 0
,当存在可消费的id时,消费者不会阻塞,但是如果没有可消费的id,那消费者就会陷入阻塞,直到有人调用了rpush list:1 id4
- 消息广播
服务A启动后,执行brpop list:A 0
监听队列A,同时执行rpush queueNameList list:A
注册自己的监听队列,然后服务B启动,执行brpop list:B 0
开始监听队列B,同时也注册自己rpush queueNamelist list:B
,这时,如果服务C要通知服务A和服务B,那么服务C执行lrange queueNameList 0 -1
获取到一个队列列表,然后依次执行rpush list:A 消息内容
rpush list:B 消息内容
这时服务A与服务B就都收到消息了。
-
如果多个服务同时监听了一个队列,那么一个消息只能被一个服务消费。
-
由于list是按插入顺序排序的,所以还可以做时间轴
-
LPUSH+LPOP=STACK(栈) 先进后出
-
LPUSH+RPOP=QUEUE (队列) 先进先出
-
LPUSH+LTRIM=CAPPEND COLLECTION(有限集合)
-
LPUSH+BRPOP=MESSAGE QUEUE(消息队列)
集合和我们常用Set还是很类似的,也是一个容器,容器内不能存放相同的元素,同时,在这个容器内的元素是无序的。
常用命令
-
SADD key member [members...]
官方说明 O(n) 向集合中插入元素,时间复杂度与插入的元素个数相关 -
SCARD key
官方说明 O(1) 返回key对应的集合中元素的个数,如果key指向的集合不存在,那么会返回0 -
SISMEMEBER key member
官方说明 O(1) 判断某元素是否存在于集合中,如果存在则返回1,如果元素不存在或者key指向的集合不存在都会返回0 -
SRANDMEMBER key [count]
官方说明 O(n) 从key指向的集合中随机返回count个元素,时间复杂度与count相关。count的默认值为1, -
当count=0时,没有返回值。
-
当count>0且小于集合中元素的总数时,随机从集合中返回count个元素.
-
当count>集合中元素的总数时,返回集合中全部的元素,但是依旧没有顺序。
-
当count<0时,返回的结果中可能出现重复项,但是返回结果的长度一定是count*-1个
-
SPOP key [count]
官方说明 O(n) 从集合中随机pop出count个元素并返回。时间复杂度与count的个数相关,count的默认值为1 -
SMEMBERS key
官方说明 O(n) 返回集合中所有的元素,无序 -
SINTER key [key...]
官方说明 O(n*m) 对给定的集合做交集并返回,时间复杂度为集合中元素个数相乘 -
SUNION key [key...]
官方说明 O(n) 对给定的集合做并集并返回,时间复杂度为所有参与运算的集合的元素的总个数 -
SDIFF key [key...]
官方说明 O(n) 返回集合1与集合2的差集,需要注意的是集合A-集合B<>集合B-集合A ,时间复杂度为所有参与运算的集合的元素的总个数 -
SINTERSTORE destination key [key...]
官方说明 O(n*m) 对给定的集合做交集并存储到destination中,如果destination已存在且不为空,那么destination会被覆盖。 -
SUNIONSTORE destination key [key...]
官方说明 O(n) 对给定的集合做并集,并将结果存到destination中,如果destination已经存在,那么会被覆盖。 -
SDIFFSTORE destination key [key...]
官方说明 O(n) 对给定的集合做差集运算,并将结果存到destination中,如果destination已存在,那么会被覆盖
应用场景
-
集合一般在互联网应用上可以用来做用户标签
-
使用SPOP命令可以从集合中随机弹出count个元素,利用这种特性可以用来做抽奖
-
集合的交、并、差运算的时间复杂度都比较高,所以尽可能使用store命令将结果储存起来,方面下次查看。但是需要注意的是,store命令存储的结果并不会跟着原始集合的变化而变化,当原始集合发生变化后,需要再次使用store命令才能获取到最新的结果。
独家面经总结,超级精彩
本人面试腾讯,阿里,百度等企业总结下来的面试经历,都是真实的,分享给大家!
Java面试准备
准确的说这里又分为两部分:
- Java刷题
- 算法刷题
Java刷题:此份文档详细记录了千道面试题与详解;
算法刷题
Java刷题:此份文档详细记录了千道面试题与详解;
[外链图片转存中…(img-prNwT5Dk-1715646916885)]
[外链图片转存中…(img-dUEukAVV-1715646916885)]