4. NoSQL之Redis学习笔记

1. Nosql介绍

1.1. 一类新出现的数据库(not only sql),它的特点
1.1.1. 不支持SQL语法
1.1.2. 存储结构跟传统关系型数据库中的那种关系表完全不同,nosql中存储的数据都是KV形式
1.1.3. NoSQL的世界中没有一种通用的语言,每种nosql数据库都有自己的api和语法,以及擅长的业务场景
1.2. NoSQL产品种类
1.2.1. Mongodb 文档型nosql数据库,擅长做CMS系统(内容管理系统)
1.2.2. Redis 内存数据库,数据结构服务器,号称瑞士军刀(精巧),只要你有足够的想象力,它可以还给你无限惊喜
1.2.3. Hbase hadoop生态系统中原生的一种nosql数据库,重量级的分布式nosql数据库,用于海量数据的场景
1.2.4. Cassandra hadoop生态系统中原生的一种分布式nosql数据库,后起之秀
1.3. NoSQL和SQL数据库的比较
1.3.1. 适用场景不同:sql数据库适合用于关系特别复杂的数据查询场景,nosql反之
1.3.2. “事务”特性的支持:sql对事务的支持非常完善,而nosql基本不支持事务
1.3.3. 两者在不断地取长补短,呈现融合趋势

2. Redis介绍

2.1. 简述
Redis是一个高性能的kv对缓存和内存数据库(存的不像mysql那样的表)Redis的存储结构就是key-value,
Redis中的value内部可以支持各种数据结构类型,比如可以存入一个普通的string,还可以存list,set,hashmap,sortedSet(有序的set)
2.2. Redis的特性
2.2.1. Redis数据访问速度快(数据在内存中)
2.2.2. Redis有数据持久化机制(持久化机制有两种:1、定期将内存数据dump到磁盘;
2、aof(append only file)持久化机制——用记日志的方式记录每一条数据更新操作,一旦出现灾难事件,可以通过日志重放来恢复整个数据库
2.2.3. Redis支持集群模式(容量可以线性扩展)
2.2.4. Redis相比其他缓存工具(ehcach/memcached),有一个鲜明的优势:支持丰富的数据结构
2.3. Redis应用场景
2.3.1. 用来做缓存(ehcache/memcached)——Redis的所有数据是放在内存中的(内存数据库)
2.3.2. 可以在某些特定应用场景下替代传统数据库——比如社交类的应用
2.3.3. 在一些大型系统中,巧妙地实现一些特定的功能:session共享、购物车
只要你有丰富的想象力,Redis可以给你无限的惊喜…….

3. Redis的安装及配置

3.1. 到官网下载最新stable版
3.2. 解压源码并进入目录 tar -zxvf redis-2.8.19.tar.gz -C ./redis-src/
3.3. make
如果报错提示缺少gcc,则安装gcc : yum install -y gcc
如果报错提示:Newer version of jemalloc required
则在make时加参数:make MALLOC=libc

3.4. 安装redis,指定安装目录,如 /usr/local/redis
make PREFIX=/usr/local/redis install

3.5. 拷贝一份配置文件到安装目录下
切换到源码目录,里面有一份配置文件 redis.conf,然后将其拷贝到安装路径下
cp redis.conf /usr/local/redis/

3.6. 启动redis
cd /usr/local/redis
bin/redis-server redis.conf
3.7. 启动为后台服务
3.7.1. 方式一
nohup bin/redis-server ./redis.conf 1>/dev/null 2>&1 &
Nohup:控制台关闭或闲置超时,也不退出
1>/dev/null : 把程序的“1”——标准输出,重定向到文件/dev/null
2>&1 : 把程序的“2”——错误输出,重定向到“1”所去的文件
& : 把程序放到后台运行
3.7.2. 方式二
修改redis.conf 配置文件 daemonize为yes
3.8. 查看后台进程
ps -ef | grep redis
3.9. 查看端口号
netstat -nltp
3.10. 连接客户端
bin/redis-cli -h mini1 -p 6379

4. Redis常用API-使用文档

链接: https://www.cnblogs.com/libaoting/p/4418007.html

5. Redis的数据功能

5.1. String 类型的数据
5.1.1. 插入和读取一条string类型的数据
set sessionid-0001 “zhangsan”
5.1.2. 对string类型数据进行增减(前提是这条数据的value可以看成数字)
set sessionid-0001 “123”
decr sessionid-0001
incr sessionid-0001
decrby sessionid-0001 10 # 修改redis中的数据,一次减少10
incrby sessionid-0001 10
5.1.3. 一次性插入或者获取多条数据
MGET sessionid-0001 sessionid-0002
5.1.4. 在插入一条string类型数据的同时为它指定一个存活期限
setex sessionid-0001 10 weige # 单位时间为s (这里出现了一个错误 - 解决方案: https://www.cnblogs.com/anny-1980/p/4582674.html)
5.2. List功能演示
5.2.1. 从头部(左边)插入数据
lpush list-001 a b c
lrange list-001 0 -1
结果: c b a
5.2.2. 从尾部(右边)插入数据
rpush list-002 a b c
lrange list-001 0 -1
结果: a b c
5.2.3. 从尾部(右边)读取数据
lrange key start end
lrange key 0 -1 # 读取整个list
5.2.4. 从头部弹出一个元素
lpop list-001
c 被弹了出来,原list-001 少了一个元素
5.2.5. 从尾部弹出一个元素
rpop list-002
c 被弹了出来,原list-002 少了一个元素
5.2.6. 从一个list的尾部弹出一个元素插入到另一个list
rpoplpush list-001 list-002 # 这是一个原子性操作
5.3. List的应用案例Demo
5.3.1. 需求描述
任务调度系统:
生产者不断产生任务,放入task-queue排队
消费者不断拿出任务来处理,同时放入一个tmp-queue暂存,如果任务处理成功,则清除tmp-queue,否则,将任务弹回task-queue
5.3.2. 设计思路

5.3.3. 代码实现
生产者

public class TaskProducer {

// 获取一个redis的客户端连接对象
public static Jedis getRedisConnection(String host, int port) {

	Jedis jedis = new Jedis(host, port);

	return jedis;

}

public static void main(String[] args) {

	Jedis jedis = getRedisConnection("mini1", 6379);

	Random random = new Random();
	// 生成任务
	while (true) {

		try {
			// 生成任务的速度有一定的随机性,在1-2秒之间
			Thread.sleep(random.nextInt(1000) + 1000);
			// 生成一个任务
			String taskid = UUID.randomUUID().toString();

			// 往任务队列"task-queue"中插入,第一次插入时,"task-queue"还不存在
			//但是lpush方法会在redis库中创建一条新的list数据
			jedis.lpush("task-queue", taskid);
			System.out.println("向任务队列中插入了一个新的任务: " + taskid);

		} catch (InterruptedException e) {
			e.printStackTrace();
		}

	}

}

}

消费者

public class TaskConsumer {

public static void main(String[] args) {

	Jedis jedis = new Jedis("mini1", 6379);
	Random random = new Random();

	while (true) {

		try {
			// 从task-queue中取一个任务,同时放入"tmp-queue"
			String taskid = jedis.rpoplpush("task-queue", "tmp-queue");

			// 模拟处理任务
			Thread.sleep(1000);

			// 模拟有成功又有失败的情况
			int nextInt = random.nextInt(13);
			if (nextInt % 7 == 0) { // 模拟失败的情况

				// 失败的情况下,需要将任务从"tmp-queue"弹回"task-queue"
				jedis.rpoplpush("tmp-queue", "task-queue");
				System.out.println("-------任务处理失败: " + taskid);

			} else { // 模拟成功的情况

				// 成功的情况下,将任务从"tmp-queue"清除
				jedis.rpop("tmp-queue");
				System.out.println("任务处理成功: " + taskid);

			}

		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}

}

5.4. Hash功能演示
5.4.1. 往redis库中插入一条hash类型的数据
hset user001:zhangsan iphone 6
hset user001:zhangsan xiaomi 7
hset user001:zhangsan meizu 8
5.4.2. 取出一条hash类型数据中所有field-value对
hgetall user001:zhangsan
5.4.3. 取出hash数据中所有fields
hkeys user001:zhangsan
5.4.4. 取出hash数据中所有的value
hvals user001:zhangsan
5.4.5. 取出hash数据中一个指定field的值
hget user001:zhangsan xiaomi
5.4.6. 为hash数据中指定的一个field的值进行增减
hincrby user001:zhangsan xiaomi 2 # 如果减,就填负数
5.4.7. 从hash数据中删除一个字段field及其值
hdel user001:zhangsan iphone
5.5. Set 数据结构功能
特点:无序、无重复元素
5.5.1. 插入一条set数据
sadd fields:ids 1 2 3 4 5 2 3 # 结果是5个元素
5.5.2. 获取一条set数据的所有members
smembers fields:ids
5.5.3. 判断一个成员是否属于某条指定的set数据
sismember fields:ids 4 #如果不是,则返回0
sismember fields:ids 7 #如果是,则返回1
5.5.4. 求两个set数据的差集
sadd fields:counts 4 5 6 7 8
sdiff fields:ids fields:counts
sdiff fields:counts fields:ids
sdiffstore fields:rets fields:ids fields:counts # 求差集,并将结果存入到另一个set
5.5.5. 求交集,求并集
sinter fields:ids fields:counts
sunion fields:ids fields:counts
注意:同样可以把求得的结果存入到一个新的集合当中
5.6. sortedSet(有序集合)数据结构
sortedset中存储的成员都有一个附带的分数值,而redis就可以根据分数来对成员进行各种排序(正序、倒序)
5.6.1. 往redis库中插入一条sortedset数据
zadd ranking 70 liudehua 90 huangbo 100 weixiaobao 60 zhangfei
5.6.2. 从sortedset中查询有序结果
zrange ranking 0 -1
5.6.3. 查询某个成员的名次
zrank ranking zhangfei
zrevrank ranking zhangfei # 在倒序榜中的名次
5.6.4. 修改成员的分数
zincrby ranking 300 zhangfei

6. Redis应用案例(待续)

Lol盒子英雄数据排行榜:
1、在redis中需要一个榜单所对应的sortedset数据
2、玩家每选择一个英雄打一场游戏,就对sortedset数据的相应的英雄分数+1
3、Lol盒子上查看榜单时,就调用zrange来看榜单中的排序结果

7. Redis应用案例(待续)

1、每来一个用户创建购物车,就对购物车中的每一件商品在redis中插入一条以商品名称为key的sortedset,成员为同时出现在购物车中的其他商品,分数为1
2、每新产生一个购物车,就对车中的商品更新redis中的sortedset,将同时出现的商品的分数增1
3、推荐时,用户放入一件商品到购物车,则从这件商品对应的sortedset中查询分数最高的同现商品,推荐给该用户

发布了85 篇原创文章 · 获赞 12 · 访问量 3736

猜你喜欢

转载自blog.csdn.net/fanjianhai/article/details/103798531