当前位置 博文首页 > 程序员springmeng:redis那些事

    程序员springmeng:redis那些事

    作者:[db:作者] 时间:2021-08-10 22:17

    欢迎关注我的公众号:springmeng,共同分享软件开发的事。

    简单来说 redis 就是一个数据库,不过与传统数据库不同的是 redis 的数据是存在内存中的,所以存写速度非常快,因此redis 被广泛应用于缓存方向。另外,redis 也经常用来做分布式锁。redis 提供了多种数据类型来支持不同的业务场景。除此之外,redis支持事务、持久化、LUA脚本、LRU驱动事件、多种集群方案。

    ?

    为什么要用redis /为什么要用缓存? ? ? ?

    ?

    主要从“高性能”和“高并发”这两点来看待这个问题。

    ?

    高性能:

    ?

    假如用户第一次访问数据库中的某些数据。这个过程会比较慢,因为是从硬盘上读取的。将该用户访问的数据存在数缓存中,这样下一次再访问这些数据的时候就可以直接从缓存中获取了。操作缓存就是直接操作内存,所以速度相当快。如果数据库中的对应数据改变的之后,同步改变缓存中相应的数据即可!

    ?

    ?

    高并发:

    ?

    直接操作缓存能够承受的请求是远远大于直接访问数据库的,所以我们可以考虑把数据库中的部分数据转移到缓存中去,这样用户的一部分请求会直接到缓存这里而不用经过数据库。

    ?

    ?

    ?

    ?

    为什么要用 redis 而不用 map/guava 做缓存?? ? ? ? ? ? ? ? ? ??

    ?

    缓存分为本地缓存和分布式缓存。以 Java 为例,使用自带的 map 或者guava 实现的是本地缓存, 主要的特点是轻量以及快速,生命周期随着 jvm 的销毁而结束,并且在多实例的情况下,每个实例都需要各自保存一份缓存,缓存不具有一致性。

    ?

    使用 redis 或 memcached 之类的称为分布式缓存,在多实例的情况下,各实例共用一份缓存数据,缓存具有一致性。缺点是需要保持redis 或 memcached服务的高可用,整个程序架构上较为复杂。

    ?

    redis 和 memcached 的区别? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?

    对于 redis 和 memcached 我总结了下面四点。现在公司一般都是用redis 来实现缓存,而且 redis 自身也越来越强大了!

    ?

    1.redis支持更丰富的数据类型(支持更复杂的应用场景):Redis不仅仅支持简单的k/v类型的数据,同时还提供list,set,zset,hash等数据结构的存储。memcache支持简单的数据类型,String。

    ?

    2.Redis支持数据的持久化,可以将内存中的数据保持在磁盘中,重启的时候可以再次加载进行使用,而

    ?

    Memecache把数据全部存在内存之中。

    ?

    3.集群模式:memcached没有原生的集群模式,需要依靠客户端来实现往集群中分片写入数据;但是redis 目前是原生支持 cluster 模式的.

    ?

    4.Memcached是多线程,非阻塞IO复用的网络模型;Redis使用单线程的多路 IO 复用模型。

    ?

    ?

    ?

    ?

    redis 常见数据结构以及使用场景分析? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?

    1.String? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?

    ?

    ?常用命令: set,get,decr,incr,mget 等。

    ?

    String数据结构是简单的key-value类型,value其实不仅可以是String,也可以是数字。常规key-value缓存应用;常规计数:微博数,粉丝数等。

    ?

    2.Hash? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??

    ?常用命令: hget,hset,hgetall 等。

    ?

    Hash 是一个 string 类型的field 和 value 的映射表,hash 特别适合用于存储对象,后续操作的时候,你可以直接仅仅修改这个对象中的某个字段的值。比如我们可以Hash数据结构来存储用户信息,商品信息等等。比如下面我就用hash 类型存放了我本人的一些信息:

    ?

    key = JavaUser29380547;value = {  "id":1,  "name":zhixihanxi,  "age":22  }?

    3.List? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??

    ?常用命令: lpush,rpush,lpop,rpop,lrange等

    ?

    list 就是链表,Redis list 的应用场景非常多,也是Redis重要的数据结构之一,比如微博的关注列表,粉丝列表,消息列表等功能都可以用Redis的list 结构来实现。

    ?

    Redis list 的实现为一个双向链表,即可以支持反向查找和遍历,更方便操作,不过带来了部分额外的内存开销。另外可以通过lrange 命令,就是从某个元素开始读取多少个元素,可以基于 list 实现分页查询,这个很棒的一个功能,基于 redis 实现简单的高性能分页,可以做类似微博那种下拉不断分页的东西(一页一页的往下走),性能高。

    ?

    4.Set? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??

    ?常用命令: sadd,spop,smembers,sunion 等

    ?

    set 对外提供的功能与list类似是一个列表的功能,特殊之处在于 set是可以自动排重的。

    ?

    当你需要存储一个列表数据,又不希望出现重复数据时,set是一个很好的选择,并且set提供了判断某个成员是否在一个set集合内的重要接口,这个也是list所不能提供的。可以基于 set轻易实现交集、并集、差集的操作。

    ?

    比如:在微博应用中,可以将一个用户所有的关注人存在一个集合中,将其所有粉丝存在一个集合。Redis可以非常方便的实现如共同关注、共同粉丝、共同喜好等功能。这个过程也就是求交集的过程,具体命令如下:

    ?

    5.Sorted Set? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?

    ?

    常用命令: zadd,zrange,zrem,zcard等

    ?

    和set相比,sorted set增加了一个权重参数score,使得集合中的元素能够按score进行有序排列。

    ?

    举例:在直播系统中,实时排行信息包含直播间在线用户列表,各种礼物排行榜,弹幕消息(可以理解为按消息维度的消息排行榜)等信息,适合使用Redis 中的 SortedSet 结构进行存储。

    ?

    redis 设置过期时间? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??

    ?

    Redis中有个设置时间过期的功能,即对存储在 redis 数据库中的值可以设置一个过期时间。作为一个缓存数据库,这是非常实用的。如我们一般项目中的token 或者一些登录信息,尤其是短信验证码都是有时间限制的,按照传统的数据库处理方式,一般都是自己判断过期,这样无疑会严重影响项目性能。

    ?

    我们 set key 的时候,都可以给一个 expire time,就是过期时间,通过过期时间我们可以指定这个 key可以存活的时间。

    ?

    如果假设你设置了一批 key只能存活1个小时,那么接下来1小时后,redis是怎么对这批key进行删除的?定期删除+惰性删除。

    ?

    通过名字大概就能猜出这两个删除方式的意思了。

    ?

    ?定期删除:redis默认是每隔100ms 就随机抽取一些设置了过期时间的key,检查其是否过期,如果过期就删除。注意这里是随机抽取的。为什么要随机呢?你想一想假如redis 存了几十万个 key ,每隔100ms就遍历所有的设置过期时间的 key的话,就会给 CPU 带来很大的负载!? 惰性删除:定期删除可能会导致很多过期 key到了时间并没有被删除掉。所以就有了惰性删除。假如你的过期 key,靠定期删除没有被删除掉,还停留在内存里,除非你的系统去查一下那个 key,才会被redis给删除掉。这就是所谓的惰性删除,也是够懒的哈!但是仅仅通过设置过期时间还是有问题的。我们想一下:如果定期删除漏掉了很多过期 key,然后你也没及时去查,也就没走惰性删除,此时会怎么样?如果大量过期key堆积在内存里,导致redis内存块耗尽了。怎么解决这个问题呢?

    ?

    redis 内存淘汰机制。

    ?

    6.7 redis 内存淘汰机制(MySQL里有2000w数据,Redis中只存

    ?

    20w的数据,如何保证Redis中的数据都是热点数据?)

    ?

    redis配置文件 redis.conf 中有相关注释,提供 6种数据淘汰策略:

    ?

    1.? ? ?volatile-lru:从已设置过期时间的数据集(server.db[i].expires)中挑选近 少使用的数据淘汰

    ?

    2.? ? ?volatile-ttl:从已设置过期时间的数据集(server.db[i].expires)中挑选将要过期的数据淘汰

    ?

    3.? volatile-random:从已设置过期时间的数据集(server.db[i].expires)中任意选择数据淘汰

    ?

    4.? ? ?allkeys-lru:当内存不足以容纳新写入数据时,在键空间中,移除近 少使用的key(这个是 常用的).

    ?

    5.? ? ?allkeys-random:从数据集(server.db[i].dict)中任意选择数据淘汰

    ?

    6.? ? ?no-eviction:禁止驱逐数据,也就是说当内存不足以容纳新写入数据时,新写入操作会报错。这个应该没人使用吧!

    cs
    下一篇:没有了