既然要学习 Redis,那么就先了解一下什么是 NoSQL 吧。
NoSQL 的全称是 Not Only SQL,不仅是 SQL。
什么是 NoSQL
NoSQL 泛指非关系型数据库,伴随着 web2.0 互联网的诞生。传统的关系型数据库早已很难对付 web2.0 时代,尤其是超大规模的高并发舍弃,暴露出来很多难以克服的问题,NoSQL 在当今大数据环境下发展的十分迅速,Redis 是发展最快的。
很多的数据类型用户的个人信息,社交网络,地理位盾。这些数据类型的存储不需要一个固定的格式!不需要多余的操作就可以横向扩展的!
比如 Java 中的 Map<String, Object> 使用是键值对的方式来控制的,它是 NoSQL 的一种表现形式。
特点
- 方便扩展
- 数据之间没有关系
- 大数据量,高性能
- 一秒写 8 万次,读取 11 万,NoSQL 的缓存记录级,是一种细粒度的缓存,性能会比较高。
- 数据类型多样化
- 不需要事先设计数据库,随取随用,如果是数据量十分大的表,很多人就无法设计了!
- 传统 RDBMS 和 Nosql
- 传统的 RDBMS
- 结构化组织
- SQL
- 数据和关系都在单独的表中
- DDL、DML、DCL、DQL
- 严格的一致性
- 基础的事务
- ……
- Nosql
- 没有固定的查询语言
- 键值对存储,列存储,文档存储,图形数据库(社交关系)
- 最终一致性,
- CAP 定理和 BASE (异地多活)初级架构师!(狂神理念:只要学不死,就往死里学!)
- 高性能,高可用,高可扩
- ……
- 传统的 RDBMS
目前,NoSQL 和 RDBMS 结合起来使用,使性能达到最佳。
NoSQL 的四大分类
KV键值对:
- 新浪:Redis
- 美团:Redis +Tair
- 阿里、百度:Redis + memecache
文档型数据库 ( bson 格式和 json 一样)∶
- MongoDB (一般必须要掌握)
- MongoDB 是一个基于分布式文件存储的数据库,C++编写,主要用来处理大量的文档!
- MongoDB 是一个介于关系型数据库和非关系型数据中中间的产品!MongoDB是非关系型数据库中功能最丰富,最像关系型数据库的!
- CouchDB
列存储数据库
- HBase
- 分布式文件系统
图关系数据库
图关系数据库存的是关系,而不是图形。
Redis 是什么
Redis ( Remote Dictionary Server ),即远程字典服务!
是一个开源的使用 ANSl C 语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value 数据库,并提供多种语言的 API。
Redis 能做什么
- 内存存储、持久化(rdb、aof)
- 效率高,可以用于高速缓存
- 发布订阅系统
- 地图信息分析
- 计时器、计数器
- …
安装 Redis
Redis 的安装有 Windows 版和 Linux 版,Windows 版解压直接运行 redis-server 即可。Linux 版只提供源代码,需要自己通过编译源代码的方式来安装。
我在学习的时候用的是 Linux 版,安装时候有几个步骤。
1、使用 wget 命令去下载,如果提示 -bash: wget: command not found
,则需要安装一下 wget,然后再下载。
31 yum -y install wget
33 wget https://download.redis.io/releases/redis-6.2.5.tar.gz
2、解压,进入目录
tar zxvf redis-6.2.5.tar.gz
cd redis-6.2.5
3、安装一下 c++ 的编译器,如果你有,就不用装。
yum -y install gcc-c++
4、编译并安装
make MALLOC=libc
make install
这样,Redis 就安装完成了。
启动 Redis
Redis 的默认的安装位置是在 /usr/local/bin
,里面有如下信息。
[root@localhost bin]# ls
redis-benchmark redis-check-aof redis-check-rdb redis-cli redis-sentinel redis-server
Redis 的配置文件,默认是保存在解压文件中。建议将配置文件复制到上面提到的路径当中。
由于 Redis 默认不是以后台运行的,所以要在配置文件中找到以下属性并配置成 yes。
################################# GENERAL #####################################
# By default Redis does not run as a daemon. Use 'yes' if you need it.
# Note that Redis will write a pid file in /var/run/redis.pid when daemonized.
# When Redis is supervised by upstart or systemd, this parameter has no impact.
daemonize yes
然后先运行服务端,再运行客户端,输入 ping 命令看看能不能联通,如果返回 PONG,说明连接成功了。
[root@localhost bin]# ./redis-server redis_conf/redis.conf
[root@localhost bin]# redis-cli
127.0.0.1:6379> ping
PONG
127.0.0.1:6379>
查看正在运行的 Redis 进程
[root@localhost ~]# ps -ef | grep redis
root 1372 1 0 16:49 ? 00:00:00 ./redis-server 127.0.0.1:6379
root 1376 1299 0 16:49 pts/0 00:00:00 redis-cli
root 1400 1382 0 16:52 pts/1 00:00:00 grep --color=auto redis
小试一下
试用 set 和 get 命令,保存一些信息并获取。
127.0.0.1:6379> set name xiaohehe
OK
127.0.0.1:6379> get name
"xiaohehe"
试用 redis-benchmark 命令来测试 redis 的单机性能,redis 的性能会受到服务器的制约,来感受一下速度。
[root@localhost ~]# redis-benchmark -h localhost -p 6379 -c 100 -n 100000
比如,我们看一下 LPUSH 的处理请求。
====== LPUSH ======
100000 requests completed in 3.43 seconds
100 parallel clients
3 bytes payload
keep alive: 1
host configuration "save": 3600 1 300 100 60 10000
host configuration "appendonly": no
multi-thread: no
Latency by percentile distribution:
0.000% <= 0.991 milliseconds (cumulative count 2)
50.000% <= 2.287 milliseconds (cumulative count 50170)
75.000% <= 2.895 milliseconds (cumulative count 75016)
87.500% <= 3.471 milliseconds (cumulative count 87608)
93.750% <= 3.951 milliseconds (cumulative count 93756)
96.875% <= 4.351 milliseconds (cumulative count 96879)
98.438% <= 4.695 milliseconds (cumulative count 98458)
99.219% <= 5.031 milliseconds (cumulative count 99224)
99.609% <= 5.399 milliseconds (cumulative count 99610)
99.805% <= 5.847 milliseconds (cumulative count 99805)
99.902% <= 6.303 milliseconds (cumulative count 99903)
99.951% <= 10.199 milliseconds (cumulative count 99952)
99.976% <= 10.535 milliseconds (cumulative count 99976)
99.988% <= 10.703 milliseconds (cumulative count 99988)
99.994% <= 10.791 milliseconds (cumulative count 99994)
99.997% <= 10.839 milliseconds (cumulative count 99997)
99.998% <= 10.871 milliseconds (cumulative count 99999)
99.999% <= 10.911 milliseconds (cumulative count 100000)
100.000% <= 10.911 milliseconds (cumulative count 100000)
测试 LPUSH 时,在 请求次数为 100000 ,每次写入 3 个字节的数据,100个客户端同时并发的情况下,花费了 10.9 ms,如果不是在虚拟机也许会更快。
Redis 基础知识和基本命令
Redis 默认有 16 个数据库,可以在配置文件中查看并修改数据库个数,默认使用的数据库是第 0 个。
# Set the number of databases. The default database is DB 0, you can select
# a different one on a per-connection basis using SELECT <dbid> where
# dbid is a number between 0 and 'databases'-1
databases 16
select 命令是切换数据库。
127.0.0.1:6379> select 4 # 切换到4号数据库
OK
127.0.0.1:6379[4]>
dbsize 查看数据库大小,每一组键值对占用一个单位。
127.0.0.1:6379[4]> set name xiaohehe
OK
127.0.0.1:6379[4]> get name
"xiaohehe"
127.0.0.1:6379[4]> dbsize
(integer) 1
查看数据库中的键
127.0.0.1:6379[4]> keys *
1) "name"
127.0.0.1:6379[4]>
flushdb 清空当前数据库
127.0.0.1:6379[4]> flushdb
OK
127.0.0.1:6379[4]> dbsize
(integer) 0
flushall 清空全部数据库
127.0.0.1:6379[4]> flushall
OK
127.0.0.1:6379[4]> select 0
OK
127.0.0.1:6379> DBSIZE
(integer) 0
exists 判断当前的 key 是否存在
127.0.0.1:6379> exists name
(integer) 0
move 移除当前的 key 到其它数据库中
127.0.0.1:6379> set name2 xiaohehe
OK
127.0.0.1:6379> move name2 2
(integer) 1
127.0.0.1:6379> select 2
OK
127.0.0.1:6379[2]> get name2
"xiaohehe"
expire 设置 key 的过期时间,单位是秒
127.0.0.1:6379[2]> expire name2 10
(integer) 1
ttl 查看 key 的剩余时间,单位是秒,-1 为永久,-2 为不存在。
127.0.0.1:6379> ttl name2
(integer) 6
127.0.0.1:6379> ttl name2
(integer) 3
127.0.0.1:6379> ttl name2
(integer) 1
127.0.0.1:6379> ttl name2
(integer) 0
127.0.0.1:6379> ttl name2
(integer) -2
type 查看 key 中所保存的值的类型。
127.0.0.1:6379> set age 20
OK
127.0.0.1:6379> type age
string
Redis 是单线程的
为什么?
明白 Redis 是很快的,因为 Redis 是基于内存操作,CPU 并不是 Redis 性能瓶颈,真正的 Redis 的性能瓶颈是在机器的内存和网络带宽,既然可以使用单线程来实现,就使用单线程了。
QPS(Query Per Second),QPS 其实是衡量吞吐量(Throughput)的一个常用指标,就是说服务器在一秒的时间内处理了多少个请求 —— 我们通常是指 HTTP 请求,显然数字越大代表服务器的负荷越高、处理能力越强。作为参考,一个有着简单业务逻辑(包括数据库访问)的程序在单核心运行时可以提供 50 - 100 左右的 QPS,即每秒可以处理 50 - 100 个请求。
Redis 是 C 语言写的,官方提供的数据为 100000+ 的 QPS,完全不比同样是使用 key-value 的 Memecache 差。
Redis 为什么很快
误区1∶高性能的服务器一定是多线程的?
误区2∶多线程一定比单线程效率高!
Redis 是将所有的数据全部放在内存中的,所以说使用单线程去操作效率就是最高的,由于多线程涉及到上下文切换,这对于内存系统来说就是浪费时间,如果没有上下文切换效率就是最高的!多次读写都是在一个 CPU 上的,在内存情况这个就是最佳的方案!
请勿发布违反中国大陆地区法律的言论,请勿人身攻击、谩骂、侮辱和煽动式的语言。