在正式的走入 Redis 的世界之前,我想和你一起探讨下 Redis 的前世,为什么会有 Redis 的出现?是什么促成 Redis 的诞生?
在早期,数据库等概念还没诞生的时候,【数据以文件的形式】存储在磁盘上,例如 xxx.txt 文件,程序员通过 awk/grep/Java 等方式对数据进行访问。然而,随着文件的增大,这些方式对数据的访问变慢,磁盘 I/O 成为限制。
【Tips】常识补充
从磁盘读取数据,涉及到两个时间:
- 寻址时间:ms 级
- 带宽:G/M 级
从内存读取数据,涉及到两个时间:
- 寻址时间:nm 级
- 带宽:很大,DDR4 3200可以达到25.6G/s
寻址:磁盘在寻址上比内存慢了10万倍
I/O Buffer
- 磁盘由多个盘片组成,每个盘片有两个盘面
- 盘面中一圈圈灰色同心圆为一条条磁道,从圆心向外画直线, 将磁道划分为若干个扇区
- 扇区是磁盘的最小组成单位,通常为512个字节,此时带来一个巨大的开销,即维护扇区的索引
- 操作系统读取磁盘数据时,无论你实际读多少,都是【以4K为单位从磁盘读取】
随着技术的发展,关系型数据库随之诞生,由于操作系统读取磁盘时以4K为单位,关系型数据库在设计时,也以4K为单位划分底层磁盘块。
同时,为了快速检索数据,关系型数据库还维护了索引,同样以4K的磁盘块存储,而对于索引,又引入了 B+ 树的数据结构,实现了索引查找的平衡。
【Tips】关系型数据库
关系型数据库建表时:必须给出 schema
- 字段类型
- 字段宽度
关系型数据库,倾向于【行级存储】
表很大时,性能下降?
- 如果表有索引,在对数据进行增、删、改操作时,由于需要对索引进行维护,会导致操作变慢
- 查询速度
- 一个或少量查询依然很快
- 高并发时,由于受磁盘带宽的影响,很导致查询速度变慢
上述着重描述的是基于磁盘的数据库,其实市场上还存在着【基于内存的数据库】,如 SAP 的 HANA 数据库,作为内存数据库,SAP HANA 可以实时运行 PB 级的复杂 ERP 计算,有兴趣的小伙伴可以进一步了解(超级贵)。
【Tips】数据在内存与磁盘中的体积不一样
- 数据在磁盘中除了数据本身外,还有数据的元数据,因此在磁盘中会发生膨胀
信息化的不断前进,产生了大量的数据资产,基于磁盘的数据库廉价但效率偏低,基于内存的数据库效率高但价格昂贵,在这样的环境下,一种折中的方案应运而生【缓存】,典型的就是 Memcached 和 Redis。
【Tips】制约计算机的两个基础设施
- 冯诺依曼体系的硬件结构
- 以太网和 TCP/IP 的网络架构
分享一个数据库网站:https://db-engines.com/en/ranking
引用 http://redis.cn/的一段介绍:
Redis 是一个开源(BSD许可)的,内存中的数据结构存储系统,它可以用作数据库、缓存和消息中间件。
它支持多种类型的数据结构,如字符串(strings), 散列(hashes), 列表(lists), 集合(sets), 有序集合(sorted sets) 与范围查询, bitmaps, hyperloglogs 和 地理空间(geospatial) 索引半径查询。
Redis 内置了复制(replication),LUA脚本(Lua scripting), LRU驱动事件(LRU eviction),事务(transactions) 和不同级别的磁盘持久化(persistence), 并通过 Redis哨兵(Sentinel)和自动分区(Cluster)提供高可用性(high availability)。
众所周知,Redis 是一个 <K,V> 型的数据库,同时官方的介绍中又提到它支持多种类型的数据结构,这里的数据结构是针对 Value 的。
由此,可以引出 Redis 的数据结构,key 指向 value,value 拥有多种类型,每种类型又有多种的操作。
简单的介绍完 Redis ,我们来想一下 Redis 与 Memcached 的区别,为什么在 Memcached 出现后又有 Redis 的诞生呢?
曾经看到过一段话,这世界上大概有3种数据表示:
在 Memcached 中,数据同样是以 <K,V> 的形式存储的,但是 Value 没有类型的概念,它的 Value 可以用 JSON 表示出很复杂的数据结构。
当客户端向缓存请求取出 <K,V> 中 Value 的某一个元素时:
下面演示下在 Linux 服务器上安装 Redis 的方式:
1. yum install wget 2. wget https://github.com/redis/redis/archive/7.0.4.tar.gz # 下载安装包 3. tar xf 7.0.4.tar.gz 4. yum install gcc # 安装依赖 5. cd redis-7.0.4 6. make # 编译 7. make install PREFIX="/opt/redis" # 安装 8. vi /etc/profile # 配置环境变量 9. export REDIS_HOME=/opt/soft/redis-7.0.4 export PATH=$PATH:$JAVA_HOME/bin:$REDIS_HOME/bin source /etc/profile 10. cd utils 11. vi install-server.sh # 注释掉如下部分 #bail if this system is managed by systemd #_pid_1_eoe="$(readlink -f /proc/1/exe)" #if [ "${_pid_1_exe##*/}" = systemd ] #then # echo "This systems seems to use systemd." # echo "Please take a look at the provided example service unit files in this directory, and adapt and install them. Sorry!" # exit 1 #fi 12. ./install-server.sh # 将redis安装成Linux服务 Welcome to the redis service installer This script will help you easily set up a running redis server Please select the redis port for this instance: [6379] Selecting default: 6379 Please select the redis config file name [/etc/redis/6379.conf] Selected default - /etc/redis/6379.conf Please select the redis log file name [/var/log/redis_6379.log] Selected default - /var/log/redis_6379.log Please select the data directory for this instance [/var/lib/redis/6379] Selected default - /var/lib/redis/6379 Please select the redis executable path [/opt/redis/bin/redis-server] Selected config: Port : 6379 Config file : /etc/redis/6379.conf Log file : /var/log/redis_6379.log Data dir : /var/lib/redis/6379 Executable : /opt/redis/bin/redis-server Cli Executable : /opt/redis/bin/redis-cli Is this ok? Then press ENTER to go on or Ctrl-C to abort. Copied /tmp/6379.conf => /etc/init.d/redis_6379 Installing service... Successfully added to chkconfig! Successfully added to runlevels 345! Starting Redis server... Installation successful! 13. systemctl status redis-6379 # 查看redis服务 ● redis_6379.service - LSB: start and stop redis_6379 Loaded: loaded (/etc/rc.d/init.d/redis_6379; bad; vendor preset: disabled) Active: inactive (dead) Docs: man:systemd-sysv-generator(8)
【Tips】小补充
- 一个物理机中可以有多个 redis 实例,通过 port 区分
- 可执行程序就一份在目录,但内存中未来的多个实例需要各自的配置文件,持久化目录等资源