- NoSQL背景
- NoSQL简介
- NoSQL和关系型数据库对比
- Redis简介
- Redis下载安装配置(Linux环境)
- Redis优点
- Redis性能
- Redis常见命令
- Redis数据类型
- Redis的功能
- Redis发布/订阅
- Redis事务支持
- Redis主从复制(集群)
- Redis持久化
- Java操作Redis示例
- Redis总结
随着互联网Web网站的兴起,传统的关系数据库在应付Web网站,特别是超大规模和高并发的社交网络类型的Web纯动态网站已经显得力不从心,暴露出了很多难以克服的问题。例如:关系数据库为了降低数据冗余,保证数据约束性,在数据查询时不得不使用多个数据表之间的连接操作,这极大地降低了查询效率,不能够满足当前Internet的高实时性的要求。而非关系型数据库对并发的大规模访问有着效率上的优势,因此,非关系数据库是在具体应用背景下得到了迅速的发展。
NoSQL指的是非关系型的数据库。其实,NoSQL概念最早出现在1998年,当时的含义是反SQL技术革命运动,但并未引起太多的关注。直到2009年,NoSQL概念被来自Rackspace的EricEvans再次提出,这时的NoSQL已经不是单纯的反SQL运动,指的主要是非关系型的分布式数据库,并且不支持原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)的数据库设计模式。在亚特兰大举行的有关NoSQL的讨论会上,学者给出了NoSQL较为普遍的解释,即“非关系型的”。并且指出Key-Value存储和文档数据库是NoSQL的主要特点。
例如:
网上定票系统:扣钱和定票是一个事务,它需要有原子性即不能只运行扣钱不运行定票,符合原子性.这张票被多人同时在网上定,就会有先来的才定上这个票,后来定票的动作,如果发现票已卖出,(票的状态改变了,其它人通过网站访问这个数据,就会发现票已卖出符合一致性),就会回滚到不扣钱,票订不上的状态.符合隔离性。票被定了,在数据库里设置标志位,它就一直显示为卖出状态。符合持久性 |
---|
1:key-value存储2:最终一致性3:可拓展 |
---|
关系型数据库
优势: 1.擅长小数据量的处理 2.擅长复杂的SQL操作,可以进行Join等复杂查询 3.可以方便的生成各种数据对象,利用存储的数据建立窗体和报表,可视性好劣势: 1.很难进行分布式应用和大量数据的写入处理 2.为有数据更新的表做索引和结构变更 3.字段不固定的应用 4.对简单查询需要快速返回结果的处理 |
---|
NoSQL数据库
优势: 1.擅长大量数据的写入和读取 2.快速的查询响应,灵活的数据模型 3.数据结构变更或更新非常方便,不需要更改已有数据的数据结构 4.击碎了性能瓶颈,可以使执行速度变的更快劣势: 1.不提供复杂的API接口 2.一般仅提供key索引 3.不适合小数据的处理 4.现有产品的不够成熟,大多数产品都还处于初创期 |
---|
Redis(REmote DIctionary Server)是一个开源的使用ANSI C语言编写、是一个由Salvatore Sanfilippo写的key-value存储系统,支持网络、可基于内存亦可持久化的日志型、并提供多种语言的API。
Redis是一个key-value存储系统。和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash(哈希类型)。与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。
下载:
官网:https://redis.io/ |
---|
下载步骤:
安装(Linux版本下CentOS Linux release 7.3.1611 (Core))
在线安装:
1:查看系统版本:
cat /etc/redhat-release |
---|
2:进入到opt目录下、创建redis文件夹:
cd /opt/mkdir redis |
---|
3:进入/opt/redis/目录下,下载redis
wget http://download.redis.io/releases/redis-4.0.6.tar.gz |
---|
4:解压redis-4.0.6.tar.gz
tar -zvxf redis-4.0.6.tar.gz |
---|
5:在安装之前需要预装gcc、tcl
没有安装的小伙伴,需要安装,如果已经存在,则略过此步骤
查看安装gcc信息:gcc -v安装命令:mount /dev/cdrom /mntyum install gcc tcl -y |
---|
6:执行redis安装
make |
---|
7:切换到目录/usr下新建目录/usr/lksoft/redis
cd /usrmkdir lksoftcd lksoftmkdir redis |
---|
8:重新设置PREFIX
make PREFIX=/usr/lksoft/redis/ install |
---|
9:查看当前系统中端口使用情况
ss -tanl |
---|
10:将redis设置成服务(配置环境变量)
cd ./opt/redis/redis-4.0.6/srccp redis-sentinel /usr/lksoft/redis/bin/ |
---|
11:设置环境变量bash_profile
vim ~/.bash_profile |
---|
修改内容部分:export REDIS_HOME=/usr/lksoft/redisexport PATH=$PATH:$REDIS_HOME/bin |
---|
使文件生效source ~/.bash_profile |
---|
12:任何地方,都可以启动redis了
为了更说明,切换到根目录下cd /可以自动补全redis-server了 |
---|
13:将redis启动程序做成服务
切换到之前的redis目录:cd /opt/redis/redis-4.0.6/utils./install_server.sh 提示是否使用默认的6379端口,点击回车即可,使用默认Please select the redis port for this instance: [6379] 是否将redis的服务配置文件,放到[/etc/redis/6379.conf]下面,直接回车即可:Please select the redis config file name [/etc/redis/6379.conf] 是否将redis服务的日志文件,放到[/var/log/redis_6379.log]下面,直接回车即可:Please select the redis log file name [/var/log/redis_6379.log]是否将redis的数据,存放到[/var/lib/redis/6379]下面,直接回车即可:Please select the data directory for this instance [/var/lib/redis/6379]是否默认redis可执行的文件路径为[/usr/lksoft/redis/bin/redis-server],直接回车即可Please select the redis executable path [/usr/lksoft/redis/bin/redis-server] 然后显示的是设置的文件信息,直接回车即可。 |
---|
发现:Copied /tmp/6379.conf => /etc/init.d/redis_6379
14:修改启动的名称
cd /etc/init.d/mv redis_6379 redisd |
---|
15:启动redis
service redisd start发现已经启动需要停止服务:service redisd stop重新启动service redisd start查看目前系统使用端口情况:ss -tanl |
---|
16:测试连接redis
切换到根目录cd /查看客户端连接帮助redis-cli --help连接0号库redis-cli |
---|
在50个并发的情况下请求10W次,写的速度是11W次/s,读的速度是8.1w次/s |
---|
官网参考命令地址:https://redis.io/commands
exists(key):确认一个key是否存在del(key):删除一个keytype(key):返回值的类型keys(pattern):返回满足给定pattern的所有keyrandomkey:随机返回key空间的一个keyrename(oldname, newname):重命名keydbsize:返回当前数据库中key的数目expire:设定一个key的活动时间(s)ttl:获得一个key的活动时间select(index):按索引查询move(key, dbindex):移动当前数据库中的key到dbindex数据库flushdb:删除当前选择数据库中的所有keyflushall:删除所有数据库中的所有key |
---|
set(key, value):给数据库中名称为key的string赋予值valueget(key):返回数据库中名称为key的string的valuegetset(key, value):给名称为key的string赋予上一次的valuemget(key1, key2,…, key N):返回库中多个string的valuesetnx(key, value):添加string,名称为key,值为valuesetex(key, time, value):向库中添加string,设定过期时间timemset(key N, value N):批量设置多个string的值msetnx(key N, value N):如果所有名称为key i的string都不存在incr(key):名称为key的string增1操作incrby(key, integer):名称为key的string增加integerdecr(key):名称为key的string减1操作decrby(key, integer):名称为key的string减少integerappend(key, value):名称为key的string的值附加valuesubstr(key, start, end):返回名称为key的string的value的子串 |
---|
rpush(key, value):在名称为key的list尾添加一个值为value的元素lpush(key, value):在名称为key的list头添加一个值为value的 元素llen(key):返回名称为key的list的长度lrange(key, start, end):返回名称为key的list中start至end之间的元素ltrim(key, start, end):截取名称为key的listlindex(key, index):返回名称为key的list中index位置的元素lset(key, index, value):给名称为key的list中index位置的元素赋值lrem(key, count, value):删除count个key的list中值为value的元素lpop(key):返回并删除名称为key的list中的首元素rpop(key):返回并删除名称为key的list中的尾元素blpop(key1, key2,… key N, timeout):lpop命令的block版本。brpop(key1, key2,… key N, timeout):rpop的block版本。rpoplpush(srckey, dstkey):返回并删除名称为srckey的list的尾元素,并将该元素添加到名称为dstkey的list的头部 |
---|
sadd(key, member):向名称为key的set中添加元素membersrem(key, member) :删除名称为key的set中的元素memberspop(key) :随机返回并删除名称为key的set中一个元素smove(srckey, dstkey, member) :移到集合元素scard(key) :返回名称为key的set的基数sismember(key, member) :member是否是名称为key的set的元素sinter(key1, key2,…key N) :求交集sinterstore(dstkey, (keys)) :求交集并将交集保存到dstkey的集合sunion(key1, (keys)) :求并集sunionstore(dstkey, (keys)) :求并集并将并集保存到dstkey的集合sdiff(key1, (keys)) :求差集sdiffstore(dstkey, (keys)) :求差集并将差集保存到dstkey的集合smembers(key) :返回名称为key的set的所有元素srandmember(key) :随机返回名称为key的set的一个元素 |
---|
hset(key, field, value):向名称为key的hash中添加元素fieldhget(key, field):返回名称为key的hash中field对应的valuehmget(key, (fields)):返回名称为key的hash中field i对应的valuehmset(key, (fields)):向名称为key的hash中添加元素field hincrby(key, field, integer):将名称为key的hash中field的value增加integerhexists(key, field):名称为key的hash中是否存在键为field的域hdel(key, field):删除名称为key的hash中键为field的域hlen(key):返回名称为key的hash中元素个数hkeys(key):返回名称为key的hash中所有键hvals(key):返回名称为key的hash中所有键对应的valuehgetall(key):返回名称为key的hash中所有的键(field)及其对应的value |
---|
Master/Slave配置:Master IP:175.41.209.118Master Redis Server Port:6379Slave配置很简单,只需要在slave服务器的redis.conf加入:slaveof 175.41.209.118 6379启动master和slave,然后写入数据到master,读取slave,可以看到数据被复制到slave了.用途:读写分离,数据备份,灾难恢复等 |
---|
配置好slave后,slave与master建立连接,然后发送sync命令. 无论是第一次连接还是重新连接,master都会启动一个后台进程,将数据库快照保存到文件中,同时master主进程会开始收集新的写命令并缓存. 后台进程完成写文件后,master就发送文件给slave,slave将文件保存到硬盘上,再加载到内存中。接着master就会把缓存的命令转发给slave,后续master将收到的写命令发送给slave. 如果master同时收到多个slave发来的同步连接命令,master只会启动一个进程来写数据库镜像, 然后发送给所有的slave |
---|
1. master可以拥有多个slave.2. 多个slave可以连接同一个master外,还可以连接到其他slave.3. 主从复制不会阻塞master,在同步数据时,master可以继续处理client请求.4. 可以在master禁用数据持久化,注释掉master配置文件中的所有save配置,只需在slave上配置数据持久化.5. 提高系统的伸缩性 |
---|
官方提供了一个数据, slave在21秒即完成了对Amazon网站 10G key set的复制. |
---|
所需jar包:
<!-- https://mvnrepository.com/artifact/redis.clients/jedis --><dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>2.9.0</version></dependency> |
---|
java操作:
import java.util.Iterator;import java.util.List;import java.util.Set;import redis.clients.jedis.Jedis;public class RedisTest { public static void main(String[] args) { Jedis jd = new Jedis("39.106.131.203"); System.out.println("连接redis成功"); // System.out.println("服务正在运行" + jd.ping()); /** * 操作string类型 */ // jd.set("key2", "java1212"); // System.out.println("redis中存储的值为:"+jd.get("key2")); /** * 操作list类型 */ // jd.lpush("list", "listvalue1"); // jd.lpush("list", "listvalue2"); // jd.lpush("list", "listvalue3"); // // List<String> list = jd.lrange("list", 0, 2); // for (int i = 0; i < list.size(); i++) { // System.out.println("list的结果是:" + list.get(i)); // } /** * 操作set类型 */ jd.sadd("setKey1", "setvalue1"); jd.sadd("setKey1", "setvalue2"); jd.sadd("setKey1", "setvalue3"); Set<String> keys = jd.keys("*"); // Set<String> keys = jd.smembers("setKey1"); Iterator<String> it = keys.iterator(); while(it.hasNext()){ String key = it.next(); System.out.println(key); } }} |
---|
Redis使用最佳方式是全部数据in-memory。 Redis更多场景是作为Memcached的替代者来使用。 当需要除key/value之外的更多数据类型支持时,使用Redis更合适。 当存储的数据不能被剔除时,使用Redis更合适。(持久化) |
---|