在我们日常的Java Web开发中,无不都是使用数据库来进行数据的存储,由于一般的系统任务中通常不会存在高并发的情况,所以这样看起来并没有什么问题,可是一旦涉及大数据量的需求,比如一些商品抢购的情景,或者是主页访问量瞬间较大的时候,单一使用数据库来保存数据的系统会因为面向磁盘,磁盘读/写速度比较慢的问题而存在严重的性能弊端,一瞬间成千上万的请求到来,需要系统在极短的时间内完成成千上万次的读/写操作,这个时候往往不是数据库能够承受的,极其容易造成数据库系统瘫痪,最终导致服务宕机的严重生产问题。
NOSQL 技术
Not Only SQL,为了克服上述的问题,Java Web项目通常会引入NoSQL技术,这是一种基于内存的数据库,并且提供一定的持久化功能。
Redis和MongoDB是当前使用最广泛的NoSQL,而就Redis技术而言,它的性能十分优越,可以支持每秒十几万次的读/写操作,其性能远超数据库,并且还支持集群、分布式、主从同步等配置,原则上可以无限扩展,让更多的数据存储在内存中,更让人欣慰的是它还支持一定的事务能力,这保证了高并发的场景下数据的安全和一致性。
Redis 在 Java Web 中的应用
Redis 在 Java Web 主要有两个应用场景:
1. 存储 缓存 用的数据;
2. 需要高速读/写的场合使用它快速读/写;
在日常对数据库的访问中,读操作的次数远超写操作,比例大概在 1:9 到 3:7,所以需要读的可能性是比写的可能大得多的。当我们使用SQL语句去数据库进行读写操作时,数据库就会去磁盘把对应的数据索引取回来,这是一个相对较慢的过程。
如果我们把数据放在 Redis 中,也就是直接放在内存之中,让服务端直接去读取内存中的数据,那么这样速度明显就会快上不少,并且会极大减小数据库的压力,但是使用内存进行数据存储开销也是比较大的,限于成本的原因,一般我们只是使用 Redis 存储一些常用和主要的数据,比如用户登录的信息等。
一般而言在使用 Redis 进行存储的时候,我们需要从以下几个方面来考虑:
业务数据常用吗?命中率如何?
该业务数据是读操作多,还是写操作多?
业务数据大小如何?
在考虑了这些问题之后,如果觉得有必要使用缓存,那么就使用它!使用 Redis 作为缓存的读取逻辑如下图所示:
![](https://img6.php1.cn/3cdc5/9a17/78c/84e5695acee0387f.png)
为什么使用NoSQL ?
今天我们可以通过第三方平台(如:Google,Facebook等)可以很容易的访问和抓取数据。用户的个人信息,社交网络,地理位置,用户生成的数据和用户操作日志已经成倍的增加。我们如果要对这些用户数据进行挖掘,那SQL数据库已经不适合这些应用了,NoSQL数据库的发展也能很好的处理这些大的数据。
KV型NoSql(代表----Redis)
KV型NoSql顾名思义就是以键值对形式存储的非关系型数据库,是最简单、最容易理解也是大家最熟悉的一种NoSql,因此比较快地带过。Redis、MemCache是其中的代表,Redis又是KV型NoSql中应用最广泛的NoSql,KV型数据库以Redis为例,最大的优点我总结下来就两点:
数据基于内存,读写效率高
KV型数据,时间复杂度为O(1),查询速度快
因此,KV型NoSql最大的优点就是高性能,利用Redis自带的BenchMark做基准测试,TPS可达到10万的级别,性能非常强劲。同样的Redis也有所有KV型NoSql都有的比较明显的缺点:
只能根据K查V,无法根据V查K
查询方式单一,只有KV的方式,不支持条件查询,多条件查询唯一的做法就是数据冗余,但这会极大的浪费存储空间
内存是有限的,无法支持海量数据存储
同样的,由于KV型NoSql的存储是基于内存的,会有丢失数据的风险
综上所述,KV型NoSql最合适的场景就是缓存的场景:
读远多于写
读取能力强
没有持久化的需求,可以容忍数据丢失,反正丢了再查询一把写入就是了
NoSQL特点
解耦
1、方便扩展(数据之间没有关系,很好扩展! )
2、大数据量高性能(Redis一秒写8万次,读取11万, NoSQL的缓存记录级,是一种细粒度的缓存,性能会比较高!)
3、数据类型是多样型的! (不需要事先设计数据库!随取随用!如果是数据量十分大的表,很多人就无法设计了!)
![](https://img6.php1.cn/3cdc5/9a17/78c/49db76a319d91002.png)
NoSQL的四大分类
KV键值对:
新浪: Redis
美团: Redis +Tait
阿里、百度: Redis + memcache
文档型数据库(bson格式和json一样) :
MongoDB (一般必须要掌握)o MongoDB是一个基于分布式文件存储的数据库, C++编写,主要用来处理大量的文档!oMongoDB是一个介于关系型数据库和非关系型数据中中间的产品! MongoDB是非关系型数据库中功能最丰富,最像关系型数据库的!
ConthDB
列存储数据库:
图关系数据库:
![](https://img6.php1.cn/3cdc5/9a17/78c/720bc24d59854f9a.png)
他不是用来存图形的,存放的是关系,比如朋友圈社交网络,广告推荐!
Redis入门
概述
Redis是什么?
Redis ( Remote Dictionary Server ) ,即远程字典服务!
是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API
基本的数据结构,例如以下几种:
String: 字符串
Hash: 散列
List: 列表
Set: 集合
Sorted Set: 有序集合
Redis能干嘛?
1、内存存储、持久化,内存中是断电即失、所以说持久化很重要(rdb, aof )
2、效率高,可以用于高速缓存
3、发布订阅系统
4、地图信息分析
5、计时器、计数器(浏览量!)
特性
1、多样的数据类型
2、持久化
3、集群
4、事务
Redis 的安装(windows)
访问地址:
https://github.com/ServiceStack/redis-windows/tree/master/downloads
![](https://img6.php1.cn/3cdc5/9a17/78c/7451da4b41fd7685.png)
把 Redis 下载下来后找到一个合适的地方解压,就能得到如下图所示的目录(这里空格被替换成了%20...):
![](https://img6.php1.cn/3cdc5/9a17/78c/c0d3f5f55cd9e692.png)
为了方便启动,我们在该目录下新建一个 startup.cmd 的文件,然后将以下内容写入文件:
redis-server redis.windows.conf
这个命令其实就是在调用 redis-server.exe 命令来读取 redis.window.conf 的内容,我们双击刚才创建好的 startup.cmd 文件,就能成功的看到 Redis 启动:
![](https://img6.php1.cn/3cdc5/9a17/78c/6ce8e70888a58df2.png)
① Redis 当前的版本为 3.0.503;
② Redis 运行在 6379 端口;
③ Redis 进程的 PID 为 14748;
④ 64 位。
我们可以打开同一个文件夹下的 redis-cli.exe 文件,这是 Redis 自带的一个客户端工具,它可以用来连接到我们当前的 Redis 服务器,我们做以下测试:
![](https://img6.php1.cn/3cdc5/9a17/78c/68324305358fc4af.png)
Redis 的安装(Linux)
[root@misayaq jiaqi]# mv redis-6.0.9.tar.gz opt
[root@misayaq jiaqi]# cd opt/
[root@misayaq opt]# ls
containerd redis-6.0.9.tar.gz rh
[root@misayaq opt]# tar -zxvf redis-6.0.9.tar.gz
![](https://img6.php1.cn/3cdc5/9a17/78c/b323ead93864ac0f.png)
基本的环境安装
![](https://img6.php1.cn/3cdc5/9a17/78c/55271fc395e2f7b3.png)
redis默认安装路径 usr/local/bin
![](https://img6.php1.cn/3cdc5/9a17/78c/1a9b8cfe639d106e.png)
将redis配置文件 复制到当前目录下
![](https://img6.php1.cn/3cdc5/9a17/78c/330514f8cf828833.png)
redis默认不是后台启动的 需要修改配置文件
![](https://img6.php1.cn/3cdc5/9a17/78c/7c7bb2df96a7ca7c.png)
启动redis服务
![](https://img6.php1.cn/3cdc5/9a17/78c/88952f5551d70a43.png)
测试连接 使用 redis-cli
![](https://img6.php1.cn/3cdc5/9a17/78c/fd364eb6a0698ff8.png)
查看进程
![](https://img6.php1.cn/3cdc5/9a17/78c/80c01a7c27a089f7.png)
如何关闭Redis服务?shutdown
![](https://img6.php1.cn/3cdc5/9a17/78c/c8a5c5027b361b4b.png)
再次查看进程
![](https://img6.php1.cn/3cdc5/9a17/78c/6ac4687146127122.png)
后面我们会使用单机多redis集成
常遇报错:
报错1:/bin/sh: cc: command not found
[root@master redis-6.0.1]# make
……
make[3]: cc: Command not found
make[3]: *** [net.o] Error 127
make[3]: Leaving directory `/root/redis-6.0.1/deps/hiredis'
make[2]: *** [hiredis] Error 2
make[2]: Leaving directory `/root/redis-6.0.1/deps'
make[1]: [persist-settings] Error 2 (ignored)
CC adlist.o
/bin/sh: cc: command not found
make[1]: *** [adlist.o] Error 127
make[1]: Leaving directory `/root/redis-6.0.1/src'
make: *** [all] Error 2
解决办法:
报错2:server.c:xxxx:xx: error: ‘xxxxxxxx’ has no member named ‘xxxxx’
[root@master redis-6.0.1]# make
……
server.c:5101:19: error: ‘struct redisServer’ has no member named ‘sofd’
if (server.sofd > 0)
^
server.c:5102:94: error: ‘struct redisServer’ has no member named ‘unixsocket’
serverLog(LL_NOTICE,"The server is now ready to accept connections at %s", server.unixsocket);
^
server.c:5103:19: error: ‘struct redisServer’ has no member named ‘supervised_mode’
if (server.supervised_mode == SUPERVISED_SYSTEMD) {
^
server.c:5104:24: error: ‘struct redisServer’ has no member named ‘masterhost’
if (!server.masterhost) {
^
server.c:5117:15: error: ‘struct redisServer’ has no member named ‘maxmemory’
if (server.maxmemory > 0 && server.maxmemory <1024*1024) {
^
server.c:5117:39: error: ‘struct redisServer’ has no member named ‘maxmemory’
解决办法:
# 查看gcc版本是否在5.3以上,centos7.6默认安装4.8.5
gcc -v
# 升级 gcc到5.3及以上,如下:
# 升级到 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 "source opt/rh/devtoolset-9/enable" >>/etc/profile
# 这样退出shell重新打开就是新版的gcc了
# 以下其他版本同理,修改devtoolset版本号即可。
其他命令
# 编译出错时,清出编译生成的文件
make distclean
# 编译安装到指定目录下
make PREFIX=/usr/local/redis install
# 卸载
make uninstall
测试性能
redis-benchmark一个压力测试工具!官方自带的性能测试工具!
压测命令:
redis-benchmark -h 127.0.0.1 -p 6379 -c 50 -n 10000
![](https://img6.php1.cn/3cdc5/9a17/78c/634b5dfaba477954.png)
简单测试:
# 卸载
redis-benchmark -h 127.0.0.1 -p 6379 -c 50 -n 10000
![](https://img6.php1.cn/3cdc5/9a17/78c/fbea8761b4408a41.png)
如何查看这些分析呢?
![](https://img6.php1.cn/3cdc5/9a17/78c/1d570d32bd303f17.png)
基础的知识
redis具有16个数据库
![](https://img6.php1.cn/3cdc5/9a17/78c/b009b5bfd1c03e60.png)
默认使用的是第0个
可以使用select (index)进行切换数据库 ,DBSIZE查看数据库大小
127.0.0.1:6379> clear
127.0.0.1:6379> select 3 #切换数据库
OK
127.0.0.1:6379[3]> DBSIZE #查看db大小
(integer) 0
![](https://img6.php1.cn/3cdc5/9a17/78c/ab5a512b80d7c2db.png)
查看数据库所有的key----->keys *
127.0.0.1:6379[3]> keys *
1) "name"
清空数据库 flushall(清空所有db) flushdb(清空当前db)
127.0.0.1:6379[3]> flushdb
OK
127.0.0.1:6379[3]> keys *
(empty array)
Redis是单线程的
Redis是基于内存操作, CPU不是Redis性能瓶颈, Redis的瓶颈是根据机器的内存和网络带宽,既然单线程容易实现,而且CPU不会成为瓶颈,那就顺理成章地采用单线程的方案了
Redis为什么单线程还这么快
redis是将所有的数据全部放在内存中的,所以说使用单线程去操作效率就是最高的,多线程(CPU上下文会切换:耗时的操作 ) ,对于内存系统来说,如果没有上下文切换效率就是最高的!多次读写都是在一个CPU上的,在内存情况下,这个就是最佳的方案!
1、完全基于内存,绝大部分请求是纯粹的内存操作,非常快速。数据存在内存中,类似于HashMap,HashMap的优势就是查找和操作的时间复杂度都是O(1);
2、数据结构简单,对数据操作也简单,Redis中的数据结构是专门进行设计的;
3、采用单线程,避免了不必要的上下文切换和竞争条件,也不存在多进程或者多线程导致的切换而消耗 CPU,不用去考虑各种锁的问题,不存在加锁释放锁操作,没有因为可能出现死锁而导致的性能消耗;
4、使用多路I/O复用模型,非阻塞IO;这里“多路”指的是多个网络连接,“复用”指的是复用同一个线程
5、使用底层模型不同,它们之间底层实现方式以及与客户端之间通信的应用协议不一样,Redis直接自己构建了VM 机制 ,因为一般的系统调用系统函数的话,会浪费一定的时间去移动和请求;
文章来自于对《狂神说Redis》的总结。