Redis
NoSQL数据库
NoSQL数据库简介
NoSQL数据存储不需要固定的模式,无序多余的操作就可以横向发展,NoSQL用于解决大规模数据集合多重数据带来的挑战,尤其是大数据应用难题,包括超大规模数据的存储
大数据时间3V:海量Volume 多样Variety 实时Velocity
互联网需求3高:高并发 高扩展 高性能
当下NoSQL应用场景
当下应该是SQL和NoSQL共同使用,以淘宝为例具体数据存放方式如下:
- 商品的基本信息:MySQL
- 商品的评价信息,描述,以文字居多的:IO读写性能变差,用MongDB
- 商品的图片:分布式文件系统,如Hadoop的HDFS
- 商品用于搜索的关键字:ISearch
- 商品热搜的高频词汇:Redis、Memcache
大数据、高并发、多样数据类型的难点和解决方案:
难点:
数据类型的多样性
数据源多样性和变化重构
数据源改造而数据平台不需要大面积重构
解决方式:使用同一数据平台封装好不同数据库的访问
NoSQL数据模型简介
NoSQL如何设计:使用BSON画出构建的数据模型
Bson:是一种类Json的二进制的存储格式,简称Binary JSON
高并发的操作是不太建议有关联查询的(关联查询是指mysql中的join多表关联),互联网公司使用冗余数据来避免关联查询,分布式事务是支持不了太多的并发的。
聚合模型:KV键值对、Bson、列族、图形
NoSQL数据库四大分类
- KV键值:美团:redis+tair ,阿里百度:memcache+redis
- 文档类型的数据库(bson格式比较多):CouchDB,MongoDB
MongoDB是基于分布式文件存储的数据库,是介于关系型和非关系型的一个产品 - 列存储数据库:Cassandra,Hbase,分布式文件系统
- 图关系数据库:存放的是关系比如朋友圈社交网络、广告推荐系统等,专注于构建关系图谱,Neo4J,InfoGrid
分布式数据库CAP原理
传统的关系型数据库满足ACID:原子性、一致性、独立性、持久性
非关系型数据库CAP原理:
强一致性(Consistency):访问所有的节点得到的数据应该是一样的
可用性(Availability):所有的节点都保持高可用性
分区容错性(Partiton tolerence):这里的分区是指网络意义上的分区,在节点不能通信时,要保证系统可以继续正常服务
一个分布式系统不可能同时很好的满足一致性、可用性和分区容错性,最多只能同时较好的满足两个
分区容忍性是分布式数据库必须实现的,所以我们只能在一致性和可用性之前进行权衡
CA:传统的数据库
AP:大多数网站的选择
CP:Redis、Mongodb
BASE:
基本可用(Basically Avalilable)
软状态(Soft state)
最终一致(Eventrually consistent)
分布式:不同的多台服务器部署不同的服务模块
集群:不同的多台服务器部署相同的模块
Redis入门
Redis:REmote DIctionary Server(远程字典服务器)
Redis启动
第一步:在linux下新建文件夹myredis,并把redis安装包内的redis.conf移动到myredis文件夹下
第二步:vim redis.conf,daemonize no改为daemonize yes。使用vim时注意shift+$移动到行末,i为插入,shift+:为命令输入,wq!为强制保存退出
第三步:redis-server /myredis/redis.conf启动redis,redis-cli -p 6379设置端口,并设置k1值为hello,得到k1,然后再关闭服务
第四步:
ps -ef|grep redis查看运行状态如下,ps显示程序信息,-e显示全部程序,-f显示完整信息,grep指定筛选关键字
Redis启动后杂项知识讲解
- Redis是单进程的,通过对epoll函数包装来实现多路IO复用,Redis默认有16个数据库,默认端口是6379
- select i:可以选择第i个数据库
- dbsize:查看当前数据库key数量
- keys * : 罗列当前数据库的所有key
- keys k??:查出kxx
- flushall:删除所有的数据库,flushdb:删除当前数据库
Redis 键key
key *
exists keyname 判断keyname是否存在
move key db 移除当前key到db
expire key s 为当前key设置过期时间
ttl key 查看还有多少秒过期,-1表示永不过期,-2表示已过期
type key 查看key的类型
Redis五大常用数据类型
从redisdoc.com获取数据类型操作列表
-
String(字符串)
getrange k1 0 1:获取k1从0到1范围内的值
setrange k1 0 xxx:设置指定k1从0开始改为xxx
mset k1 v1 k2 v2:设置两组键值对 -
List(列表):可重复
LPUSH:正进反出
RPUSH:正进正处
LRANGE list1 0 -1:显示list1的所有值
lpop:栈首出栈
rpop:栈尾出栈
llen:获取长度
lrem N key:删除N个key
itrim key i j :把从i到j赋值给原key -
Set(集合):不可重复
sadd set01 1 2 3 4 5:给集合set01添加元素1 2 3 4 5
smembers set01:获取01中的所有元素
scard set01:获取集合的元素个数
srem set01 value:删除set01中的元素value
srandmember set01 n:从set01中随机取n个元素
spop set01:随机出栈
smove set01 set02 value :将set01中的value赋值给set02
sdiff set01 set02:差集,在set01但是不在set02里面
sinter set01 set02:交集
sunion set01 set02:并集 -
Hash(哈希,类似于java中的Map):
KV模式不变,但V是一个键值对
hset user id 11: user为key value为键值对<id,11>
hset customer id 11 name li4 age 26:设置custom
hkeys customer:获取customer所有的key
hvals customer:获取所有的value
hincreby customer age n:让custom的age增长2
hsettnx customer age 23:设置年龄为23 -
Zset(有序集合):在set基础上添加一个score值
之前set是k1 v1 v2 v3
现在zset是k1 score1 v1 score2 v2
zadd zset01 60 v1 70 v2 80 v3:设置zset
zrange zset01 0 -1 withscores:查看zset和score
zcount zset01 60 80:统计60和80的
Redis配置文件redis.conf
Redis缓存策略Maxmemory-policy设置,其中LRU算法是指最近最少使用
- volatile-lru:使用LRU算法移除key,只对设置了过期时间的键
- allkeys-lru:使用LRU算法移除key
- volatile-random:在过期集合中移除随机的key,只对设置了过期时间的键
- allkeys-random:随机移除key
- volatile-ttl:移除那些TTL(生存周期)值最小的key,即移除那些最近要过期的key
- noeviction:不进行移除
Redis持久化之RDB
RDB(Redis DataBase):在指定的时间间隔内将内存中的数据集快照(snapshotting)写入磁盘,恢复时将快照文件直接读到内存中。Redis会单独创建(fork)一个子进程来进行持久化,会先将数据写到一个临时文件中,待持久化过程都结束了,再用这个临时文件替换上次持久化好的文件。整个过程中,主进程是不进行任何IO操作的,这确保了极高的性能
如果要进行大规模的数据恢复,且对于数据恢复的完整性不是非常敏感,那么RDB方式比AOF方式更加的高效。RDB的缺点是最后一次持久化的数据可能丢失
Fork:作用是复制一个与当前进程一样的进程。新进程的所有数据都和原进程一致,并作为原进程的子进程
Redis数据备份:在redis.conf存在三行如下,分别表示900s内修改1次则自动备份,300s内修改10次则自动备份,备份的文件为dump.rdb
save:可以让当前值即刻保存
bgsave:在保存的同时会在后台异步进行快照操作
Redis数据恢复:CONFIG GET dir可以显示当前运行地址,dump.rdb会备份到当前运行地址下。dump.rdb移动到某目录并从该目录启动redis即可恢复数据
Redis持久化之AOF
AOF:以日志的形式来记录每个写操作,将Redis执行过的所有写指令记录下来(读操作不记录),只允许追加文件但不可以改写文件,redis启动之初会读取该文件并执行记录的操作以重新构建数据
开启AOF如下图:appendonly yes
Redis数据恢复:CONFIG GET dir可以显示当前运行地址,appendonly.aof会备份到当前运行地址下。appendonly.aof移动到某目录并从该目录启动redis即可恢复数据
RDB和AOF可以共存,优先加载AOF
AOF优势:灵活设置,可以设置每秒同步,每修改同步,不同步等
AOF劣势:相同的数据集的数据aof文件远大于rdb文件,恢复速率慢与rdb
Redis事务
Redis部分支持事务,事务是指按顺序地串行化执行而不会被其他命令插入,不许加塞
MULTI:开启事务
EXEC:执行事务
DISCARD:中途放弃事务
-
若在事务队列中存在命令性错误,在执行EXEC时,所有的命令都不会执行,例如下图getset k3在执行时即报错,则所有命令都不会被执行
-
若在事务中存在语法性错误,则执行EXEC命令时,其他正确命令会被执行,例如下图的错误对int类的k1进行加操作,加入队列但是不会直接报错
watch监控:
监视一个key,如果事务执行之前这个key被其他命令所改动,那么事务将被打断
Redis消息订阅发布
在终端1订阅消息
subscribe c1 c2 c3
在终端2发布消息
publish c2 hello
则在终端1可以收到消息hello
Redis主从复制
Master-Slaver,Master以写为主,Slave以读为主,用于实现读写分离、容灾恢复
Redis Jedis使用
Redis Jedis事务
使用watch监控一个变量balance,再模拟一个在事务过程中外界的对balance的操作,当watch监控到balance被修改,则事务的执行无效
import redis.clients.jedis.Jedis;
import redis.clients.jedis.Transaction;
public class testTX {
public boolean transMethod(){
Jedis jedis = new Jedis("192.168.42.130",6379);
int balance;
int debt;
int amtToSubtract = 10 ;
jedis.watch("balance");
jedis.set("balance","5");//模拟其他的人对balance的干扰操作
balance = Integer.parseInt(jedis.get("balance"));
if(balance<amtToSubtract){
jedis.unwatch();
System.out.println("modify");
return false;
}else{
System.out.println("******************transaction");
Transaction transaction = jedis.multi();
transaction.decrBy("balance",amtToSubtract);
transaction.incrBy("debt",amtToSubtract);
transaction.exec();
balance = Integer.parseInt(jedis.get("balance"));
debt = Integer.parseInt(jedis.get("debt"));
System.out.println("******************"+ balance);
System.out.println("******************"+debt);
return true;
}
}
public static void main(String[] args) {
testTX test = new testTX();
boolean re = test.transMethod();
System.out.println("main value-----------" + re);
}
}