redis默认有16个数据库,默认使用第0个,
可以使用select 进行切换(如:select 3 ,切换到第四个)
查看DB大小:DBSIZE
清空当前数据库:flushdb
清空所有数据库:flushall
redis是单线程的(6.0以上为多线程),基于内存操作,CPU不是redis的性能瓶颈,
redis的瓶颈是机器的内存和网络带宽,既然可以使用单线程来实现,
就使用单线程了。多线程(CPU上下文切换)不一定比单线程效率高。
对于内存系统来说,如果没有上下文切换,效率就是最高的。
redis-benchmark 官方自带性能压力测试工具
具体参考菜鸟教程
redis-benchmark -h localhost -p 6379 -c 50 -n 10000
我的redis安装路径:/usr/local/bin
1根据我的配置启动服务:redis-server myconfig/redis.conf
2启动客户端连接:redis-cli -p 6379 -a 123456
3测试连接:ping
4测试set:set keyname jiutou
5测试get:get keyname
6查看所有key:keys *
7查看redis进程是否启动 :ps -ef|grep redis
8关闭redis:shutdown
9退出redis:exit
(具体命令查看redis官网命令帮助文档)
判断某个key是否存在:exists keyname (存在为1,不存在为0)
移除用del keyname
移动某个key到第1个数据库:move keyname 1
设置某个key一段时间后过期,单位是秒(如:十秒后过期expire keyname 10)
ttl keyname 查看key剩余过期时间
setex设置值一段时间后过期,单位是秒(如:十秒后过期setex keyname 10 “xxx”)
setnx设置一个值,没有值才会设置成功,setnx keyname “xxx”(在分布式锁常常使用)
查看某个数据是什么类型:type keyname
往字符串后追加字符串:append keyname “hello” ;当key不存在,相当于set一个key
获取字符串的长度:strlen keyname
自增一:incr keyname;自减一:decr keyname
设置步长,指定增量:incrby keyname 10
字符串范围:getrange keyname 0 3 (查看字符串0~3范围);0 -1获取全部
替换指定位置开始的字符串字符串:setrange keyname 1 xx
批量设置键值:mset keyname xxx keyname2 xxx keyname3 xxx ,如已存在就覆盖
批量获取key的值:mget keyname keyname2 keyname3
msetnx设置键值,原子性,要么一起成功,要么一起失败
对象
set user:1 {name:zhangsan,age:3} 设置一个user:1对象,值为json字符来保存一个对象
另一种设置方法:mset user:1:name zhangsan user:1:age 2
getset先获取再设置getset keyname xxx ,如存在先获取原值,再覆盖
String类型的使用场景:value除了字符串还可以是数字,
(计数器、统计多单位的数量、粉丝数、对象缓存存储)
List:
将一个值或多个值,插入到列表头部(左):lpush list xxx
将一个值或多个值,插入到列表尾部(右):rpush list xxx
获取list的值:lrange list 0 -1
获取列表的长度:llen list
通过下标截取指定的长度:ltrim list 1 2
通过下标获取list中某一个值:lindex list 1
移除list的第一个元素:lpop list
移除list的最后一个元素:rpop list
移除列表指定个数的值,精确匹配:lrem list 1 xxx
移除列表最后一个元素移动到新的列表中:rpoplpush list list2
将列表指定下标的值替换为另一个值,相当于更新替换,不存在则报错:lset list 0 xxx
将值插入到某个元素的前面或者后面:linsert list BEFORE xxx xxx1 或linsert list AFTER xxx xxx1
list优势{
可做消息队列:左边插入,右边取出(lpush rpop)
栈:左边插入,左边取出(lpush lpop)
}
Set:
值不重复,无序,可以抽随机
集合中添加值:sadd myset xxx
判断某值是否在set集合中:sismember myset xxx
获取set集合元素的个数:scard myset
移除set集合中的指定元素:srem myset xxx
查看set集合中的元素:smembers myset
随机抽取一个元素:srandmember myset
随机删除set集合中一个元素:spop myset
移动指定元素到另一个set集合中:smove myset myset2 xxx
查看两个set集合的差集:sdiff myset myset2
查看两个set集合的交集:sinter myset myset2
查看两个set集合的并集:sunion myset myset2
Hash(哈希):
map(key-vlaue)集合,key-这时候值是一个map集合
本质与String类型没有太大区别
添加一个具体的key-vlaue:hset myhash field1 xxx
添加多个key-vlaue:hmset myhash field1 xxx field2 xxx2
获取一个字段值:hget myhash field1
获取多个字段值:hmget myhash field1 field2
获取全部的数据:hgetall myhash
获取hash字段数量:hlen myhash
只获取所有field:hkeys myhash
只获取所有的value:hvals myhash
删除指定的key字段(对应vlaue值也删除):hdel myhash field1
判断hash中指定字段是否存在:hexists myhash field1
指定增量:hset myhash field1 5
指定值加一:hincrby myhash field1 1
指定值减一:hincrby myhash field1 -1
如果不存在可以设置(存在则不能设置):hsetnx myhash field4 xxx
hash可以做变更的数据,尤其是用户信息之类,经常变动的信息!
hash更适合对象的存储。String更适合字符串的存储。
Zset(有序集合):
在set的基础上,增加了一个值,set k1 v1 ,zset k1 score1 v1
添加一个值:zadd myset score xxx
查询所有值:zrange myset 0 -1
所有值按从大到小排序:zrevrange myset 0 -1
所有值按从小到大排序显示:zrangebyscore myset -inf +inf
显示全部用户排序并附带分数:zrangebyscore myset -inf +inf withscores
对分数小于2500的值进行排序:zrangebyscore myset -inf 2500 withscores
移除指定元素:zrem myset xxx
获取集合中个数:zcard myset
统计指定区间的成员数量:zcount myset 1 3
三种特殊数据类型
geospatial地理位置
规则:两级无法直接添加,我们一般下载城市数据,直接通过java程序一次性导入
参数:key 值(纬度,经度,名称)
添加地理位置:geoadd china:city 116.42 39.90 beijing
获取指定城市经纬度:geopos china:city beijing
查看两地之间直线距离:geodist china:city beijing shanghai km
单位:m表示单位为米,km千米,mi英里,ft英尺
以给定经纬度为中心,找出某一半径元素:georadius china:city 116.42 39.90 1000 km
(以116.42 39.90经纬度为中心,寻找方圆1000km的城市)
georadius china:city 116.42 39.90 1000 km withdist 显示到中心位置的距离及城市
georadius china:city 116.42 39.90 1000 km withcoord 显示距离内城市的经纬度
georadius china:city 116.42 39.90 1000 km withdist withcoord count 1 筛选显示数量
找出指定城市距离周围其他城市:georadiusbymember china:city beijing 1000 km
将二维经纬度转为一维字符串,两个字符串越接近,距离越近:
geohash china:city beijing chongqing
geo底层实现原理是Zset,所以我们可以使用Zset命令来操作geo。
查询所有城市:zrange china:city 0 -1
删除某城市:zrem china:city beijing
Hyperloglog:
基数(不重复的元素),可接受误差,占用内存是固定的。
可用来统计一些允许容错的数据个数。
创建第一组元素:pfadd mykey a b c d e f
统计mykey元素个数:pfcount mykey
合并两组,并集:pfmerge mykey3 mykey mykey2
Bitmaps:
位存储,可用于统计活跃、不活跃,打卡、未打卡等两个状态的数据,
Bitmaps位图,数据结构。操作二进制来记录,只有0 和1两个状态。
例:(
用bitmap来记录周一到周日的打卡,周一:1,周二:0,周三:0
setbit sign 0 1
setbit sign 1 0
setbit sign 2 0
查看周三是否打卡:
getbit sign 2
统计打卡天数:
bitcount sign
)
事务:
redis单条命令是保证原子性的,但事务不保证原子性!
一个事务所有命令都被序列化,执行过程按顺序执行!
一次性、顺序性、排他性。没有隔离级别概念。
所有命令在事务中,没有直接执行,只有发起执行命令才会执行。
编译型异常(代码错误,命令错误)事务所有命令不会被执行。
运行时异常(1/0等语法错误)其他命令正常执行,错误命令抛出异常。
redis事务:
开启事务(multi)
命令入队( .....)
执行事务(exec)
{
127.0.0.1:6379> multi
OK
127.0.0.1:6379> set k1 v1
QUEUED
127.0.0.1:6379> set k2 v2
QUEUED
127.0.0.1:6379> exec
1) OK
2) OK
}
放弃事务(discard)
监控:
悲观锁:认为什么时候都会出现问题,无论做什么都加锁。
乐观锁:认为什么时候都不会出现问题,所以不会加锁,
更新数据时才判断一下是否有人修改这个数据。
正常执行成功:{
127.0.0.1:6379> set money 100
OK
127.0.0.1:6379> set out 0
OK
127.0.0.1:6379> watch money //监视money
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> decrby money 20 //减指定的整数
QUEUED
127.0.0.1:6379> incrby out 20 //添加指定的整数
QUEUED
127.0.0.1:6379> exec
1) (integer) 80
2) (integer) 20
}
多线程修改值,使用watch当做redis的乐观锁操作:{
127.0.0.1:6379> watch money
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> decrby money 10
QUEUED
127.0.0.1:6379> incrby out 10
QUEUED
127.0.0.1:6379> exec //执行exec后无论事务是否都会自动解锁
(nil) //当另一个线程修改值后,这里事务会失败显示nil
127.0.0.1:6379> unwatch //事务执行失败,先解锁,该操作可无
}