一、说明
(1)Redis是可基于内存也可持久化的Key-Value数据库(非关系性数据库),做缓存时数据存储在内存,做持久化时存储在硬盘。
(2)单线程但纯内存操作(最主要)、非阻塞IO、避免线程切换和竞争引起的消耗 所以速度很快,其单条命令操作都是原子性的。
(3)可用作数据库,高速缓存和消息队列代理(具备发布订阅功能,一个或多个消费者订阅一个频道)。
(4)redis支持高可用与分布式。高可用(Redis-Sentinel支持)、分布式(Redis-Cluster支持)
(5)Redis内存数据写入硬盘有一定的时间间隔,而在这个间隔内数据可能会丢失,尽管有办法降低数据丢失可能性,但还是有丢失的可能, 所以对数据有严格要求的不建议使用Redis做为数据库。
二、配置
redis的安装这里就不多做说明,只简单说明下面几个配置的含义(redis.conf):
daemonize:是否守护进程(yes/no)
port:设置对外端口
logfile:Redis系统日志
dir:redis工作目录
requirepass:配置密码
logfile:配置日志文件名称
另外在linux可通过如下命令查看、登录redis:
ps -ef|grep redis //查看启动的redis服务
netstat -antpl |grep redis //查看redis启动端口
redis-cli -h xxx -p xxx -a pwd //客户端带ip、端口、密码登录
三、命令使用
redis支持string,list,set,zset(有序集合),hash五种数据类型
1、String
string存储的元素类型可为string/int/float,int类型可进行增加和减少操作。可用于做缓存、计数器、分布式锁。(getbit、setbit不讲解)
//get|set|del
set a b //设置key为a,value为b
get a //获取key为a的value值
del a //删除key为a
//incr|decr|decrby|incrby|incrbyfloat
set c 1
//加减操作过程,若key不存在,则操作完key对应的value为加减对应的数字
incr c //对key为c的value进行加一操作,decr自减
decrby c 2 //对key为c的value进行减2操作,incrby 加操作
incrbyfloat key 3.5 //对key的value加3.5
//set|setnx|set xx|setex
set key value //设置,key存在则覆盖
setnx key value //设置,key不存在才设置
set key value xx //key存在才设置,在set最后加上 xx
setex key seconds value //设置key,同时定义在seconds秒后过期
//mget|mset
mget key1 key2 ... //批量获取多个key对应value,原子操作,1次网络时间+n次命令时间
mset key1 value1 key2 value2 ... //批量设置
//getset|append|strlen
getset key newvalue //将key的值覆盖为新值并回旧值
append key value //在原来value后面加字符串,如原来value为22,执行的value为33,则value为2233
strlen key //获取key对应value字符串长度,注意中文
//getrange|setrange
//getrange key start end :获取key对应value字符串的对应下标值,0开始
set a abcdef
getrange a 2 4 //获取到的为 cde
//setrange key index val :设置key对应value字符串的下标为index的值为val
set a abcdef
setrange a 3 r //则a对应的value变为abcref
2、list
list类型是一个有序的列表,元素可以重复。
lpush list1 a //向list1集合左边加入a
lpush list1 b
rpush list1 c //向list1集合右边加入c,此刻list1为 b a c
lpop list1 //拿出list1集合左边第一位元素b
rpop list1 //拿出list1集合右边第一位元素c
llen list1 //获取list1集合元素个数
lpushx list1 n //list1集合存在时才添加元素
rpush key value1 value2 ... //向集合右边依次添加多个元素
linsert key before|after value newvalue //在key集合的value值前后插入一个新值,时间复杂度:O(n)
lrem key count value //从key集合左边开始删除count个值为value的元素。
count>0 从左到右删;<0 从右到左删,既-2表删右边第1,2个value;0表示所有等于value的都删
ltrim key start end //删除下标范围外的元素,0开始 时间复杂度:O(n)
lrange key start end //取key集合下标范围内的元素,最后一位为-1,倒数第二位-2 时间复杂度:O(n)
lindex key index //获取左边开始指定索引index对应的value,0开始 时间复杂度:O(n)
lset key index newValue //将key集合中下标index下的元素改为newValue
3、set
set类型用无序的方式存储元素,可以快速对元素中的值添加删除,检查某些值是否存在,重复的元素是无法继续插入集合的。
sadd set1 a //向set1集合加入元素a,当a存在则添加失败
sadd set1 b c d //添加多个元素
scard set1 //查看set1集合元素个数
smembers set1 //获取set1集合中的所有元素
srem set1 a //删除set1集合中的a元素
sismember set1 b //查看set1集合是否含b,返回1则存在
srandmember set1 3 //从set集合中随机挑3个元素,操作完集合不变
spop set1 //从集合随机拿出一个元素,该元素将删除
sinter set1 set2 //获取set1、set2集合的交集
sunion set1 set2 //获取set1、set2集合的并集
sdiff set1 set2 //获取set1、set2集合的差集
4、hash
hash类型也叫散列类型,存储的是键值对。
hset hash1 key1 a //向hash类型的集合hash1中放入 (key1,a) 的键值对
hset hash1 key2 b //向hash类型的集合hash1中放入 (key2,b) 的键值对
hget hash1 key1 //获取hash1集合中key为key1对应的value
hlen hash1 //查看hash1中键值对个数
hdel hash1 key1 //删除hash1集合中的key1的键值对
hmget hash1 key1 key2 //获取hash1集合中key为key1和key2的多个value
hmset hash1 key3 value3 key4 value4 //向hash1集合添加多个键值对
hexists hash1 key2 //hash集合hash1中是否有key2对应的键值对
hincrby hash1 key5 2 //加2,hincrbyfloat,减可以-2
hsetnx hash1 key4 value //当hash1集合中不存在key4对应键值对才设置成功
hgetall hash1 //获取hash1所有键值对key和value
hvals hash1 //获取hash1所有键值对中的值 value
hkeys hash1 //获取hash1所有键值对中的键 key
时间复杂度: hget 、hset、hdel、hexists、hincrby 为 O(1) ; hgetall、hvals、hkeys、hmget、hmset 为 O(n)
5、zset
zset 也称 sore set(有序分数集),可以把它看作一个排行榜,排行榜中还有一个排名的属性,排行属性从0,根据分数不断变大,排行也不断变大。sore set中的值是全局唯一的,会覆盖修改。如果有两条分数相同,会根据值两个元素变量名的字典排序顺序排列先后。下面例子中,时间复杂度:N表示集合元素个数,M表示被操作的元素个数
zadd zset1 10 a //向zset1集合中添加元素a,且a的分数为10,可一次加多个
zadd zset1 11 b //向zset1集合中添加元素b,且b的分数为11
zadd zset1 9 c
zcard zset1 //查看集合元素个数,时间复杂度:O(1)
zscore zset1 b //获取元素b的分数,时间复杂度:O(1)
zrem zset1 a c //删集合中的多个元素
zcount zset1 6 10 //获取集合中分数在6到9之间的元素个数(闭区间),时间复杂度:O(log(N)+M)
zincrby zset1 5 b //将集合中的元素b的分数加5,如果元素不存在,该命令将添加该元素并假设其初始分数为0,此后再将其分数加上5。时间复杂度:O(1)
zrank zset1 b //查看b排在第几位 ,0开始,所以显示 2,时间复杂度:O(log(N))
zrevrank zset1 b //同zrank,获得元素的排名(元素分数从大到小排序),时间复杂度:O(log(N))
zrange zset1 //列出集合中所有元素 ,既a b c
zrange zset1 0 1 withscores //查看排在0到1的值和分数按照排名,既c 9 ;a 10;
另外,当a,c分数相同时,a排在前;时间复杂度:O(log(N)+M),m表示查到的元素个数
zrevrange zset1 0 1 [withscores] //同上,只是从大到小排列,既a 10 ;c 9;
zrangebyscore key min max [WITHSCORES] [LIMIT offset count] //获得分数在min到max范围(闭区间)的元素,分数从低到高的顺序返回,可选参数LIMIT用于限制返回成员的数量范围。可选参数offset表示从符合条件的第offset个成员开始返回,同时返回count个成员。时间复杂度:O(log(N)+M)
zrevrangebyscore key max min [WITHSCORES] [LIMIT offset count] //基本同上,列出的顺序从大到小
zremrangebyrank key start stop //从小到大排,删除索引位置位于start和stop之间的成员,时间复杂度:O(log(N)+M)
zremrangebyscore key start stop //删除指定分数范围内的元素,时间复杂度:O(log(N)+M)
6、通用命令
八个通用命令:keys、exists、del、dbsize、type、expire、ttl、persist
keys * //查出所有key,数据多会较久,生产环境慎用,keys 后面可跟正则,列出对应key
keys he* //列出he开头的key
exists a //查看为a的key有没存在,返回1则存在,0不存在
del a //删除某个key,这里删除key为a
dbsize //计算数据库中key总数
type a //查看key为a的数据类型
expire a 2 //设置a在两秒后过期,expire key seconds,即key在seconds秒后过期,key本身存在
ttl key //查看key剩余过期时间,-2表示key已不存在,-1表示没过期时间
persist key //去掉key过期时间
时间复杂度:除了keys 为 O(n),其他几个命令为 O(1)
7、其他
(1)一个redis实例最多提供下标为0到15的16个数据库,默认使用第0个
select 1 //切换到第2个数据库,select num
move list1 3 //将当前数据库中的list1集合移动到第4个数据库
(2) 通过java代码连接redis的demo(引入jedis)
构造函数:Jedis(String host,int port,int connectionTimeout,int soTimeout)
host:服务端ip、port:redis服务端口
connectionTimeout:客户端连接超时时间
soTimeout:客户端读写超时时间
Jedis jedis = new Jedis(“192.168.1.1”,6379);
jedis.set(“hi”,”hehe”); //hset,rpush各种跟命令一致的方法
jedis.get(“hi”);
使用连接池
GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
JedisPool jedisPool = new JedisPool(poolConfig,”127.0.0.1”,6379);
Jedis jedis=null;
try{
jedis=jedisPool.getResource();
jedis.xxxx;
}catch{
}finally{
//jedis.close();
}
(3)慢查询
1、定义:我们将命令执行时间超过指定时间的查询称为慢查询,通过分析这些慢查询并对这些查询进行优化可以提高系统性能。
在redis服务端中,会有一个慢查询队列,当执行语句符合慢查询则会被放入该队列。该队列长度有限,即随着加入的慢查询条数的增加,旧的慢查询会被挤出慢查询队列。
2、redis在执行命令时会经过如下过程:
- client发送命令到redis服务端
- 服务端接收到命令之后将命令放到队列
- redis服务端依次执行队列中的命令
- 返回结果给客户端
其中慢查询指的就是上面的第三步的过程,即查询语句在服务端的执行时间。所以不难看出客户端超时不一定是慢查询,也可能跟网络等有关,但慢查询是照成客户端超时的一个原因。
3、慢查询设计的两个配置
- slowlog-log-slower-than:慢查询阈值(微秒),当等于0 则会记录所有命令,当小于0则不会记录任何命令。
- slowlog-max-len:定义慢查询的队列长度,先进先出队列,固定长度,保存在内存
4、命令
- slowlog get [n] 获取慢查询队列中N的命令
- slowlog len 获取慢查询队列长度
- slowlog reset 清空慢查询队列
5、建议
- slowlog-log-slower-than 不要设置过大,默认10ms,一般设置1ms
- slowlog-max-len 不要设置太小,一般1000
- 定期持久化慢查询以便后面可以进行慢查询的命令分析,不持久化则会因为重启或挤出而无法找到
(4)发布订阅功能
三个角色:发布者、订阅者、频道
其中发布者、订阅者都是相对客户端而言,即客户端称为发布者或订阅者,而频道则相当于服务端提供的一个专有管道。
- 订阅频道:客户端执行:subscribe channel(即订阅某个频道),如 subscribe one(表示订阅频道one)
- 发布消息:客户端执行:publish channel message(即向某个频道发消息),如 publish one "hello" (向频道one发“hello”消息,返回订阅该频道的个数),这时上面的订阅者客户端将收到hello消息
- 取消订阅:客户端执行:unsubscribe channel(即取消订阅某个频道)
(5)geo
定义:redis在3.2版本后添加的,用于存储一个地理位置的经纬度,方面计算地方氛围、距离等的数据类型,其实际类型为zset,一些zset命令可用。
api:
1、geoadd key 经度 维度 地址 :添加某个地理位置
如 geoadd citys 116.69 23.39 shantou :添加汕头的地理位置到citys集合,汕头的地理位置为
2、geopos key 地址 :获取地理位置
如 geopos citys shantou :获取citys中汕头的经纬度
3、geodist key 地址1 地址2 [单位] : 计算两个地理位置之间的距离,可设置距离单位
如 geodist citys shantou beijing km :计算汕头跟北京的距离