基本知识
Redis是一个开源的,基于内存的数据结构存储,可用用于数据库、缓存、消息中间件。实现语言是c语言。单线程。
为什么要使用缓存机制?
假设请求量和并发量特别大的时候,所有的信息都需要去数据库查询,这样就很容易让数据库挂掉,从而有性能问题(访问反应慢,无法获取数据等),因为数据库的读写都是要经过磁盘,然而磁盘的访问速度没有内存快;
假设请求量和并发量特别大的时候,所有的信息都需要去数据库查询,这样就很容易让数据库挂掉,从而有性能问题(访问反应慢,无法获取数据等),因为数据库的读写都是要经过磁盘,然而磁盘的访问速度没有内存快;
Redis可以保存多种数据结构,它的存储基于内存,可以key-Value的形式保存;其保存格式类似于Map
redis默认有16个数据库
默认使用第0个数据库
可以通过select+index切换数据库
dbsize 当前数据库大小
keys *
查看所有的key值
flushall
清空全部库
flushdb
清空当前库
为什么选择6379作为端口号
redis的作者Salvatore Sanfilippo(Antirez),意大利人,6379源于一位意大利的一位广告女郎,其Merz名字对应九宫格上的6379,作者认为这个名字是愚蠢的意思,所以用6379作为端口号
redis为什么要使用单线程
redis是基于内存操作的,速度很快,redis的瓶颈不是CPU,而是机器的机器的内存和网络带宽,既然能使用单线程就使用单线程了
redis为什么单线程还能这么快
误区1:高性能的服务器一定是多线程的
误区2:多线程一定比单线程效率高
核心:redis是将所有的内存放在内存中的,所以用单线程去操作是最高效的,多线程中CPU的上下文切换会耗时,对于内存系统来说,cpu没有上下文切换就是效率最高的,redis多次读写都是在同一个cpu上,在内存情况下,这个就是最佳方案。
redis-key
expire + key + 时间
设置过期时间
ttl+key
剩余时间
type key
查看当前key的类型
redis的基本五大类型
String
append
向尾部追加值。如果键不存在则创建该键,其值为写的value,即相当于SET key value。返回值是追加后字符串的总长度。
语法:APPEND key value
当append的key不存在时,相当于执行一个set操作
strlen
字符串长度,返回数据的长度,如果键不存在则返回0。注意,如果键值为空串,返回也是0。
语法:STRLEN key
decr/decrby
减少指定的整数
DECR key 按照默认步长(默认为1)进行递减
DECRBY key decrement 按照指定步长进行递减
说明,如果key不存在,则自动会创建,如果存在自动+1。
getrange
截取存储的字符串
语法:getrange key start end
setrange
相当于替换字符串
语法:setrannge key 起始位置 替换的字符串
ttl + key 该key的剩余过期时间
setex(set with expire)
设置过期时间
sexnx(set if not exist)
不存在再设置(在分布式锁中会常使用)
如果存在这个key,再set一次的时候会失败,不会覆盖之前的值
mset/mget
同时设置/获取多个键值
语法:MSET key value [key value …]
MGET key [key …]
getset
先get再set,如果没有这个key,返回null,然后赋值
如果存在这个值,先获取,再赋值
小结:
- 博客的字数统计如何实现?(strlen)
- 如何将审计日志不断追加到指定key?(append)
- 你如何实现一个分布式自增id?(incr-雪花算法)
- 如何实现一个博客的的点赞操作?(incr,decr)
List
Redis的list类型相当于java中的LinkedList,其原理就就是一个双向链表。支持正向、反向查找和遍历等操作,插入删除速度比较快。经常用于实现热销榜,最新评论等的设计
Lpush 左边插入 Lpop 从左边移除
Rpush 右边插入 Rpop 从右边移除
del
清空集合元素
linsert
在key对应list的特定位置之前或之后添加字符串元素
lset
设置list中指定下标的元素值(一般用于修改操作)
lrem
从key对应list中删除count个和value相同的元素,count>0时,按从头到尾的顺序删除
ltrim
保留指定key 的值范围内的数据
lindex
返回名称为key的list中index位置的元素:
如何基于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
smembers
获取集合中成员,例如
127.0.0.1:6379> smembers name
spop
移除并返回集合中的一个随机元素
scard
获取集合中的成员个数
smove
移动一个元素到另外一个集合
sunion
实现集合的并集操作