redis简单介绍

1.什么是redis

Redis 本质上也是一种键值数据库的, 但它在保持键值数据库简单快捷特点的同时,

又吸收了部分关系数据库的优点。 从而使它的位置处于关系数据库和键值数 据库之间。 Redis 不仅能保存 Strings 类型的数据, 还能保存 Lists 类型(有序) 和 Sets 类型(无序) 等类型的数据, 而且还能完成排序(SORT) 等高级功能, 在实现 INCR(使key加一), 等功能的时候, 保证了其操作的原子性(要么都成功要么都失败), 除此以外, 还支持主从复制等功能。

2.Redis 用来做什么?

通常局限点来说, Redis 也以消息队列的形式存在, 作为内嵌的 List 存在, 满足实时的高并发需求。 而通常在一个电商类型的数据处理过程之中, 有关商品, 热销, 推荐排序的队列, 通常存放在Redis 之中, 期间也包扩 Storm 对于 Redis 列表的读取和更新。

3.reids的优点

    1.性能极高 – Redis 能支持超过 100K+ 每秒的读写频率。

     2.丰富的数据类型 – Redis 支持二进制案例的 Strings, Lists, Hashes, Sets 及 Ordered Sets
     3.数据类型操作。
     4..原子 – Redis 的所有操作都是原子性的,同时 Redis 还支持对几个操作全并后的原子性执行。
     5.丰富的特性 – Redis 还支持 publish/subscribe, 通知, key 过期等等特性

4.redis的缺点

     数据库容量受到物理内存的限制,不能用作海量数据的高性能读写,因此 Redis 适合的场景主要局限在较小数据量的

      高性能操作和运算上

5.redis的数据类型

在具体描述这几种数据类型之前,我们先通过一张图了解下Redis内部内存管理中是如何描述这些不同数据类型的:

 

  首先Redis内部使用一个redisObject对象来表示所有的key和value,redisObject最主要的信息如上图所示:

      type代表一个value对象具体是何种数据类型,

      encoding是不同数据类型在redis内部的存储方式,

     比如:type=string代表value存储的是一个普通字符串,那么对应的encoding可以是raw或者是int,

               如果是int则代表实际redis内部是按数值型类存储和表示这个字符串的,当然前提是这个字符串本身可以用数值表示,

               比如:"123" "456"这样的字符串。

       这里需要特殊说明一下vm字段,只有打开了Redis的虚拟内存功能,此字段才会真正的分配内存,

       该功能默认是关闭状态的。通过上图我们可以发现Redis使用redisObject来表示所有的key/value数据是比较浪费内存的,

       当然这些内存管理成本的付出主要也是为了给Redis不同数据类型提供一个统一的管理接口

 

      1. Strings数据结构是简单的key-value类型,value其实不仅仅是String,数字也是可以的

          实现方式: String在redis内部默认就是一个字符串,被redisObject所引用,当遇到incr,decr等操作的时候会转换成数值进行计算

      2.hash

         实现方式:Redis Hash对应Value内部实际就是一个HashMap,实际这里会有2种不同实现,

                    这个Hash的成员比较少时Redis为了节省内存会采用类似一维数组的方式来紧凑存储,

                    而不会采用真正的HashMap结构,对应的value redisObject的encoding为zipmap,

                     当成员数量增大时会自动转成真正的HashMap,此时encoding为ht。

     3.List

        实现方式:Redis list的实现为一个双向链表,即可以支持反向查找和遍历,更方便操作,

                    不过带来了部分额外的内存开销,Redis内部的很多实现,包括发送缓冲队列等也都是用的这个数据结构。

    4.set

        实现方式:set 的内部实现是一个 value永远为null的HashMap,实际就是通过计算hash的方式来快速排重的,

                       这也是set能提供判断一个成员是否在集合内的原因。

     5.sorted set

        每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序。

        实现方式:Redis sorted set的内部使用HashMap和跳跃表(SkipList)来保证数据的存储和有序,

                       HashMap里放的是成员到score的映射,而跳跃表里存放的是所有的成员,排序依据是HashMap里存的score,

                       使用跳跃表的结构可以获得比较高的查找效率,并且在实现上比较简单

6. redis的持久化

  •  redis 提供了多种不同级别的持久化方式:大致上分为两种:  RDB,ROF

   1.  RDB 持久化可以在指定的时间间隔内生成数据集的时间点快照,简单来说就是间隔固定的时间持久化一次   

   2.  ROF持久化 持久化记录服务器执行的所有写操作命令,并在服务器启动时,通过重新执行这些命令来还原数据集。

           AOF 文件中的命令全部以 Redis 协议的格式来保存,新命令会被追加到文件的末尾。

          Redis 还可以在后台对 AOF 文件进行重写(rewrite),使得 AOF 文件的体积不会超出保存数据集状态所需的实际大小。

   3. Redis 可以同时使用 AOF 持久化和 RDB 持久化。在这种情况下,当 Redis 重启时,

      它会优先使用 AOF 文件来还原数据集,因为 AOF 文件保存的数据集通常比 RDB 文件所保存的数据集更完整。

   4. redis的持久化是可以关闭的,这个时候数据只在内存中,为什么有的公司不使用redis的持久化

          ,原因是持久化是很消耗性能的,一般来说如果开启持久化可以在redis集群的 (slave)redis上面启用持久化的功能

  5 .RDB模式的优缺点

       ① 优点:

 ·       对性能影响最小。Redis在保存RDB快照时会fork(可以理解为创建出一个新的进程,该进程拥有所有的父进程的东西)

         出子进程进行,几乎不影响Redis处理客户端请求的效率。 (不是绝对的,因为fork子进程的时候会消耗性能)

·        每次快照会生成一个完整的数据快照文件,所以可以辅以其他手段保存多个时间点的快照

       (例如把每天0点的快照备份至其他存储媒介中),作为非常可靠的灾难恢复手段。

·        使RDB文件进行大的数据恢复比使用AOF要快很多。
    ② 缺点

  •   快照是定期生成的,所以或多或少会丢失一部分数据。
  • 如果数据集非常大且CPU不够强(比如单核CPU),Redisfork子进程时可能会消耗相对较长的时间(长至1秒),影响这期间的客户端请求。

   6.ROF模式的优缺点 

      优点

·         最安全,在启用appendfsync always(有写入的时候就持久化),任何已写入的数据都不会丢失,

          使用在启用appendfsync everysec(每秒持久化一次)也至多只会丢失1秒的数据。

·        AOF文件在发生断电等问题时也不会损坏,即使出现了某条日志只写入了一半的情况,

         也可以使用redis-check-aof工具轻松修复。

·        AOF文件易读,可修改,在进行了某些错误的数据清除操作后,只要AOF文件没有rewrite,就可以把AOF文件备份出来, 

          把错误的命令删除,然后恢复数据。

    ② 缺点

  •      AOF文件通常比RDB文件更大
  •     性能消耗比RDB高
  •    数据恢复速度比RDB慢

7.redis为什么可以这么快

   1.完全基于内存,数据存在内存中,类似于HashMap,HashMap的优势是查找和操作;

   2.数据结构简单,对数据操作也简单

   3.采用单线程,避免了不必要的上下文切换和多线程竞争条件,不存在锁问题

   4.使用的底层模型不同,底层实现方式和客户端之间的通信的应用协议不一样,redis直接构建了自己的VM机制,

     因为一般系统调用系统函数,会浪费一定时间去移动和请求

   5.使用多路(多个网络)I/0复用(复用同一个线程)模型,非阻塞I/O; 

      ① IO多路复用是指内核一旦发现进程指定的一个或者多个IO条件准备读取,它就通知该进程。

      ②可以让单个线程高效的处理多个连接请求,尽量减少网络IO的

      ③IO多路复用程序可以同时监听AE_REABLE和AE_WRITABLE两种事件,

          要是一个socket同时产生了AE_READABLEAE_WRITABLE两种事件,

        那么文件事件分派器优先处理AE_REABLE事件,然后才是AE_WRITABLE事件。

      ④非阻塞 IO 有个问题,那就是线程要读数据,结果读了一部分就返回了,线程如何知道何时才应该继续读。

          也就是当数据到来时,线程如何得到通知。写也是一样,如果缓冲区满了,写不完,

         剩下的数据何时才应该继续写,线程也应该得到通知。

     ④redis拿到事件后,线程就可以继续挨个处理相应的事件。处理完了继续过来轮询。于是线程就进入了一个死循环,

          我们把这个死循环称为事件循环,一个循环为一个周期。

     ⑤时间消耗,主要是利用select,poll,epoll同时监察多个流的I/O时间能力,在空闲的时候,会把当前线程阻塞掉

          1. epoll 没有最大并发连接的限制,上限是最大可以打开文件的数目,这个数字一般远大于 2048,

             一般来说这个数目和系统内存关系很大  ,具体数目可以 cat /proc/sys/fs/file-max 察看。


           2. 效率提升, Epoll 最大的优点就在于它只管你“活跃”的连接 ,而跟连接总数无关,

               因此在实际的网络环境中,Epoll 的效率就会远远高于 select 和 poll 。


          3. 内存拷贝, Epoll 在这点上使用了“共享内存 ”,这个内存拷贝也省略了

 

   6.设想一下如下场景:有100万个客户端同时与一个服务器进程保持着TCP连接。而每一时刻,

    通常只有几百上千个TCP连接是活跃的(事实上大部分场景都是这种情况)。如何实现这样的高并发?

      epoll的设计和实现与select完全不同。epoll通过在Linux内核中申请一个简易的文件系统

           (文件系统一般用什么数据结构实现?B+树)。把原先的select/poll调用分成了3个部分:
           1)调用epoll_create()建立一个epoll对象(在epoll文件系统中为这个句柄对象分配资源)
           2)调用epoll_ctl向epoll对象中添加这100万个连接的套接字
           3)调用epoll_wait收集发生的事件的连接
              如此一来,要实现上面说是的场景,只需要在进程启动时建立一个epoll对象,然后在需要的时候向

             这个epoll对象中添加或者删 除连接。同时,epoll_wait的效率也非常高,因为调用epoll_wait时,

            并没有一股脑的向操作系统复制这100万个连接的句柄数据,内核也不需要去遍历全部的连接。

     原文:https://blog.csdn.net/wxy941011/article/details/80274233

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值