[if !supportLists]1.1.1 [endif]安装环境
redis是C语言开发,安装redis需要先将官网下载的源码进行编译,编译依赖gcc环境。如果没有gcc环境,需要安装gcc:
yum install gcc-c++
如果提示是否下载,输入y。
如果提示是否安装,输入y
[if !supportLists]1.1.2 [endif]Redis安装
[if !supportLists]l [endif]步骤1:将Windows下下载的压缩文件上传到Linux下。通过secureCRT进行上传,步骤如下:
l alt + p
l put F:/redis-3.0.0.tar.gz
l
[if !supportLists]l [endif]步骤2: 解压文件
l tar –zxvf redis-3.0.0.tar.gz
[if !supportLists]l [endif]步骤3: 编译redis (编译,将.c文件编译为.o文件)
l 进入解压文件夹,cd redis-3.0.0
l 执行make
1)如果没有安装gcc,编译将出现错误提示。(如果安装失败,必须删除文件夹,重写解压)
2)安装成功
[if !supportLists]l [endif]步骤4: 安装
l make PREFIX=/usr/local/src/redis install
l
安装完后,在/usr/local/src/redis/bin下有几个可执行文件
redis-benchmark ----性能测试工具
redis-check-aof ----AOF文件修复工具
redis-check-dump ----RDB文件检查工具(快照持久化文件)
redis-cli ----命令行客户端
redis-server ----redis服务器启动命令
[if !supportLists]l [endif]步骤5: copy文件
redis启动需要一个配置文件,可以修改端口号等信息。
cp redis.conf /usr/local/redis
[if !supportLists]1.1 [endif]Redis的启动
[if !supportLists]1.1.1 [endif]前端模式启动
直接运行bin/redis-server将以前端模式启动,前端模式启动的缺点是启动完成后,不能再进行其他操作,如果要操作必须使用ctrl+c,同时redis-server程序结束,不推荐使用此方法。
/usr/local/redis/bin/redis-server
使用CTRL+ C停止前端模式
[if !supportLists]1.1.2 [endif]后端模式
[if !supportLists]l [endif]修改redis.conf配置文件, daemonize yes 以后端模式启动。
vim /usr/local/redis/redis.conf
[if !supportLists]l [endif]启动时,指定配置文件
cd /usr/local/redis/
./bin/redis-server ./redis.conf
[if !supportLists]l [endif]Redis默认端口6379,通过当前服务进行查看
ps -ef | grep -i redis
[if !supportLists]1.2 [endif]Redis停止
[if !supportLists]l [endif]强制结束程序。强行终止Redis进程可能会导致redis持久化数据丢失。
kill -9 31475 #pid需要通过“ps aux | grep -i redis”进行查询
[if !supportLists]l [endif]正确停止Redis的方式应该是向Redis发送SHUTDOWN命令,方法为:(关闭默认端口)
cd /usr/local/redis
./bin/redis-cli shutdown
[if !supportLists]1.3 [endif]Redis使用
[if !supportLists]1.3.1 [endif]连接客户端
在redis的安装目录中有redis的客户端,即redis-cli(Redis Command Line Interface),它是Redis自带的基于命令行的Redis客户端。
redis-cli -h ip地址 -p 端口
默认ip和端口
[if !supportLists]1.3.2 [endif]向Redis服务器发送命令
redis-cli连上redis服务后,可以在命令行发送命令。
[if !supportLists]l [endif]ping,测试客户端与Redis的连接是否正常,如果连接正常会收到回复PONG
[if !supportLists]l [endif]set/get,使用set和get可以向redis设置数据、获取数据。
[if !supportLists]l [endif]del,删除指定key的内容。
[if !supportLists]l [endif]keys *,查看当前库中所有的key值
[if !supportLists]第2章 [endif]Jedis入门
[if !supportLists]2.1 [endif]Jedis介绍
Redis不仅是使用命令来操作,现在基本上主流的语言都有客户端支持,比如java、C、C#、C++、php、Node.js、Go等。
在官方网站里列一些Java的客户端,有Jedis、Redisson、Jredis、JDBC-Redis、等其中官方推荐使用Jedis和Redisson。在企业中用的最多的就是Jedis,下面我们就重点学习下Jedis。
Jedis同样也是托管在github上,地址:https://github.com/xetorthio/jedis
[if !supportLists]2.2 [endif]Java连接Redis
[if !supportLists]2.2.1 [endif]导入jar包
[if !supportLists]2.2.2 [endif]单实例连接
@Test
public void testJedisSingle(){
//1设置ip地址和端口
Jedis jedis = new Jedis("192.168.137.128", 6379);
//2设置数据
jedis.set("name", "itheima");
//3获得数据
String name = jedis.get("name");
System.out.println(name);
//4释放资源
jedis.close();
}
DENIED Redisis running in protected modebecause protected mode is enabled, no bind address was specified, noauthentication password is requested to clients.
In this mode connections areonly accepted from the loopback interface. If you want to connect from externalcomputers to Redis you may adopt one of the following
solutions: 1) Justdisable protected mode sending the command'CONFIG SET protected-mode no' fromthe loopback interface by connecting to Redis from the same host
the server isrunning, however MAKE SURE Redisis not publicly accessible from internet ifyou do so. Use CONFIG REWRITE to make this change permanent.
2) Alternativelyyou can just disable the protected modeby editing the Redis configurationfile, and setting the protected mode option to 'no', and then restarting theserver.
3) If you started the server manually justfor testing, restart it withthe '--protected-mode no' option.
4) Setup a bind addressor an authenticationpassword. NOTE: You only need to do one of the above things in order for theserver to start accepting connections from the outside.
Connection closed by foreign host.
1、修改redis服务器的配置文件
vi redis.conf
注释以下绑定的主机地址
# bind 127.0.0.1
2、修改redis服务器的参数配置
修改redis的守护进程为no ,不启用
127.0.0.1:6379> configset daemonize "no"
OK
修改redis的保护模式为no,不启用
127.0.0.1:6379> configset protected-mode "no"
OK
[if !supportLists]2.2.3 [endif]连接超时
[if !supportLists]l [endif]如果运行上面代码时,抛如下异常
redis.clients.jedis.exceptions.JedisConnectionException: java.net.SocketTimeoutException: connect timed out
[if !supportLists]l [endif]必须设置linux防火墙
vim /etc/sysconfig/iptables
service iptables restart
[if !supportLists]2.2.4 [endif]连接池连接
@Test
public void testJedisPool(){
//1获得连接池配置对象,设置配置项
JedisPoolConfig config = new JedisPoolConfig();
// 1.1最大连接数
config.setMaxTotal(30);
// 1.2最大空闲连接数
config.setMaxIdle(10);
//2获得连接池
JedisPool jedisPool = new JedisPool(config, "192.168.137.128", 6379);
//3获得核心对象
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
//4设置数据
jedis.set("name", "itcast");
//5获得数据
String name = jedis.get("name");
System.out.println(name);
} catch (Exception e) {
e.printStackTrace();
} finally{
if(jedis != null){
jedis.close();
}
//虚拟机关闭时,释放pool资源
if(jedisPool != null){
jedisPool.close();
}
}
}
[if !supportLists]第3章 [endif]Redis的数据结构
[if !supportLists]3.1 [endif]Redis数据结构介绍
[if !supportLists]l [endif]redis是一种高级的key-value的存储系统,其中value支持五种数据类型。
[if !supportLists]1、 [endif]字符串(String)
[if !supportLists]2、 [endif]哈希(hash)
[if !supportLists]3、 [endif]字符串列表(list)
[if !supportLists]4、 [endif]字符串集合(set)
[if !supportLists]5、 [endif]有序字符串集合(sorted set)
[if !supportLists]l [endif]而关于key的定义呢,需要大家注意的几点:
[if !supportLists]1、 [endif]key不要太长,最好不要超过1024个字节,这不仅会消耗内存还会降低查找效率
[if !supportLists]2、 [endif]key不要太短,如果太短会降低key的可读性
[if !supportLists]3、 [endif]在项目中,key最好有一个统一的命名规范
[if !supportLists]3.2 [endif]存储string
[if !supportLists]3.2.1 [endif]概述
字符串类型是Redis中最为基础的数据存储类型,它在Redis中是二进制安全的,这便意味着该类型存入和获取的数据相同。在Redis中字符串类型的Value最多可以容纳的数据长度是512M。
[if !supportLists]3.2.2 [endif]常用命令
[if !supportLists]3.2.2.1 [endif]赋值
[if !supportLists]l [endif]set key value:设定key持有指定的字符串value,如果该key存在则进行覆盖操作。总是返回”OK”
[if !supportLists]3.2.2.2 [endif]取值
[if !supportLists]l [endif]get key:获取key的value。如果与该key关联的value不是String类型,redis将返回错误信息,因为get命令只能用于获取String value;如果该key不存在,返回(nil)。
[if !supportLists]l [endif]getsetkey value:先获取该key的值,然后在设置该key的值。
[if !supportLists]3.2.2.3 [endif]删除
[if !supportLists]l [endif]del key:删除指定key
[if !supportLists]3.2.2.4 [endif]数值增减
[if !supportLists]l [endif]incr key:将指定的key的value原子性的递增1.如果该key不存在,其初始值为0,在incr之后其值为1。如果value的值不能转成整型,如hello,该操作将执行失败并返回相应的错误信息。
[if !supportLists]l [endif]decr key:将指定的key的value原子性的递减1.如果该key不存在,其初始值为0,在incr之后其值为-1。如果value的值不能转成整型,如hello,该操作将执行失败并返回相应的错误信息。
[if !supportLists]3.2.3 [endif]扩展命令(了解)
[if !supportLists]l [endif]incrby key increment:将指定的key的value原子性增加increment,如果该key不存在,器初始值为0,在incrby之后,该值为increment。如果该值不能转成整型,如hello则失败并返回错误信息
[if !supportLists]l [endif]decrby key decrement:将指定的key的value原子性减少decrement,如果该key不存在,器初始值为0,在decrby之后,该值为decrement。如果该值不能转成整型,如hello则失败并返回错误信息
[if !supportLists]l [endif]appendkey value:拼凑字符串。如果该key存在,则在原有的value后追加该值;如果该key不存在,则重新创建一个key/value
[if !supportLists]3.3 [endif]存储hash
[if !supportLists]3.3.1 [endif]概述
Redis中的Hash类型可以看成具有String Key和String Value的map容器。所以该类型非常适合于存储值对象的信息。如Username、Password和Age等。如果Hash中包含很少的字段,那么该类型的数据也将仅占用很少的磁盘空间。每一个Hash可以存储4294967295个键值对。
[if !supportLists]3.3.2 [endif]常用命令
[if !supportLists]3.3.2.1 [endif]赋值
[if !supportLists]l [endif]hsetkey field value:为指定的key设定field/value对(键值对)。
[if !supportLists]l [endif]hmset key field value [field2 value2 …]:设置key中的多个filed/value
[if !supportLists]3.3.2.2 [endif]取值
[if !supportLists]l [endif]hgetkey field:返回指定的key中的field的值
[if !supportLists]l [endif]hmget key fileds:获取key中的多个filed的值
[if !supportLists]l [endif]hgetallkey:获取key中的所有filed-vaule
[if !supportLists]3.3.2.3 [endif]删除
[if !supportLists]l [endif]hdel key field [field …]:可以删除一个或多个字段,返回值是被删除的字段个数
[if !supportLists]l [endif]del key:删除整个内容
[if !supportLists]3.3.2.4 [endif]增加数字
[if !supportLists]l [endif]hincrbykey field increment:设置key中filed的值增加increment,如:age增加20
[if !supportLists]3.3.3 [endif]自学命令(了解)
[if !supportLists]l [endif]hexists key field:判断指定的key中的filed是否存在
[if !supportLists]l [endif]hlenkey:获取key所包含的field的数量
[if !supportLists]l [endif]hkeys key:获得所有的key
[if !supportLists]l [endif]hvals key:获得所有的value
[if !supportLists]3.4 [endif]存储list(了解)
[if !supportLists]3.4.1 [endif]概述
在Redis中,List类型是按照插入顺序排序的字符串链表。和数据结构中的普通链表一样,我们可以在其头部(left)和尾部(right)添加新的元素。在插入时,如果该键并不存在,Redis将为该键创建一个新的链表。与此相反,如果链表中所有的元素均被移除,那么该键也将会被从数据库中删除。List中可以包含的最大元素数量是4294967295。
从元素插入和删除的效率视角来看,如果我们是在链表的两头插入或删除元素,这将会是非常高效的操作,即使链表中已经存储了百万条记录,该操作也可以在常量时间内完成。然而需要说明的是,如果元素插入或删除操作是作用于链表中间,那将会是非常低效的。相信对于有良好数据结构基础的开发者而言,这一点并不难理解。
[if !supportLists]1、 [endif]ArrayList使用数组方式存储数据,所以根据索引查询数据速度快,而新增或者删除元素时需要设计到位移操作,所以比较慢。
[if !supportLists]2、 [endif]LinkedList使用双向链接方式存储数据,每个元素都记录前后元素的指针,所以插入、删除数据时只是更改前后元素的指针指向即可,速度非常快,然后通过下标查询元素时需要从头开始索引,所以比较慢。
[if !supportLists]3、 [endif]双向链表中添加数据
[if !supportLists]4、 [endif]双向链表中删除数据
[if !supportLists]3.4.2 [endif]常用命令
[if !supportLists]3.4.2.1 [endif]两端添加
[if !supportLists]l [endif]lpush key values[value1 value2…]:在指定的key所关联的list的头部插入所有的values,如果该key不存在,该命令在插入的之前创建一个与该key关联的空链表,之后再向该链表的头部插入数据。插入成功,返回元素的个数。
[if !supportLists]l [endif]rpush key values[value1、value2…]:在该list的尾部添加元素。
[if !supportLists]3.4.2.2 [endif]查看列表
[if !supportLists]l [endif]lrangekey start end:获取链表中从start到end的元素的值,start、end从0开始计数;也可为负数,若为-1则表示链表尾部的元素,-2则表示倒数第二个,依次类推…
[if !supportLists]3.4.2.3 [endif]两端弹出
[if !supportLists]l [endif]lpop key:返回并弹出指定的key关联的链表中的第一个元素,即头部元素。如果该key不存在,返回nil;若key存在,则返回链表的头部元素。
[if !supportLists]l [endif]rpopkey:从尾部弹出元素。
[if !supportLists]3.4.2.4 [endif]获取列表中元素的个数
[if !supportLists]l [endif]llenkey:返回指定的key关联的链表中的元素的数量。
[if !supportLists]3.4.3 [endif]扩展命令(了解)
[if !supportLists]l [endif]lpushx key value:仅当参数中指定的key存在时,向关联的list的头部插入value。如果不存在,将不进行插入。
[if !supportLists]l [endif]rpushx key value:在该list的尾部添加元素
[if !supportLists]l [endif]lremkey count value:删除count个值为value的元素,如果count大于0,从头向尾遍历并删除count个值为value的元素,如果count小于0,则从尾向头遍历并删除。如果count等于0,则删除链表中所有等于value的元素。
0)初始化数据
1)从头删除,2个数字“3”
lrem mylist3 2 3
2)从尾删除,2个数字“1”
lrem mylist3 -2 1
3)删除所有数字“2”
lrem mylist3 0 2
[if !supportLists]l [endif]lsetkey index value:设置链表中的index的脚标的元素值,0代表链表的头元素,-1代表链表的尾元素。操作链表的脚标不存在则抛异常。
[if !supportLists]l [endif]linsert key before|after pivot value:在pivot元素前或者后插入value这个元素。
[if !supportLists]l [endif]rpoplpush resource destination:将链表中的尾部元素弹出并添加到头部。[循环操作]
1)将mylist5右端弹出,压入到mylist6左边。
2)将mylist6右端数据弹出,压入到左端
[if !supportLists]3.4.4 [endif]使用场景
rpoplpush的使用场景:
Redis链表经常会被用于消息队列的服务,以完成多程序之间的消息交换。假设一个应用程序正在执行LPUSH操作向链表中添加新的元素,我们通常将这样的程序称之为"生产者(Producer)",而另外一个应用程序正在执行RPOP操作从链表中取出元素,我们称这样的程序为"消费者(Consumer)"。如果此时,消费者程序在取出消息元素后立刻崩溃,由于该消息已经被取出且没有被正常处理,那么我们就可以认为该消息已经丢失,由此可能会导致业务数据丢失,或业务状态的不一致等现象的发生。然而通过使用RPOPLPUSH命令,消费者程序在从主消息队列中取出消息之后再将其插入到备份队列中,直到消费者程序完成正常的处理逻辑后再将该消息从备份队列中删除。同时我们还可以提供一个守护进程,当发现备份队列中的消息过期时,可以重新将其再放回到主消息队列中,以便其它的消费者程序继续处理。
[if !supportLists]3.5 [endif]存储set(了解)
[if !supportLists]3.5.1 [endif]概述
在Redis中,我们可以将Set类型看作为没有排序的字符集合,和List类型一样,我们也可以在该类型的数据值上执行添加、删除或判断某一元素是否存在等操作。需要说明的是,这些操作的时间复杂度为O(1),即常量时间内完成次操作。Set可包含的最大元素数量是4294967295。
和List类型不同的是,Set集合中不允许出现重复的元素,这一点和C++标准库中的set容器是完全相同的。换句话说,如果多次添加相同元素,Set中将仅保留该元素的一份拷贝。和List类型相比,Set类型在功能上还存在着一个非常重要的特性,即在服务器端完成多个Sets之间的聚合计算操作,如unions、intersections和differences。由于这些操作均在服务端完成,因此效率极高,而且也节省了大量的网络IO开销。
[if !supportLists]3.5.2 [endif]常用命令
[if !supportLists]3.5.2.1 [endif]添加/删除元素
[if !supportLists]l [endif]sadd key values[value1、value2…]:向set中添加数据,如果该key的值已有则不会重复添加
[if !supportLists]l [endif]srem key members[member1、member2…]:删除set中指定的成员
[if !supportLists]3.5.2.2 [endif]获得集合中的元素
[if !supportLists]l [endif]smembers key:获取set中所有的成员
[if !supportLists]l [endif]sismember key member:判断参数中指定的成员是否在该set中,1表示存在,0表示不存在或者该key本身就不存在。(无论集合中有多少元素都可以极速的返回结果)
[if !supportLists]3.5.2.3 [endif]集合的差集运算A-B
[if !supportLists]l [endif]sdiff key1 key2…:返回key1与key2中相差的成员,而且与key的顺序有关。即返回差集。
(属于A并且不属于B的元素构成的集合)
[if !supportLists]3.5.2.4 [endif]集合的交集运算A∩ B
[if !supportLists]l [endif]sinter key1 key2 key3…:返回交集。
(属于A且属于B的元素构成的集合)
[if !supportLists]3.5.2.5 [endif]集合的并集运算A∪ B
[if !supportLists]l [endif]sunion key1 key2 key3…:返回并集。
(属于A或者属于B的元素构成的集合)
[if !supportLists]3.5.3 [endif]扩展命令(了解)
[if !supportLists]l [endif]scard key:获取set中成员的数量
[if !supportLists]l [endif]srandmember key:随机返回set中的一个成员
[if !supportLists]l [endif]sdiffstore destination key1 key2…:将key1、key2相差的成员存储在destination上
[if !supportLists]l [endif]sinterstore destination key[key…]:将返回的交集存储在destination上
[if !supportLists]l [endif]sunionstore destination key[key…]:将返回的并集存储在destination上
[if !supportLists]3.5.4 [endif]使用场景
1、可以使用Redis的Set数据类型跟踪一些唯一性数据,比如访问某一博客的唯一IP地址信息。对于此场景,我们仅需在每次访问该博客时将访问者的IP存入Redis中,Set数据类型会自动保证IP地址的唯一性。
2、充分利用Set类型的服务端聚合操作方便、高效的特性,可以用于维护数据对象之间的关联关系。比如所有购买某一电子设备的客户ID被存储在一个指定的Set中,而购买另外一种电子产品的客户ID被存储在另外一个Set中,如果此时我们想获取有哪些客户同时购买了这两种商品时,Set的intersections命令就可以充分发挥它的方便和效率的优势了。
[if !supportLists]3.6 [endif]存储sortedset(了解)
[if !supportLists]3.6.1 [endif]概述
Sorted-Set和Set类型极为相似,它们都是字符串的集合,都不允许重复的成员出现在一个Set中。它们之间的主要差别是Sorted-Set中的每一个成员都会有一个分数(score)与之关联,Redis正是通过分数来为集合中的成员进行从小到大的排序。然而需要额外指出的是,尽管Sorted-Set中的成员必须是唯一的,但是分数(score)却是可以重复的。
在Sorted-Set中添加、删除或更新一个成员都是非常快速的操作,其时间复杂度为集合中成员数量的对数。由于Sorted-Set中的成员在集合中的位置是有序的,因此,即便是访问位于集合中部的成员也仍然是非常高效的。事实上,Redis所具有的这一特征在很多其它类型的数据库中是很难实现的,换句话说,在该点上要想达到和Redis同样的高效,在其它数据库中进行建模是非常困难的。
例如:游戏排名、微博热点话题等使用场景。
[if !supportLists]3.6.2 [endif]常用命令
[if !supportLists]3.6.2.1 [endif]添加元素
[if !supportLists]l [endif]zadd key score member score2 member2 … :将所有成员以及该成员的分数存放到sorted-set中。如果该元素已经存在则会用新的分数替换原有的分数。返回值是新加入到集合中的元素个数,不包含之前已经存在的元素。
[if !supportLists]3.6.2.2 [endif]获得元素
[if !supportLists]l [endif]zscorekey member:返回指定成员的分数
[if !supportLists]l [endif]zcardkey:获取集合中的成员数量
[if !supportLists]3.6.2.3 [endif]删除元素
[if !supportLists]l [endif]zrem key member[member…]:移除集合中指定的成员,可以指定多个成员。
[if !supportLists]3.6.2.4 [endif]范围查询
[if !supportLists]l [endif]zrange key start end [withscores]:获取集合中脚标为start-end的成员,[withscores]参数表明返回的成员包含其分数。
[if !supportLists]l [endif]zrevrange key start stop [withscores]:照元素分数从大到小的顺序返回索引从start到stop之间的所有元素(包含两端的元素)
[if !supportLists]l [endif]zremrangebyrank key start stop:按照排名范围删除元素
[if !supportLists]l [endif]zremrangebyscore key min max:按照分数范围删除元素
[if !supportLists]3.6.3 [endif]扩展命令(了解)
[if !supportLists]l [endif]zrangebyscore key min max [withscores] [limit offset count]:返回分数在[min,max]的成员并按照分数从低到高排序。[withscores]:显示分数;[limit offset count]:offset,表明从脚标为offset的元素开始并返回count个成员。
[if !supportLists]l [endif]zincrby key increment member:设置指定成员的增加的分数。返回值是更改后的分数。
[if !supportLists]l [endif]zcount key min max:获取分数在[min,max]之间的成员
[if !supportLists]l [endif]zrank key member:返回成员在集合中的排名。(从小到大)
[if !supportLists]l [endif]zrevrank key member:返回成员在集合中的排名。(从大到小)
[if !supportLists]3.6.4 [endif]使用场景
1、可以用于一个大型在线游戏的积分排行榜。每当玩家的分数发生变化时,可以执行ZADD命令更新玩家的分数,此后再通过ZRANGE命令获取积分TOPTEN的用户信息。当然我们也可以利用ZRANK命令通过username来获取玩家的排行信息。最后我们将组合使用ZRANGE和ZRANK命令快速的获取和某个玩家积分相近的其他用户的信息。
2、Sorted-Set类型还可用于构建索引数据。
[if !supportLists]第4章 [endif]keys的通用操作
[if !supportLists]l [endif]keyspattern:获取所有与pattern匹配的key,返回所有与该key匹配的keys。*表示任意一个或多个字符,?表示任意一个字符
[if !supportLists]l [endif]del key1 key2…:删除指定的key
[if !supportLists]l [endif]exists key:判断该key是否存在,1代表存在,0代表不存在
[if !supportLists]l [endif]renamekey newkey:为当前的key重命名
[if !supportLists]l [endif]expire key:设置过期时间,单位:秒
[if !supportLists]l [endif]ttlkey:获取该key所剩的超时时间,如果没有设置超时,返回-1。如果返回-2表示超时不存在。
[if !supportLists]l [endif]type key:获取指定key的类型。该命令将以字符串的格式返回。 返回的字符串为string、list、set、hash和zset,如果key不存在返回none。