做的网站访问不了,二级建造师报名的官网,WordPress不能新建页面,廊坊公司快速建站简单的kafkaredis学习之redis 
2. Redis 
2.1 什么是Redis 
Redis是一种面向 “Key-Value” 数据类型的内存数据库#xff0c;可以满足我们对海量数据的快速读写需求#xff0c;Redis是一个 NoSQL 数据库#xff0c;NoSQL的全称是not only sql#xff0c;不仅仅是SQLredis学习之redis 
2. Redis 
2.1 什么是Redis 
Redis是一种面向 “Key-Value” 数据类型的内存数据库可以满足我们对海量数据的快速读写需求Redis是一个 NoSQL 数据库NoSQL的全称是not only sql不仅仅是SQL泛指非关系型数据库这种类型的数据库不支持SQL语法。 
首先Redis是一种内存数据库它的数据都是放在内存里面的然后Redis中存储的数据都是key-value类型的其中redis中的key只能是字符串value支持多种数据类型 
常见的有string、hash、list、set、sortedset等 
字符串 string哈希 hash类似于java中的hashmap字符串列表 list字符串集合 set 不重复无序有序集合sorted set 不重复有序 
2.2 Redis的特点 
接下来看一下Redis的一些特点 
高性能Redis读的速度是11W次/s,写的速度是8.1W次/s原子性保证数据的准确性持久存储支持两种方式的持久化RDB和AOF可以把内存中的数据持久化到磁盘中支持主从master-slave架构可以实现负载均衡、高可用支持集群从3.0版本开始支持 注意Redis是一个 单线程的服务作者之所以这么设计主要是为了保证redis的快速高效如果涉及了多线程就需要使用锁机制来解决并发问题这样执行效率反而会打折扣。 2.3 Redis安装部署 
下面来看一下redis的安装部署首先下载redis使用此链接下载可以显示Redis目前所有的版本 http://download.redis.io/releases/我们选择目前比较稳定的5.0.9版本。将下载好的安装包上传到bigdata04机器的/data/soft目录下 
将下载好的安装包上传到bigdata04机器的/data/soft目录下 1解压 
[rootbigdata04 soft]# tar -zxvf redis-5.0.9.tar.gz2编译安装 
[rootbigdata04 soft]# cd redis-5.0.9
[rootbigdata04 redis-5.0.9]# make
[rootbigdata04 redis-5.0.9]# make install只要不报错就说明编译安装成功。由于redis需要依赖于C语言环境yum install gcc如果你安装的centos镜像是精简版会缺失c语言的依赖所以需要安装C语言环境才可以编译成功。我们在这使用的centos镜像是完整版里面是包含C语言环境的所以就不存在这个问题了。 
如果yum install gcc后执行make报 [致命错误jemalloc/jemalloc.h没有那个文件或目录] 错误需要再执行 make MALLOClibc 
3修改redis.conf配置文件 
[rootbigdata04 redis-5.0.9]# vi redis.conf
daemonize yes
logfile /data/soft/redis-5.0.9/log
bind 127.0.0.1 192.168.182.103daemonize参数的值默认是no表示在前台启动Redis但是Redis是一个数据库我们希望把它放到后台运行所以将参数的值改为yeslogfile 参数的值默认为空表示redis会将日志输出到/dev/null里面也就是不保存了建议在这设置一个日志路径记录redis的日志便于后期排查问题。bind 参数可以绑定指定ip这样就可以通过这里指定的ip来访问redis服务了可以在后面指定当前机器的本地回环地址(127.0.0.1)和内网地址(192.168.182.103)指定本地回环地址是为了能够在本机自己连自己比较方便。指定内网地址是为了能够让公司局域网内的其它服务器也能连到这个redis 如果你这台机器有外网地址的话不建议在这配置因为使用外网地址的话就不安全了容易受到网络攻击。 
4启动redis 
shell
[rootbigdata04 redis-5.0.9]# redis-server redis.conf 5验证 注意redis不是java程序所以使用jps命令查不到需要使用ps命令查看redis的进程 shell
[rootbigdata04 redis-5.0.9]# ps -ef|grep redis
root       5828      1  0 16:12 ?        00:00:00 redis-server 127.0.0.1:63796连接redis数据库 
[rootbigdata04 redis-5.0.9]# redis-cli 
127.0.0.1:6379 注意使用redis-cli默认可以连接本地的redis 其实redis-cli后面省略了-h 127.0.0.1 和 -p 6379 
[rootbigdata04 redis-5.0.9]# redis-cli -h 127.0.0.1 -p 6379此时使用内网ip也能连接这样其实我们就可以在其它安装有redis-cli客户端的机器上连接这个redis服务了。 
[rootbigdata04 redis-5.0.9]# redis-cli -h 192.168.182.103 -p 6379
192.168.182.103:6379 7停止redis数据库 暴力一点的方式是使用kill命令直接杀进程 不过redis提供的有停止命令 
[rootbigdata04 redis-5.0.9]# redis-cli
127.0.0.1:6379 shutdown
not connected 或者这样停止也是可以的 
[rootbigdata04 redis-5.0.9]# redis-cli shutdown2.4 Redis基础命令 
下面我们来看一下Redis中的基础命令 先启动redis服务使用redis-cli客户端连到redis数据库里面 
[rootbigdata04 redis-5.0.9]# redis-server redis.conf
[rootbigdata04 redis-5.0.9]# redis-cli 
127.0.0.1:6379 获得符合规则的键keys keys 后面可以指定正则表达式 127.0.0.1:6379 keys *
(empty list or set)
127.0.0.1:6379 set a 1
OK
127.0.0.1:6379 keys *
1)a
127.0.0.1:6379 keys a*
1) a
127.0.0.1:6379 keys a
(empty list or set)注意在生产环境下建议禁用keys命令因为这个命令会查询过滤redis中的所有数据可能会造成服务阻塞影响redis执行效率。 如果有类似的查询需求建议使用scanscan命令用于迭代当前数据库中的key集合它支持增量式迭代每次执行只会返回少量元素所以它可以用于生产环境而不会出现像keys 命令那样可能会阻塞服务器的问题。 SCAN命令是一个基于游标的迭代器。这意味着命令每次被调用都需要使用上一次调用返回的游标作为该次调用的游标参数以此来延续之前的迭代过程 当SCAN命令的游标参数被设置为 0 时 服务器将开始一次新的迭代 而当服务器向用户返回值为 0 的游标时 表示迭代已结束。 向redis中初始化一批数据 127.0.0.1:6379 set a1 1
OK
127.0.0.1:6379 set a2 1
OK
127.0.0.1:6379 set a3 1
OK
127.0.0.1:6379 set a4 1
OK
127.0.0.1:6379 set a5 1
OK
127.0.0.1:6379 set a6 1
OK
127.0.0.1:6379 set a7 1
OK
127.0.0.1:6379 set a8 1
OK
127.0.0.1:6379 set a9 1
OK
127.0.0.1:6379 set a10 1
OK使用scan迭代数据后面游标参数指定为0表示从头开始迭代key 127.0.0.1:6379 scan 0
1) 3
2)  1) a92) a33) a14) a105) a86) a57) a48) a9) a710) a6SCAN 命令的返回值是一个包含两个元素的数组第一个元素是用于进行下一次迭代的新游标而第二个元素则是一个数组 这个数组中包含了所有被迭代出来的元素。默认情况下scan返回10条数据所以这样执行效果也是一样的 127.0.0.1:6379 scan 0 count 10
1) 3
2)  1) a92) a33) a14) a105) a86) a57) a48) a9) a710) a6scan命令此时返回的游标为3注意游标的值并不等于返回的数据量。如果想要继续往下面迭代数据的话下一次执行scan的时候需要指定之前返回的游标redis会根据这个游标继续往下面迭代 127.0.0.1:6379 scan 3 count 10
1) 0
2) 1) a2这一次使用scan命令返回的游标为0表示迭代已经结束整个redis中的key都被迭代完了。redis中一共有11个key第一次使用scan 0获取到了10个key第二次获取到了1个key没有问题。  注意大家在下面练习的时候可能会发现你那边第一次返回的游标和我这边显示的不一样那也很正常因为你会发现你返回的这个数据集的顺序也是不一样的。  所以如果redis中有很多key我们可以使用scan命令来迭代一次迭代一部分不至于造成阻塞如果redis中的key比较少那么使用keys * 也是可以的。如果想要在迭代key的时候对key进行过滤可以在scan后面指定match参数match后面可以指定正则表达式 127.0.0.1:6379 scan 0 match a[1-5] count 10
1) 3
2) 1) a32) a13) a54) a4此时实际返回的key的数量是4个但是游标还是3相当于还是迭代了10条数据只不过不满足条件的没有返回而已。  判断键是否存在exists 127.0.0.1:6379 exists a
(integer) 1
127.0.0.1:6379 exists b
(integer) 0删除键del 127.0.0.1:6379 del a
(integer) 1注意del也支持一次删除多个key  127.0.0.1:6379 del a1 a2
(integer) 2获得键值的类型type 返回值可能是这五种类型string,hash,list,set,zset 127.0.0.1:6379 set a 1
OK
127.0.0.1:6379 type a
string这个命令可以帮我们快速识别某一个key中存储的数据是什么类型的因为针对存储了不同类型值的key操作的命令是不一样的。  帮助命令help 127.0.0.1:6379 help setSET key value [EX seconds] [PX milliseconds] [NX|XX]summary: Set the string value of a keysince: 1.0.0group: string退出客户端quit/exit 127.0.0.1:6379 quit不过我还是习惯使用ctrlc退出redis-cli客户端最后有一点需要注意Redis的命令不区分大小写但是key的名称需要区分大小写  
2.5 Redis多数据库特性 
Redis默认支持 16 个数据库通过databases参数控制的 这个参数在redis.conf配置文件中 
[rootbigdata04 redis-5.0.9]# cat redis.conf | grep databases
# Set the number of databases. The default database is DB 0, you can select
# dbid is a number between 0 and databases-1
databases 16
# Compress string objects using LZF when dump .rdb databases?每个数据库对外都是以一个从0开始的递增数字命名不支持自定义 
Redis默认选择的是0号数据库可以通过 select 命令切换 
127.0.0.1:6379 select 0
OK
127.0.0.1:6379 select 1
OK
127.0.0.1:6379[1] select 2
OK
127.0.0.1:6379[2] select 15
OK
127.0.0.1:6379[15] select 16
(error) ERR DB index is out of range一般在工作中会使用2~3个数据库可以根据业务类型来分库不同业务的数据存到不同的库里面还有一种用法是一个库作为测试库一个库作为正式库。 
如果没有特殊需求一般使用0号数据库就可以了这个库使用起来比较方便默认就是0号库不需要使用select切换。具体在工作中怎么用都行只要理解它的特性就可以了。但是有一点需要注意多个数据库之间并不是完全隔离的如果使用flushall命令则会清空redis中所有数据库内的数据。 
并且我们在redis中使用多个库并不能提高redis的存储能力因为默认这16个库共用redis的内存存储空间如果想要提高redis的存储能力需要给我们的服务器增加内存才可以。 
127.0.0.1:6379[15] set x 1
OK
127.0.0.1:6379[15] flushall
OK
127.0.0.1:6379[15] keys *
(empty list or set)
127.0.0.1:6379[15] select 0
OK
127.0.0.1:6379 keys *
(empty list or set)如果只想清空当前数据库中的数据可以使用flushdb 
127.0.0.1:6379 select 15
OK
127.0.0.1:6379[15] set a 1
OK
127.0.0.1:6379[15] keys *
1) a
127.0.0.1:6379[15] flushdb
OK2.6 Redis数据类型 
下面来看一下redis中的常用数据类型这些数据类型都是针对于redis中的value而言的因为key都是字符串 
stringhashlistsetsorted set 
2.6.1 Redis数据类型之string 
字符串类型是redis中最基本的数据类型它能存储任何形式的内容包含二进制数据甚至是一张图片 一个字符串类型的值存储的最大容量是1GB一般情况下我们存储的单条数据肯定是达不到的这个限值的所以大家不用担心 string类型比较适合存储类型单一的数据 针对string类型主要有下面这些常见命令 
命令格式解释setset key value给key设置一个Value(字符串类型的)getget key获取key的值incrincr key对key的值递加1(值必须是数字)decrdecr key对key的值递减-1(值必须是数字)strlenstrlen key获取key值的长度 
添加数据 set 
127.0.0.1:6379 set str a
OK 
查询数据 get 
127.0.0.1:6379 get str
a 
一次添加多条数据 
127.0.0.1:6379 mset str1 a1 str2 a2
OK 
一次查询多条数据 
127.0.0.1:6379 mget str1 str2
1) a1
2) a2递增1 
127.0.0.1:6379 set num 1
OK
127.0.0.1:6379 incr num
(integer) 2
127.0.0.1:6379 get num
2递减1 
127.0.0.1:6379 decr num
(integer) 1
127.0.0.1:6379 get num
1递增指定数值(整数类型) 
127.0.0.1:6379 incrby num 2
(integer) 3
127.0.0.1:6379 get num
3
127.0.0.1:6379 incrby num 2.1
(error) ERR value is not an integer or out of range[注意增量数值只支持integer类型]递减指定数值(整数类型) 
127.0.0.1:6379 decrby num 2
(integer) 1
127.0.0.1:6379 get num
1递增指定数值(float类型) 
127.0.0.1:6379 incrbyfloat num 2.1
3.1
127.0.0.1:6379 get num
3.1获取指定key的value长度 
127.0.0.1:6379 get str
a
127.0.0.1:6379 strlen str
(integer) 1
127.0.0.1:6379 set str abcd
OK
127.0.0.1:6379 strlen str
(integer) 42.6.2 Redis数据类型之hash 
hash类型的值存储了字段和字段值的映射字段和字段值只能是字符串不支持其他数据类型。hash类型的值至多存储2的32次方-1个字段一般情况下我们也达不到这个极限hash类型比较适合存储对象因为对象里面是有一些属性和值的我们就可以把这些属性和值存储到这个hash类型里面 针对hash类型主要有下面这些常见命令 
命令格式解释hsethset key field value向hash中添加字段和值hgethget key field获取hash中指定字段的值hgetallhgetall key获取hash中所有的字段和值hexistshexists key field判断hash中是否包含指定字段hincrbyhincrby key field num对hash中指定字段的值递增hdelhdel key field删除hash中指定的字段hkeys/hvalshkeys/hvals key获取hash中所有字段或字段值hlenhlen key获取hash中所有字段的数量 
添加数据 hget 
127.0.0.1:6379 hset user:1 name zs
(integer) 1查询数据 hget 
127.0.0.1:6379 hget user:1 name
zs向一个hash中同时添加多个k-v hmset 
127.0.0.1:6379 hmset user:2 name lisi age 18
OK查询一个hash数据中多个k的值 hmget 
127.0.0.1:6379 hmget user:2 name age
1) lisi
2) 18查询一个hash数据中的所有k-v hgetall 
127.0.0.1:6379 hgetall user:2
1) name
2) lisi
3) age
4) 18判断一个hash数据中是否存在指定k hexists 
127.0.0.1:6379 hexists user:2 name
(integer) 1
127.0.0.1:6379 hexists user:2 city
(integer) 0对一个hash数据中指定k的v进行递增 hincrby 
127.0.0.1:6379 hincrby user:2 age 1
(integer) 19
127.0.0.1:6379 hget user:2 age
19删除一个hash数据中的指定k hdel 
127.0.0.1:6379 hset user:2 city beijing
(integer) 1
127.0.0.1:6379 hdel user:2 city
(integer) 1获取一个hash数据中的所有k hkeys 
127.0.0.1:6379 hkeys user:2
1) name
2) age获取一个hash数据中的所有v hvals 
127.0.0.1:6379 hvals user:2
1) lisi
2) 19获取一个hash数据中有多少个k hlen 
127.0.0.1:6379 hlen user:2
(integer) 22.6.3 Redis数据类型之list 
list是一个有序的字符串列表列表内部是使用双向链表(linked list)实现的list列表类型的值最多可以存储2的32次方-1个元素一般我们也达不到这个限值。list类型比较适合作为队列使用使用lpushrpop可以实现先进先出的队列 
针对list类型主要有下面这些常见命令 
命令格式解释lpushlpush key value从列表左侧添加元素rpushrpush key value从列表右侧添加元素lpoplpop key从列表左侧弹出元素rpoprpop key从列表右侧弹出元素llenllen key获取列表的长度lrangelrange key start stop获取列表指定区间的元素lindexlindex key index获取列表指定角标的元素lsetlset key index value修改列表中指定角标的元素 
添加元素(左侧添加) lpush 
127.0.0.1:6379 lpush list1 a
(integer) 1
127.0.0.1:6379 lpush list1 b
(integer) 2取出元素(左侧取元素) lpop 
127.0.0.1:6379 lpop list1
b
127.0.0.1:6379 lpop list1
a
127.0.0.1:6379 lpop list1
(nil)添加元素(右侧添加) rpush 
127.0.0.1:6379 rpush list2 x
(integer) 1
127.0.0.1:6379 rpush list2 y
(integer) 2取出元素(右侧取元素) rpop 
127.0.0.1:6379 rpop list2
y
127.0.0.1:6379 rpop list2
x列表长度 llen 
127.0.0.1:6379 lpush list3 a b c d
(integer) 4
127.0.0.1:6379 llen list3
(integer) 4获取列表中的元素 lrange 
127.0.0.1:6379 lrange list3 0 -1
1) d
2) c
3) b
4) a查询指定角标元素 lindex 
127.0.0.1:6379 lindex list3 1
c修改指定角标元素 lset 
127.0.0.1:6379 lset list3 1 m
OK
127.0.0.1:6379 lrange list3 0 -1
1) d
2) m
3) b
4) a2.6.4 Redis数据类型之set 
set是一个集合set集合中的元素都是不重复的无序的。set集合类型的值最多可以存储2的32次方-1个元素。set集合比较适合用在去重的场景下因为它里面的元素是都不重复的 
针对set类型主要有下面这些常见命令 
命令格式解释saddsadd key value向集合中添加元素smemberssmembers key获取集合中所有元素sremsrem key value从集合中删除指定元素sismembersismember key value判断集合中是否包含指定元素sdiffsdiff key1 key2获取两个集合的差集sintersinter key1 key2获取两个集合的交集sunionsunion key1 key2获取两个集合的并集scardscard key获取集合中元素的数量 
向集合中添加元素 sadd 
127.0.0.1:6379 sadd set1 a
(integer) 1
127.0.0.1:6379 sadd set1 b
(integer) 1获取集合中所有元素 smembers 
127.0.0.1:6379 smembers set1
1) b
2) a删除集合中的元素 srem 
127.0.0.1:6379 srem set1 a
(integer) 1判断元素是否存在集合中 sismember 
127.0.0.1:6379 sismember set1 b
(integer) 1
127.0.0.1:6379 sismember set1 a
(integer) 0两个集合取差集 sdiff 
127.0.0.1:6379 sadd set2 a b c
(integer) 3
127.0.0.1:6379 sadd set3 a b x
(integer) 3
127.0.0.1:6379 sdiff set2 set3
1) c
127.0.0.1:6379 sdiff set3 set2
1) x两个集合取交集 sinter 
127.0.0.1:6379 sinter set2 set3
1) b
2) a两个集合取并集 sunion 
127.0.0.1:6379 sunion set2 set3
1) c
2) a
3) x
4) b获取集合长度(获取集合中元素的个数) scard 
127.0.0.1:6379 scard set3
(integer) 32.6.5 Redis数据类型之sorted set 
有序集合在集合类型的基础上为集合中的每个元素都关联了一个分数根据分数进行排序这样就实现了有序。sorted set比较适合用在获取TopN的场景因为它里面的数据是有序的 
针对sorted set类型主要有下面这些常见命令 
命令格式解释zaddzadd key value向集合中添加元素zscorezscore key value获取集合中指定元素的分值zrangezrange key value获取集合指定元素的排名(正序)zrevrange格式同上获取集合指定元素的排名(倒序)zincrbyzincrby key num value给集合中指定元素增加分值zcardzcard key获取集合中元素的数量zremzrem key value从集合中删除指定元素 
向集合中添加元素 zadd 
127.0.0.1:6379 zadd zset1 5 a
(integer) 1
127.0.0.1:6379 zadd zset1 3 b
(integer) 1
127.0.0.1:6379 zadd zset1 4 c
(integer) 1查询集合中指定元素的分值 zscore 
127.0.0.1:6379 zscore zset1 a
5根据角标获取集合中的元素(按照正序) zrange 
127.0.0.1:6379 zrange zset1 0 -1
1) b
2) c
3) a根据角标获取集合中的元素(按照倒序) zrevrange 
127.0.0.1:6379 zrevrange zset1 0 -1
1) a
2) c
3) b对集合中元素的分值进行递增 zincrby 
127.0.0.1:6379 zincrby zset1 3 a
8
127.0.0.1:6379 zscore zset1 a
8获取集合中元素的个数 zcard 
127.0.0.1:6379 zcard zset1
(integer) 3删除集合中的元素 zrem 
127.0.0.1:6379 zrem zset1 a
(integer) 1
127.0.0.1:6379 zrange zset1 0 -1
1) b
2) csorted set使用注意点 
1inf(正无穷) -inf(负无穷)在给集合中的元素设置分值的时候可以使用这两个特殊数值。2set命令如果key持有其它类型值set会覆盖旧值无视类型 
2.6.6 eg:存储高一班的学员信息 
需求将学员的姓名、年龄、性别、住址信息保存到Redis中分析一下 
在这里我们可以把学生认为是一个对象学生对象具备了多个属性信息姓名年龄性别住址信息 所以针对学生信息非常适合使用hash类型进行存储 我们可以给学生生成一个编号拼接到key里面姓名、年龄、性别、住址信息存储到hash类型的value中 注意这里面针对key的命名stu是student的简写尽量不要写太多字符否则会额外占用内存空间的后面的:1表示这个学生的编号是1后期如果我们想获取所有学员的key就可以使用这个规则进行过滤了。 这个规则进行过滤了。 127.0.0.1:6379 hmset stu:1 name xiaoming age 18 sex 0 address beijing
OK
127.0.0.1:6379 hgetall stu:1
1) name
2) xiaoming
3) age
4) 18
5) sex
6) 0
7) address
8) beijing
127.0.0.1:6379 hget user:1 age
182.7 JAVA操作redis 
在这我们以java代码为例演示一下如何使用java代码操作redis我们需要借助于第三方jar包jedis来操作首先在idea中创建maven项目db_redis。在pom.xml文件中添加jedis依赖 
dependencygroupIdredis.clients/groupIdartifactIdjedis/artifactIdversion3.3.0/version
/dependency2.7.1 单连接方式 
接下来使用单连接的方式操作redis代码如下 
package cn.git.redis;import redis.clients.jedis.Jedis;/*** 单连接方式操作redis* Created by lixuchun*/
public class RedisSingle {/*** 注意此代码能够正常执行的前提是* 1redis所在服务器的防火墙需要关闭* 2redis.conf中的bind参数需要指定192.168.182.103* param args*/public static void main(String[] args) {//获取jedis连接Jedis jedis  new Jedis(192.168.182.103,6379);//向redis中添加数据keygitvaluehello bigdata!jedis.set(git,hello bigdata!);//从redis中查询keygit的value的值String value  jedis.get(git);System.out.println(value);//关闭jedis连接jedis.close();}
}代码执行效果如下hello bigdata!此时到redis中确认一下 
127.0.0.1:6379 keys *
1) git
127.0.0.1:6379 get git
hello bigdata!其实在这你会发现我们前面讲的那些在redis-cli中使用的命令和jedis中提供的函数名称是一一对应的。切换到代码中来使用也是可以直接上手的。 
2.7.2 连接池方式 
接下来使用连接池的方式操作redis代码如下 
package cn.git.redis;import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;/*** 连接池的方式操作redis* Created by lixuchun*/
public class RedisPool {public static void main(String[] args) {//创建连接池配置对象JedisPoolConfig poolConfig  new JedisPoolConfig();//连接池中最大空闲连接数poolConfig.setMaxIdle(10);//连接池中创建的最大连接数poolConfig.setMaxTotal(100);//创建连接的超时时间poolConfig.setMaxWaitMillis(2000);//表示从连接池中获取连接的时候会先测试一下连接是否可用这样可以保证取出的连接都是可用的poolConfig.setTestOnBorrow(true);//获取jedis连接池JedisPool jedisPool  new JedisPool(poolConfig, 192.168.182.103, 6379);//从jedis连接池中取出一个连接Jedis jedis  jedisPool.getResource();String value  jedis.get(git);System.out.println(value);//注意此处的close方法有两层含义//1如果jedis是直接创建的单连接此时表示直接关闭这个连接//2如果jedis是从连接池中获取的连接此时会把这个连接返回给连接池jedis.close();//关闭jedis连接池jedisPool.close();}
}执行结果hello bigdata! 
2.7.3 提取RedisUtils工具类 
基于redis连接池的方式提取RedisUtils工具类 
package cn.git.redis;import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;/*** 基于redis连接池提取redis工具类* Created by lixuchun*/
public class RedisUtils {//私有化构造函数禁止newprivate RedisUtils(){}private static JedisPool jedisPool  null;//获取连接public static synchronized Jedis getJedis(){if(jedisPoolnull){JedisPoolConfig poolConfig  new JedisPoolConfig();poolConfig.setMaxIdle(10);poolConfig.setMaxTotal(100);poolConfig.setMaxWaitMillis(2000);poolConfig.setTestOnBorrow(true);jedisPool  new JedisPool(poolConfig, 192.168.182.103, 6379);}return jedisPool.getResource();}//向连接池返回连接public static void returnResource(Jedis jedis){jedis.close();}}使用工具类代码 
package cn.git.redis;import redis.clients.jedis.Jedis;/*** Created by lixuchun*/
public class TestRedisUtils {public static void main(String[] args) {//获取连接Jedis jedis  RedisUtils.getJedis();String value  jedis.get(git);System.out.println(value);//向连接池返回连接RedisUtils.returnResource(jedis);}
}2.8 高级特性 
2.8.1 expire 生存时间 
Redis中可以使用expire命令设置一个键的生存时间到时间后Redis会自动删除它 它的一个典型应用场景是手机验证码 我们平时在登录或者注册的时候手机会接收到一个验证码上面会提示验证码的过期时间过了这个时间之后这个验证码就不能用了。 
expire支持以下操作 
命令格式解释expireexpire key seconds设置key的过期时间(单位秒)ttlttl key获取key的剩余有效时间persistpersist key取消key的过期时间expireatexpireat key timestamp设置UNIX时间戳的过期时间 
设置key的过期时间 
127.0.0.1:6379 set abc 123
OK
127.0.0.1:6379 expire abc 200
(integer) 1获取key的剩余有效时间 
127.0.0.1:6379 ttl abc
(integer) 192取消key的过期时间 
127.0.0.1:6379 persist abc
(integer) 1此时再查看这个key的剩余有效时间返回的值是-1-1表示这个key是一个永久存在的key 
127.0.0.1:6379 ttl abc
(integer) -1还可以通过expireat指定key在指定时间点过期 先获取当前时间戳 
[rootbigdata04 ~]# date %s
1768618628127.0.0.1:6379 expireat abc 1768618638
(integer) 1过一会再查看这个key的剩余有效时间返回的是-2表示这个key被删除了不存在了 
127.0.0.1:6379 ttl abc
(integer) -2
127.0.0.1:6379 exists abc
(integer) 0总结一下 当key永久存在的时候执行ttl返回的是-1 当key被设置了过期时间之后执行ttl返回的就是这个key剩余的有效时间 当key已经被删除了不存在的时候执行ttl返回的是-2 
2.8.2 pipeline 管道 
针对批量操作数据或者批量初始化数据的时候使用效率高Redis的pipeline功能在命令行中没有实现在Java客户端(jedis)中是可以使用的 
它的原理是这样的 不使用管道的时候我们每执行一条命令都需要和redis服务器交互一次 使用管道之后可以实现一次提交一批命令这一批命令只需要和redis服务器交互一次所以就提高了性能。 这个功能就类似于mysql中的batch批处理。 
接下来看一个案例案例初始化10万条数据需求使用普通方式一条一条添加和使用管道批量初始化进行对比分析 
代码如下 
package cn.git.redis;import redis.clients.jedis.Jedis;
import redis.clients.jedis.Pipeline;/*** pipeline(管道)的使用* Created by lixuchun*/
public class PipelineOp {public static void main(String[] args) {// 1不使用管道Jedis jedis  RedisUtils.getJedis();long start_time  System.currentTimeMillis();for(int i0;i100000;i){jedis.set(ai,ai);}long end_time  System.currentTimeMillis();System.out.println(不使用管道耗时(end_time-start_time));// 2使用管道Pipeline pipelined  jedis.pipelined();start_time  System.currentTimeMillis();for(int i0;i100000;i){pipelined.set(bi,bi);}pipelined.sync();end_time  System.currentTimeMillis();System.out.println(使用管道耗时(end_time-start_time));RedisUtils.returnResource(jedis);}}结果如下 
不使用管道耗时40887
使用管道耗时180在代码执行的过程中我们可以使用info命令观察数据库中的数据条数 
127.0.0.1:6379 info
# Keyspace
db0:keys200000,expires1,avg_ttl389945从这可以看出来针对海量数据的初始化管道可以显著提高初始化性能。 
2.8.3 info命令 
这里面参数比较多在这我们主要关注几个重点的参数 
# Redis 服务器版本
redis_version:5.0.9
# Redis服务的可执行文件路径
executable:/data/soft/redis-5.0.9/redis-server
# 启动Redis时使用的配置文件路径
config_file:/data/soft/redis-5.0.9/redis.conf
# 已连接客户端的数量
connected_clients:1
# Redis目前存储数据使用的内容
used_memory_human:15.01M
# Redis可以使用的内存总量和服务器的内存有关
total_system_memory_human:1.78G
# db0表示0号数据库keys表示0号数据库的key总量expires表示0号数据库失效被删除的key总量
db0:keys200001,expires1,avg_ttl3899452.8.4 Redis的持久化 
Redis持久化简单理解就是把内存中的数据持久化到磁盘中 可以保证Reids重启之后还能恢复之前的数据Redis支持两种持久化可以 单独使用 或者 组合使用 
RDB 和 AOF 
2.8.4.1 Redis持久化之RDB 
RDB是Redis默认的持久化机制RDB持久化是通过快照完成的当符合一定条件时Redis会自动将内存中的所有数据执行快照操作并存储到硬盘上默认存储在dump.rdb文件中 
[rootbigdata04 redis-5.0.9]# ll
....
-rw-r--r--.  1 root root 2955661 Jan 17 12:12 dump.rdb
......Redis什么时候会执行快照Redis执行快照的时机是由以下参数控制的这些参数是在redis.conf文件中的 
save 900 1
save 300 10
save 60 10000save 900 1 表示900秒内至少一个key被更改则进行快照这里面的三个时机哪个先满足都会执行快照操作。 
RDB持久化的优缺点 
RDB的优点由于存储的有数据快照文件恢复数据很方便RDB的缺点会丢失最后一次快照以后更改的所有数据因为两次快照之间是由一个时间差的这一段时间之内修改的数据可能会丢。 
2.8.4.2 Redis持久化之AOF 
AOF持久化是通过日志文件的方式默认情况下没有开启可以通过appendonly参数开启 
[rootbigdata04 redis-5.0.9]# vi redis.conf 
....
appendonly yes
....AOF日志文件的保存位置和RDB文件相同都是dir参数设置的默认的文件名是appendonly.aof 注意dir参数的值为. 表示当前目录也就是说我们在哪个目录下启动redisrdb快照文件和aof日志文件就产生在哪个目录下。 可以试验一下换一个目录启动redis发下redis中的数据是空的。关闭之后重新在之前的目录启动redis数据又回来了。 
AOF方式只会记录用户的写命令添加、修改、删除之类的命令查询命令不会记录因为查询命令不会影响数据的内容。 
那redis什么时候会把用户的写命令同步到aof文件中呢 
# appendfsync always
# appendfsync everysec
# appendfsync no三种配置解释如下 
appendfsync everysec默认是每秒钟执行一次同步操作。appendfsync always实现每执行一次写操作就执行一次同步操作但是这样效率会有点低。appendfsync no表示不主动进行同步由操作系统来做30秒执行一次。 
如果大家对数据的丢失确实是0容忍的话可以使用always。不过一般情况下redis中存储的都是一些缓存数据就算丢了也没关系程序还会继续往里面写新数据不会造成多大影响。 
2.9 Redis 的安全策略 
2.9.1 设置数据库密码 
默认情况下访问redis只要网络能通就可以直接访问这样其实是有一些不安全的不过我们一般会限制只能在内网访问这样其实问题也不大。 
redis针对这个问题也支持给数据库设置密码在redis.conf中配置 
[rootbigdata04 redis-5.0.9]# vi redis.conf 
....
requirepass admin
....重启redis服务 
[rootbigdata04 redis-5.0.9]# redis-cli shutdown
[rootbigdata04 redis-5.0.9]# redis-server redis.conf重新连接redis 
[rootbigdata04 redis-5.0.9]# redis-cli 
127.0.0.1:6379 get git
(error) NOAUTH Authentication required.
127.0.0.1:6379 auth admin
OK
127.0.0.1:6379get git
hello bigdata!在代码层面以后在使用的时候时候就需要使用auth方法先校验权限了。 
package com.git.redis;import redis.clients.jedis.Jedis;/*** 单连接方式操作redis* Created by xuwei*/
public class RedisSingle {/*** 注意此代码能够正常执行的前提是* 1redis所在服务器的防火墙需要关闭* 2redis.conf中的bind参数需要指定192.168.182.103* param args*/public static void main(String[] args) {// 获取jedis连接Jedis jedis  new Jedis(192.168.182.103,6379);// 使用密码jedis.auth(admin);// 向redis中添加数据keygitvaluehello bigdata!jedis.set(git,hello bigdata!);// 从redis中查询keygit的value的值String value  jedis.get(git);System.out.println(value);//关闭jedis连接jedis.close();}
}注意在实际工作中一般不会设置密码因为我们在这设置的密码是明文的其实意义也不大针对别有用心的人你这样设置是没有意义的。 
所以在实际工作中我们一般只需要控制好redis服务器的访问权限就可以了redis服务器的访问权限其实就是使用bind参数来设置的。所以再把刚才设置的密码取消掉直接把对应的配置注释掉即可。 
所以再把刚才设置的密码取消掉直接把对应的配置注释掉即可 
[rootbigdata04 redis-5.0.9]# vi redis.conf 
#requirepass admin2.9.2 bind参数的应用 
在实际工作中我们的服务器至少会有3个ip地址 
127.0.0.1 这个是本机回环地址192.168.10.14 这个是本机的内网地址还有一个是外网地址 
我们一般会使用bind绑定内网ip这样其实就限制了redis服务器的访问范围不会暴露在外网只需要运维同学做好网络的访问限制就可以了此时我们就可以认为redis是安全的了。 
2.9.3 命令重命名 
咱们前面讲过一个命令是flushall这个命令是很危险的它可以把redis中的所有数据全部清空 所以在实际工作中一般需要将这个命令给禁用掉防止误操作。 
在redis.conf配置文件中进行设置 
[rootbigdata04 redis-5.0.9]# vi redis.conf 
....
rename-command flushall 
....这样修改之后就把flushall命令给禁用掉了重启redis服务 
[rootbigdata04 redis-5.0.9]# redis-cli shutdown
[rootbigdata04 redis-5.0.9]# redis-server redis.conf重新连接redis 
[rootbigdata04 redis-5.0.9]# redis-cli 
127.0.0.1:6379 flushall
(error) ERR unknown command flushall, with args beginning with: 
127.0.0.1:6379 此时会提示未知命令。其实我们还可以选择在重命名的时候给这个命令起一个别名这样后期如果想使用的时候也是可以使用的。我们现在在后面直接指定的是空字符串 就是直接禁用了如果指定一个其它字符串就相当于起别名了。 
2.9.4 Redis实例最多存多少key 
一个Redis实例最多能存放多少key有没有限制Redis本身是不会限制存储多少key的但是Redis是基于内存的它的存储极限是系统中的可用内存值如果内存存满了那就无法再存储key了。 
2.9.5 Redis监控命令-monitor 
这个monitor命令是一把双刃剑。在实际工作中要慎用。先演示一下 
[rootbigdata04 redis-5.0.9]# redis-cli 
127.0.0.1:6379 monitor
OK执行代码RedisSingle.java中的代码然后会发现monitor监控到我们对redis的所有操作 
[rootbigdata04 redis-5.0.9]# redis-cli 
127.0.0.1:6379 monitor
OK
1768628815.007443 [0 192.168.182.1:60633] SET git hello bigdata!
1768628815.007797 [0 192.168.182.1:60633] GET gitmonitor可以监控我们对redis的所有操作如果在线上的服务器上打开了这个功能这里面就会频繁打印出来我们对redis数据库的所有操作这样会影响redis的性能所以说要慎用。 
但是在某些特殊的场景下面它是很有用的之前在工作中我遇到过一个很奇怪的问题redis中的一个key总是会莫名其妙的消失我的一个程序会定时向redis中写入一个key但是我发现这个key刚写进去然后一会就没了很奇怪当时我仔细排查了我的代码里面既没有设置失效时间也没有使用删除功能。 
所以这个key不是我的代码删的肯定是有其它的代码会删除这个key但是到底是哪的代码这个时候就不好排查了我们的业务机有几十台根本无从下手。 这个时候我突然想到了monitor这个命令虽然开启monitor会影响redis的性能但是这个时候需要排查问题使用一会也是可以接受的。 
所以就打开了monitor打开之后屏幕上就打印出来很多命令这样根本就看不清没办法追踪数据太多了。所以又想到了这个办法结合grep命令来操作这样就可以过滤出来对指定key的所有操作了。 
[rootbigdata04 redis-5.0.9]# redis-cli monitor | grep key
1768629282.484868 [0 192.168.182.1:52364] del key通过这条数据我们可以分析出来到底是哪台机器上的程序删除了这个key。然后再排查这台机器上都有哪些程序对应的去排查代码这样就快多了最终发现是有一个代码里面会定时删除这个key。这个就是monitor的典型应用。 文章转载自: http://www.morning.smxrx.cn.gov.cn.smxrx.cn http://www.morning.plflq.cn.gov.cn.plflq.cn http://www.morning.fcftj.cn.gov.cn.fcftj.cn http://www.morning.rjynd.cn.gov.cn.rjynd.cn http://www.morning.wbysj.cn.gov.cn.wbysj.cn http://www.morning.blqsr.cn.gov.cn.blqsr.cn http://www.morning.tqsmc.cn.gov.cn.tqsmc.cn http://www.morning.skql.cn.gov.cn.skql.cn http://www.morning.rfqkx.cn.gov.cn.rfqkx.cn http://www.morning.hxlch.cn.gov.cn.hxlch.cn http://www.morning.ryrpq.cn.gov.cn.ryrpq.cn http://www.morning.bsbcp.cn.gov.cn.bsbcp.cn http://www.morning.dsncg.cn.gov.cn.dsncg.cn http://www.morning.mysmz.cn.gov.cn.mysmz.cn http://www.morning.wrysm.cn.gov.cn.wrysm.cn http://www.morning.bpmfr.cn.gov.cn.bpmfr.cn http://www.morning.lanyee.com.cn.gov.cn.lanyee.com.cn http://www.morning.myzfz.com.gov.cn.myzfz.com http://www.morning.qdbcd.cn.gov.cn.qdbcd.cn http://www.morning.dmwck.cn.gov.cn.dmwck.cn http://www.morning.zlchy.cn.gov.cn.zlchy.cn http://www.morning.txlnd.cn.gov.cn.txlnd.cn http://www.morning.khclr.cn.gov.cn.khclr.cn http://www.morning.dqwkm.cn.gov.cn.dqwkm.cn http://www.morning.hffpy.cn.gov.cn.hffpy.cn http://www.morning.yghlr.cn.gov.cn.yghlr.cn http://www.morning.pymff.cn.gov.cn.pymff.cn http://www.morning.fsnhz.cn.gov.cn.fsnhz.cn http://www.morning.hgwsj.cn.gov.cn.hgwsj.cn http://www.morning.rcrnw.cn.gov.cn.rcrnw.cn http://www.morning.qnbck.cn.gov.cn.qnbck.cn http://www.morning.qyhcm.cn.gov.cn.qyhcm.cn http://www.morning.zwpzy.cn.gov.cn.zwpzy.cn http://www.morning.pfbx.cn.gov.cn.pfbx.cn http://www.morning.hsgxj.cn.gov.cn.hsgxj.cn http://www.morning.sqskm.cn.gov.cn.sqskm.cn http://www.morning.gmjkn.cn.gov.cn.gmjkn.cn http://www.morning.jnrry.cn.gov.cn.jnrry.cn http://www.morning.mldrd.cn.gov.cn.mldrd.cn http://www.morning.lhhkp.cn.gov.cn.lhhkp.cn http://www.morning.hxxyp.cn.gov.cn.hxxyp.cn http://www.morning.cjrmf.cn.gov.cn.cjrmf.cn http://www.morning.pxlsh.cn.gov.cn.pxlsh.cn http://www.morning.qbwtb.cn.gov.cn.qbwtb.cn http://www.morning.rymd.cn.gov.cn.rymd.cn http://www.morning.dfltx.cn.gov.cn.dfltx.cn http://www.morning.xwqxz.cn.gov.cn.xwqxz.cn http://www.morning.pluimers.cn.gov.cn.pluimers.cn http://www.morning.mplld.cn.gov.cn.mplld.cn http://www.morning.pdmml.cn.gov.cn.pdmml.cn http://www.morning.cxnyg.cn.gov.cn.cxnyg.cn http://www.morning.npcxk.cn.gov.cn.npcxk.cn http://www.morning.wdlg.cn.gov.cn.wdlg.cn http://www.morning.tbbxn.cn.gov.cn.tbbxn.cn http://www.morning.mtgkq.cn.gov.cn.mtgkq.cn http://www.morning.dqxnd.cn.gov.cn.dqxnd.cn http://www.morning.dfojgo.cn.gov.cn.dfojgo.cn http://www.morning.grxyx.cn.gov.cn.grxyx.cn http://www.morning.bchfp.cn.gov.cn.bchfp.cn http://www.morning.gqksd.cn.gov.cn.gqksd.cn http://www.morning.qtzk.cn.gov.cn.qtzk.cn http://www.morning.kzhgy.cn.gov.cn.kzhgy.cn http://www.morning.mynbc.cn.gov.cn.mynbc.cn http://www.morning.cspwj.cn.gov.cn.cspwj.cn http://www.morning.ngkgy.cn.gov.cn.ngkgy.cn http://www.morning.fqyxb.cn.gov.cn.fqyxb.cn http://www.morning.dpruuode.cn.gov.cn.dpruuode.cn http://www.morning.wnhml.cn.gov.cn.wnhml.cn http://www.morning.kycwt.cn.gov.cn.kycwt.cn http://www.morning.nfyc.cn.gov.cn.nfyc.cn http://www.morning.zlfxp.cn.gov.cn.zlfxp.cn http://www.morning.yjmlg.cn.gov.cn.yjmlg.cn http://www.morning.knrgb.cn.gov.cn.knrgb.cn http://www.morning.kntbk.cn.gov.cn.kntbk.cn http://www.morning.tgtwy.cn.gov.cn.tgtwy.cn http://www.morning.ntgrn.cn.gov.cn.ntgrn.cn http://www.morning.jnptt.cn.gov.cn.jnptt.cn http://www.morning.zfyfy.cn.gov.cn.zfyfy.cn http://www.morning.xdxpq.cn.gov.cn.xdxpq.cn http://www.morning.qbjrf.cn.gov.cn.qbjrf.cn