Redis是一种key-value的格式存储数据的NO-SQL非关系型数据库。其中value有五种数据类型:String字符类型、Hash散列类型、List列表类型、Set集合类型、SortedSet或者叫zset有序集合类型。
- 常用redis命令
key是不忽略大小写的,命令是忽略大小写的。
- String类型
一个键最大能存储512MB。redis的string可以包含任何数据。比如jpg图片或者序列化的对象 。
赋值 SET key value ,取值 get key ,删除key del key
将储存的值加上1 incr key ,加上整数amount incrby key amout
将储存的值减去1 decr key ,减去整数amount decrby key amout
将值追加到key当前储存值的末尾 append key v
获取下标start到end的字符串 getrange key start end
- Hash类型
格式: hmset name key1 value1 key2 value2
是一个field和value的映射表,hash特别适合用于存储对象。
为多个key设置值 hmset hkey key v… , 获取多个值hmget hkey key… ,删除多个值并返回 hdel hkey key…
检查key是否存在在散列中 hexists hkey key
获取散列中所有key hkeys hkey
- List类型
是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)。
将一个或多个加入列表左端 lpush key [v…]
将一个或多个加入列表右端 rpush key [v…]
移除并返回最右端的元素 rpop key
移除并返回列表最左端的元素 lpop key
返回下标(偏移量)为size的元素 lindex key size
返回从start 到end的元素 包含start和end lrange key start end
只保留从start 到end的元素 包含start和end ltrim key start end
- Set类型
是无序集合,不允许重复的元素。
添加多个,返回新添加的个数(已存在的不算) sadd key item …
检查元素item是否在集合中 sismember key item
随机的移除一个元素 并返回已删除的元素 spop key
- SortedSet类型
每个元素都会关联一个double类型的分数,分数(score)却可以重复,成员是唯一的,通过分数来为集合中的成员进行从小到大的排序。
添加多个 zadd key score member …
移除多个 zerm key memer…
返回所有成员 zcard key
返回member的分值 zscore key member
- 通用命令
查看满足规则的所有key keys pattern 如,keys mylist*
删除key DEL key
确认一个key是否存在 exists key
设置key的生存时间 EXPIRE key seconds
查看key剩余的生存时间 TTL key
清除生存时间 PERSIST key
生存时间设置单位为毫秒 PEXPIRE key milliseconds
- 缓存淘汰策略
LRU原理:最近最少使用,LRU算法根据数据的历史访问记录来进行淘汰数据,其核心思想是如果数据最近被访问过,则将来被访问的几率也更高。
如使用一个链表保存数据,需满足规则:新插入的数据都插入到头部,最新查询数据都移动到头部,当链表满了就把尾部的数据丢弃。
在redis.conf中有一行配置
maxmemory-policy volatile-lru
Redis提供了6种数据淘汰策略
(1)volatile-lru:从已设置过期时间的数据集中选最近最少使用的数据淘汰。
(2)volatile-ttl:从已设置过期时间的数据集中选要过期的数据淘汰。
(3)volatile-random:从已设置过期时间的数据集中任意选择数据淘汰。
(4)allkeys-lru:从数据集中挑选最近最少使用的数据淘汰。
(5)allkeys-random:从数据集中任意选择数据淘汰。
(6)no-enviction:禁止驱逐数据。
缓存穿透
一般,都是按key去缓存查询,如果没查到,就去数据库查找。如果遇到大量请求查询永远不存在的key,就会都是数据库访问,这就会对数据库产生很大的压力,这种情况就是缓存穿透。
我们可以通过以下方式来防止:
(1)把所有可能会查询的key,放在一个bitmap中,查询前先校验bitmap中是否存在,避免查询本来不存在的数据请求。
(2)对查询结果为空的情况也进行缓存,有效时间设置短一点,在该key被插入后清除缓存,这样可以避免每次不存在的key都会访问数据库。
(3)将可能查到的key在布隆过滤器中存储,规则是,查询存储key,就是查/存的key的hash值,缓存中对存在的key是存1,对不存在的key存0。
缓存雪崩
缓存重启或大量缓存同时段失效,需要都从数据库查,导致的系统崩溃,就是缓存雪崩。
我们可以通过下面方式尽量避免缓存雪崩:
(1)给不同的key,设置不同的过期时间,尽量合理,让缓存失效的时间点均匀分布。
(2)做两级缓存,第一级设置为短期缓存,第二级设置为长期缓存;保证一级缓存失效,可以去二级缓存查找,都找不到,则去数据库查找。
(3)对数据库访问做处理,就是在缓存失效后,通过一定手段控制从数据库查找数据并写入缓存的线程数据,如对查数据库,写入缓存这两部分加锁。
缓存击穿
和缓存雪崩不同之处是,单个缓存有效期到了,而同一时间点有大量请求进行查这个key,导致都访问到数据库了。
我们可以通过下面方式尽量避免缓存击穿:
(1)使用redis的setnx互斥锁。获取到锁,则查询缓存/数据库,否则就处于等待状态中,保证不会大并发操作数据库。
怎么保证缓存中的数据和数据库中的数据库的一致性?
延时双删策略:就是先删除缓存key,再更新数据库数据;等待不会后,再尝试删除一下缓存key,防止整个过程中,出现还没更新完成,其他线程查询了改key并缓存了旧值的情况。
- Redis消息模式
(1)使用List类型的lpush和rpop实现消息队列。
rpush生产消息,lpop消费消息。当lpop没有消息的时候,要适当sleep一会再重试,但是在消费者下线的情况下,生产的消息会丢失,得使用专业的消息队列如rabbitmq等。
(2)如果要实现生产一次消费多次,需要使用pub/sub发布订阅者模式,可以实现1:N的消息队列;要先订阅后发布消息,不然前期发布的数据接收不到。
订阅消息 subscibe my-channel
发布消息 publish my-channel "我是发布者,发布了一个消息,请查收"