实际上咱们使用Redis的初衷就是为了优化数据库,当咱们用户的行为增长了,咱们数据库的IO就增长了,Redis的数据是存储在内存中,而咱们的传统的数据的数据是存储在磁盘中,就存储在内存这一方面Redis就优化了数据的读取速度。本篇中聊一聊经常使用的Redis数据结构、不一样的存储数据带来的性能提高、经常使用的数据库优化手段html
【池化技术】:实现链接资源的复用(本质上是下降资源建立和销毁的开销),当咱们去连接数据库的会发送一个TCP请求到数据库上,若是使用池化技术,那就节省了不少时间,提高了性能。c++
【数据库自己层面的优化】:redis
【索引】:当没有索引的时候,咱们去查询数据,他会去扫描磁盘轨道,有了索引就至关于经过一个点直接进行定位,这样速度就快了不少shell
【数据量的传输】:咱们能够尽可能减小数据量的传输,少查询一些没必要要的数据,确定就提升性能。数据库
【数据库的读写分离】:若是没有作读写分离,每一个数据在进行事务操做的时候就会加锁,从而影响了查询的速度centos
数据库的发展历史是->关系型数据库->NOSQL->NEWSQL数组
【KV数据库】:缓存
- 键值形式
- 数据存储在内存中(没法支持海量存储)
- 时间复杂度是O(1)
【列式数据库】:好比一些实时报表、监控数据等场景适合安全
- 统计数据速度快(相同的数据存储在一块儿)
- 事务处理速度慢(须要在加载不一样的存储块中数据进行处理,由于处理的是一条数据中的不用类型)
【 文档型】:把相关的一系列数据存储在一个文档中,日常咱们查询用户、文章、用户评论三张表才能获得一个完整的信息,如今把这些都存储在一块儿,一下就能检索出来。bash
【NEWSQL】:NOSQL的下一个阶段衍生出来的一种思想;拥有传统的关系型数据库的的核心特性,也拥有NOSQL的特性
【图形数据库】:传统数据库中,可能在一个给定实体中有不少关系,好比一个专家评分,牵扯到标书表,招标表、投标表、专家组长表、专家类型表等等,而在图形数据库中这些就抽象成一个个节点,建立相应的关系便可,这些组合成专家评分的数据所需的表只是节点集中的节点。
Redis已是一个众所周知的技术了,这里就不讲他的安装以及介绍他的。安装的时候有一个坑的地方就是咱们的GCC必须是5.3版本以上,要不安装Redis就会报错。用YUM默认是4.*,使用如下命令能够升级他的版本到9,就能够解决报错的问题
- # 升级到gcc 9.3:
- yum -y install centos-release-scl
- yum -y install devtoolset-9-gcc devtoolset-9-gcc-c++ devtoolset-9-binutils
- scl enable devtoolset-9 bash
- # 须要注意的是scl命令启用只是临时的,退出shell或重启就会恢复原系统gcc版本。
- # 若是要长期使用gcc 9.3的话:
- echo -e "\nsource /opt/rh/devtoolset-9/enable" >>/etc/profile
这里用Jemeter压测了两个接口,一个是从数据库直接读取数据的,另一个是把数据缓存在Redis中而后读取的,咱们发现使用Redis查询数据的接口每秒的吞吐量多了一倍。因此这是咱们使用他的一个缘由。
![]()
【数据类型】
String:Redis是用c开发的,C中并无string类型,因此他的底层其实是使用了一个动态的sds(由于咱们string的长度是不固定的,因此他用了一个动态的结构),在sds的结构中才使用了一个char数组对咱们的string进行存储
【常见命令】:
这里有一些特殊的命令
incr 和 decr:这个命令是原子的,他能够保证线程安全的特性。由于Redis是单线程的,因此他能够保证原子性,那咱们就能够用这个来作分布式id。
setnx: 咱们能够用这个特性作咱们的分布式锁,咱们知道锁的特性是排他的,那当返回0的时候,则证实有一个数据已经存在了,这样就巧妙的使用了这个功能。
【使用场景】:
【缓存应用】:缓存热点数据
【全局id】:使用incr 进行递增
【限流】:(好比设置一个key为一个用户id,而后value的值的过时时间设置60s(根据本身须要),而后配合incr 进行递增,当value的数值大于咱们能接受的数据,咱们就关闭访问通道)
【分布式session】:他等因而一个全局的视角,第三方的,因此咱们的全部微服务均可以去这里获取数据。
List:是一个有序,且可重复的字符串链表,是一个栈+堆结构,能够支持非or阻塞的FIFO/LIFO,
简而言之:他是一个Quicklist结构(就是个双向链表,每一个节点中存储的是一个ziplist(压缩列表,前面的线程篇章咱们讲了cpu的作高速缓存的时候一次读取的一个缓存行的数据,为了防止伪共享,若是当前的位置不是满的,则自动补0,压缩列表就是让每一个位置都存储有效的数据,而不是用0代替,这就让性能大大提高,让cpu每次读取的都是有效的数据,而且节省内存))
【常见命令】
【使用场景】:
【消息队列】:咱们使用lpush入队一个数据,用rpop从右边出队一个数据
【发送红包场景】:咱们在发送前面计算好红包的个数和金额,用lpush入队,而后抽取红包的时候使用rpop出队。其实秒杀也行,咱们把库存数据直接放在Redis中,而后仍是相同的操做
hash:当hash个数小于512的时候,以及全部的数值都小于64个字节的时候,默认状况下会经过ziplist存储多个数据元素,由于数据量小的时候,使用ziplist去存储能够节省内存空间,而且检索不会太慢,可是超过这个阈值的时候,他就会采用hashtable进行存储,由于hashtable的读写时间复杂度是o(1)
【常见命令】
【使用场景】:
购物车、商品详情数据、用户信息、计数器、so on
Set:是一个无序,而且惟一的集合 (https://www.cnblogs.com/xinhuaxuan/p/9256738.html) 若是set中存储的都会整形他都会使用intset进行存储,不然用hashtable进行存储
【使用场景】:
用户画像、标签管理
zset:他是一个有序的的集合,在每一个value前面维护了一个score,基于每一个score进行排序。看下面的命令咱们发现,能够经过key和score进行检索数据,他的底层其实是使用了hashtable和跳表进行存储的,若是我想经过key去检索数据,那就使用hashtable进行检索(他的时间复杂度是0(1)),而当咱们使用score去检索的话,那就使用跳表进行检索(咱们知道跳表有等级,当咱们要检索某个数据的时候,他不在某个等级的话,就会跳到下一个等级去进行检索,他的时间复杂度是o(log)),实际上无论使用跳表仍是hashtable他们都是一个指针指向原数据,这样就能够防止内存浪费
【常见命令】
【使用场景】:
用户点赞排行、热点话题排行,由于每一个数据中都有score,用score咱们就能够计算出排行