您的位置:首页 > 数据库 > Redis

redis的安装以及常见的使用

2016-01-17 11:35 721 查看
NOSQL

NOSQL:一类新出现的数据库,它的特点:

1、 不支持SQL语法

2、 存储结构跟传统关系型数据库中的那种关系表完全不同,nosql中存储的数据都是KV形式

3、 NOSQL的世界中没有一种通用的语言,每种nosql数据库都有自己的api和语法,以及擅长的业务场景

4、 NOSQL中的产品种类相当多:

a) Mongodb 文档型nosql数据库,擅长做CMS系统(内容管理系统)

b) Redis 数据结构服务器,号称瑞士军刀(精巧),只要你有足够的想象力,它可以发挥你想象不到的作用

c) Hbase hadoop生态系统中原生的一种nosql数据库,重量级的分布式nosql数据库,用于海量数据的场景

d) Cassandra hadoop生态系统中原生的一种分布式nosql数据库,后起之秀

。。。。。。

NOSQL和SQL数据库的比较:

1、适用场景不同:sql数据库适合用于关系特别复杂的数据查询场景,nosql反之

2、事务特性的支持:sql对事务的支持非常完善,而nosql基本不支持事务

3、两者在不断地取长补短,呈现融合趋势

Redis

1/什么是redis

1、简述

Redis是一个高性能的kv对缓存和内存数据库(存的不像mysql那样的表)

Redis的存储结构就是key-value,形式如下:



注: redis中的value内部可以支持各种数据结构类型,比如可以存入一个普通的string,还可以存list,set,hashmap,sortedSet(有序的set)

2、redis应用场景

A、用来做缓存(ehcache/memcached)——redis的所有数据是放在内存中的(内存数据库)

B、可以在某些特定应用场景下替代传统数据库——比如社交类的应用

C、在一些大型系统中,巧妙地实现一些特定的功能:session共享、购物车

只要你有丰富的想象力,redis可以用在可以给你无限的惊喜…….

3、redis的特性

A、redis数据访问速度快(数据在内存中)

B、redis有数据持久化机制(持久化机制有两种:1、定期将内存数据dump到磁盘;2、aof(append only file)持久化机制——用记日志的方式记录每一条数据更新操作,一旦出现灾难事件,可以通过日志重放来恢复整个数据库)

C、redis支持集群模式(容量可以线性扩展)

D、redis相比其他缓存工具(ehcach/memcached),有一个鲜明的优势:支持丰富的数据结构

2/安装redis

1、先去官网(http://redis.io/download )下载一个源码工程(redis官网版本只支持linux/微软开源事业部维护了一个windows版本)

2、把安装包上传到服务器,解压缩

3、切换到解压出来的源码工程目录中

cd redis-2.6.16

4、用make命令来对redis的c语言源码工程进行编译

5、编译完成之后,用make install命令进行安装

[root@notrue-centos redis-2.6.16]# make PREFIX=/usr/local/redis install

安装成功的显示:



进入redis的bin目录:



Redis服务在启动的时候可以指定配置文件,那,我们可以从redis的源码目录中拷贝一份配置文件模板到redis的安装目录,修改后使用

[root@notrue-centos redis-2.6.16]# cp /root/redis-2.6.16/redis.conf /usr/local/redis/

然后再指定配置文件,启动redis服务:



启动成功的显示:



上述启动方法,会让redis服务进程运行在console前台,最好应该放到后台运行,可将启动命令改为如下方式:

 方式一

[root@notrue-centos redis]# nohup bin/redis-server ./redis.conf 1>/dev/null 2>&1 &

Nohup:控制台关闭或闲置超时,也不退出

1>/dev/null : 把程序的“1”——标准输出,重定向到文件/dev/null

2>&1 : 把程序的“2”——错误输出,重定向到“1”所去的文件

& : 把程序放到后台运行

 方式二

修改配置文件,

vi redis.conf

修改其中一个配置



保存文件后再用普通命令启动,也可以启动为后台模式

[root@notrue-centos redis]# bin/redis-server ./redis.conf

3/客户端连接

1、 用redis自带的命令行客户端

[root@notrue-centos redis]# bin/redis-cli -h notrue-centos -p 6379

redis notrue-centos:6379> ping

PONG

redis notrue-centos:6379>

2、 或者用redis的api客户端连接

新建一个maven工程,导入jedis的maven依赖坐标

redis.clients

jedis

2.7.2

jar

compile

然后写一个类用来测试服务器跟客户端的连通性:

public class RedisClientConnectionTest {

public static void main(String[] args) {

// 构造一个redis的客户端对象

Jedis jedis = new Jedis(“pinshutang.zicp.net”, 6379);

String ping = jedis.ping();

System.out.println(ping);

}

}

4/Redis的数据功能

String类型的数据(作为缓存使用)

1/插入和读取一条string类型的数据

redis notrue-centos:6379> set sessionid-0001 “zhangsan”

OK

redis notrue-centos:6379> get sessionid-0001

“zhangsan”

2/对string类型数据进行增减(前提是这条数据的value可以看成数字)

DECR key

INCR key

DECRBY key decrement

INCRBY key increment

3/一次性插入或者获取多条数据

MGET key1 key2

MSET key1 value1 key2 value2 …..

4/在插入一条string类型数据的同时为它指定一个存活期限

setex bancao 10 weige

bancao这条数据就只会存活10秒钟,过期会被redis自动清除

作业:将一个自定义的对象比如person存入redis

List数据结构



从头部插入数据

LPUSH key value1 value2 value3

从尾部插入数据

RPUSH key value1 value2 value3

读取list中指定范围的values

LRANGE key start end

redis> lrange task-queue 0 -1 读取整个list

从头部弹出一个元素

LPOP key

从尾部弹出一个元素

RPOP key

从一个list的尾部弹出一个元素插入到另一个list

RPOPLPUSH key1 key2

 List的应用案例demo

任务调度系统:

生产者不断产生任务,放入task-queue排队

消费者不断拿出任务来处理,同时放入一个tmp-queue暂存,如果任务处理成功,则清除tmp-queue,否则,将任务弹回task-queue



代码实现:

A、 生产者——模拟产生任务

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("angelababy", 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) {
// TODO Auto-generated catch block
e.printStackTrace();
}

}

}


}

B、 消费者——模拟处理任务,并且管理暂存队列

public class TaskConsumer {

public static void main(String[] args) {

Jedis jedis = new Jedis("angelababy", 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) {
// TODO Auto-generated catch block
e.printStackTrace();
}

}

}


}

上述机制是一个简化版,真实版的任务调度系统会更加复杂,如下所示:

(增加了一个专门用来管理暂存队列的角色,以便就算消费者程序失败退出,那些处理失败的任务依然可以被弹回task-queue)



Hash数据结构

Redis中的Hashes类型可以看成具有String Key和String Value的map容器



1、往redis库中插入一条hash类型的数据

redis> HSET key field value

举例:

redis 127.0.0.1:6379> hset user001:zhangsan iphone 6

(integer) 1

redis 127.0.0.1:6379> hset user001:zhangsan xiaomi 7

(integer) 1

redis 127.0.0.1:6379> hset user001:zhangsan meizu 8

(integer) 1

在redis库中就形成了这样一条数据:



2、从redis库中获取一条hash类型数据的value

 取出一条hash类型数据中所有field-value对

redis 127.0.0.1:6379> hgetall user001:zhangsan

1) “iphone”

2) “6”

3) “xiaomi”

4) “7”

5) “meizu”

6) “8”

 取出hash数据中所有fields

redis 127.0.0.1:6379> HKEYS user001:zhangsan

1) “iphone”

2) “xiaomi”

3) “meizu”

 取出hash数据中所有的value

redis 127.0.0.1:6379> hvals user001:zhangsan

1) “6”

2) “7”

3) “8”

 取出hash数据中一个指定field的值

redis 127.0.0.1:6379> hget user001:zhangsan xiaomi

“8”

 为hash数据中指定的一个field的值进行增减

redis 127.0.0.1:6379> HINCRBY user001:zhangsan xiaomi 1

(integer) 8

 从hash数据中删除一个字段field及其值

redis 127.0.0.1:6379> hgetall user001:zhangsan

1) “iphone”

2) “6”

3) “xiaomi”

4) “7”

5) “meizu”

6) “8”

redis 127.0.0.1:6379> HDEL user001:zhangsan iphone

(integer) 1

redis 127.0.0.1:6379> hgetall user001:zhangsan

1) “xiaomi”

2) “7”

3) “meizu”

4) “8”

Set数据结构功能

集合的特点:无序、无重复元素

1、 插入一条set数据

redis 127.0.0.1:6379> sadd frieds:zhangsan bingbing baby fengjie furong ruhua feifei

(integer) 6

redis 127.0.0.1:6379> scard frieds:zhangsan

(integer) 6

redis 127.0.0.1:6379>

2、获取一条set数据的所有members

redis 127.0.0.1:6379> smembers frieds:zhangsan

1) “fengjie”

2) “baby”

3) “furong”

4) “bingbing”

5) “feifei”

6) “ruhua”

3、判断一个成员是否属于某条指定的set数据

redis 127.0.0.1:6379> sismember frieds:zhangsan liuyifei #如果不是,则返回0

(integer) 0

redis 127.0.0.1:6379> sismember frieds:zhangsan baby #如果是,则返回1

(integer) 1

4、求两个set数据的差集

求差集

redis 127.0.0.1:6379> sdiff frieds:zhangsan friends:xiaotao

1) “furong”

2) “fengjie”

3) “ruhua”

4) “feifei”

求差集,并将结果存入到另一个set

redis 127.0.0.1:6379> sdiffstore zhangsan-xiaotao frieds:zhangsan friends:xiaotao

(integer) 4

查看差集结果

redis 127.0.0.1:6379> smembers zhangsan-xiaotao

1) “furong”

2) “fengjie”

3) “ruhua”

4) “feifei”

5、 求交集,求并集

求交集

redis 127.0.0.1:6379> sinterstore zhangsan^xiaotao frieds:zhangsan friends:xiaotao

(integer) 2

redis 127.0.0.1:6379> smembers zhangsan^xiaotao

1) “bingbing”

2) “baby”

求并集

redis 127.0.0.1:6379> smembers zhangsan^xiaotao

1) “bingbing”

2) “baby”

redis 127.0.0.1:6379> sunion frieds:zhangsan friends:xiaotao

1) “fengjie”

2) “tangwei”

3) “liuyifei”

4) “bingbing”

5) “ruhua”

6) “feifei”

7) “baby”

8) “songhuiqiao”

9) “furong”

10) “yangmi”

sortedSet(有序集合)数据结构

sortedset中存储的成员都有一个附带的分数值

而redis就可以根据分数来对成员进行各种排序(正序、倒序)

1、 sortedSet存储内容示意图:



2、 往redis库中插入一条sortedset数据

redis 127.0.0.1:6379> zadd nanshen:yanzhi:bang 70 liudehua 90 huangbo 100 weixiaobao 250 yanggang 59 xiaotao

(integer) 5

3、 从sortedset中查询有序结果

正序结果

redis 127.0.0.1:6379> zrange nanshen:yanzhi:bang 0 4

1) “xiaotao”

2) “liudehua”

3) “huangbo”

4) “weixiaobao”

5) “yanggang”

倒序结果

redis 127.0.0.1:6379> zrevrange nanshen:yanzhi:bang 0 4

1) “yanggang”

2) “weixiaobao”

3) “huangbo”

4) “liudehua”

5) “xiaotao”

4、 查询某个成员的名次

在正序榜中的名次

redis 127.0.0.1:6379> zrank nanshen:yanzhi:bang xiaotao

(integer) 0

在倒序榜中的名次

redis 127.0.0.1:6379> zrevrank nanshen:yanzhi:bang xiaotao

(integer) 4

5、修改成员的分数

redis 127.0.0.1:6379> zincrby nanshen:yanzhi:bang 300 xiaotao

“359”

redis 127.0.0.1:6379> zrevrank nanshen:yanzhi:bang xiaotao

(integer) 0

案例:

Lol盒子英雄数据排行榜:

1、 在redis中需要一个榜单所对应的sortedset数据

2、 玩家每选择一个英雄打一场游戏,就对sortedset数据的相应的英雄分数+1

3、 Lol盒子上查看榜单时,就调用zrange来看榜单中的排序结果

作业:

带智能推荐的购物车整合到巴巴运动网中:

实现步骤:

1、 每来一个用户创建购物车,就对购物车中的每一件商品在redis中插入一条以商品名称为key的sortedset,成员为同时出现在购物车中的其他商品,分数为1

2、 每新产生一个购物车,就对车中的商品更新redis中的sortedset,将同时出现的商品的分数增1

3、 推荐时,用户放入一件商品到购物车,则从这件商品对应的sortedset中查询分数最高的同现商品,推荐给该用户
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: