Redis的基本知识
基础
端口号6379
redis共有16个数据库,默认使用的是第一个。
切换数据库命令:select 2
数据库的大小DBSIZE
设定值:set key value
取值:get key value
查看数据库所有的 key: keys*
清空当前数据库:flushdb
清楚所有数据库:FLUSHDBF
判断当前的key是否存在:EXISTS name
查看当前key的剩余时间ttl name
将key移动到指定的数据库:move key 1
查看key的数据类型:type name
设置key的过期时间:EXPIRE name 10 单位是秒
Redis是基础内存操作的,CPU不是Redis性能瓶颈,Redis的瓶颈是根据机器的内存和网络带宽,既然可以使用单线程来实现,就使用单线程了!
五大数据类型
String(字符串)
incr view(加1)
decr view (减1)
INCRBY view 10 (view:自增10t)
DECRBY view 10 (view:自减10)
GETRANGE key1 0 3
GETRANGE key1 0 -1(获取所有的字符串)
SETRANGE key2 1 xx(替换指定位置开始的字符串!)
setex(set with expire) 设置过期时间
setnx(set if not exist)不存在设置(用于分布式锁使用)
mset k1 v1 k2 v2 k3 v3设定多个值
mget k1 v1 k2 v2 k3 v3取出多个值
msetnx k1 v2 k2 v3 k3 v3是一个原子操作,要么一起成功,要么一起失败
set user:1{name:zhangsan,age:3}。设置一个user:1 对象 值为 json字符来保存一个对象
这里的key是一个巧妙的设计:user:{id}:{filed},如此设计在Redis中是完全ok
getset db redis 如果不存在值,则返回null
get db
getset db mongodb 如果存在值,获取原来的值,并设置新的值 d
get db
String类似的使用场景,value除了是我们的字符串还可以是我们的数字
- 计数器
- 统计多单位的数量uid
List
List有序可重复
栈、队列、阻塞队列,所有的list命令都是l开头的
LPUSH list one #将一个值或者多个值,插入到列表头部
LPUSH list two
LPUSH list three
LRANGE list 0 -1 #取出所有的值
LPUSH list four #将一个值或多个值,插入到列表的尾部
LPOP#从左弹出一个值
RPUSH#从右弹出一个值
Lindex#通过下标获得list中的某一个值!
Llen#长度
Lrem#移除list集合中指定个数的value,精确匹配
Lpoppush#移除列表的最后一个元素,将他移动到新的列别中
lset#将列表中指定下标的值替换为另外一个值,,更新操作
EXISTS list# 判断这个列表是否存在
Lset list 0 item #如果存在,更新当前下标的值
Linsert #将某个具体的value插入到列表中某个元素的前面(before)或后面(after)
set
set 无序并且不重复集合,抽随机
sadd myset "hello"//set集合中添加元素
SMEMBERS myset //查看指定set的所有值
SISMEMBER myset hell //判断某一个值是不是set集合
scard myset //获取set集合中的元素个数
srem myset hello //移除set某一个元素
srandmember myset count //随机抽取中元素个数,其中count为负数是可以重复,
spop myset //删除一些set集合中的元素!
smove source destination member//移动指定的值
Hash(哈希)
本质和String类型灭有太大区别,
Map集合,ke-Map这时候是一个map集合!
hset myhash field1 hello //set一个具体key-value
hget myhash field1//获取一个字段值
hmset myhash field1 hello field2 world //set 多个具体key-value
hgetall myhash //获取全部的值
hdel myhash field1//删除指定的key字段,对应的value值也就消失了
hlen myhash//获取hash的字段数量
hmset mys//hmset myhash field1 hello field2 hello
hgetall myhash//获取所有的hash
HEXISTS myhash field3 //判断hash中指定字段是否存在!
hkeys myhash //只获得所有field
hvals myhash //只获得value中的值
hsetnx myhash field hello //如果不存在则可以设置
hsetnx myhash field world //如果存在则不能设置
hash应用场景 变更的数据user name age,尤其是用户信息之类的,经常变动的信息!hash更适合于对象的存储,而String更加适合字符串存储!
Zset(有序集合)
在set的基础上,增加了一个值,set k1 v1 zsetk1 score v1
zadd myset 1 one//添加一个值
zadd myset 2 two 3 three//添加多个值
zrange myset 0 -1 //查看所有数据
zadd salary 2500 xiaohong
zadd salary 5000 zhangsan
zadd salary 200 xiaoming
ZRANGEBYSCORE salary -inf +infwithscores //从小到大进行排序并且附带成绩
zrem salary xiaohong//移除指定元素
zcard salary//获取有序集合中的个数
三大特殊数据类型
geospatial地理位置
朋友的定位,附近的人,打车距离计算
geoadd china:city 116.40.39.90 beijing
geoadd china:city 124.47.31.23 shanghai
geoadd china:city 106.50.29.53 chongqing
geopos china:city beijing//获取北京的经度和纬度
geodist china:city beijing shanghai km//查看上海到北京的直线距离
georadius china:city 110 30 500 km//以110,30这个经纬度为中心,寻找500内的城市
GEOADD//添加一个城市
GEODIST//返回两个给定位置之间的距离
GEOHASH//返回一个或多个位置元素的Geohash,该命令将返回11字符的Geohash字符串
GEOPOS//命令从key里面返回所有给定位置元素位置(经度和纬度)
GEORADIU//以给定的经度为中心,找出某一半径内的元素
GEORADIUDBYMEMBER//找出位于指定元素周围的其他元素!
GEO底层的实现原理其实就是Zset命令来操作geo!
zrem china:city beijing //移除指定元素!
Hyperloglog
什么是基数?基数(不重复的元素的个数)
网页的UV(Unqiue Visitor)独立访问客数,传统的方式,set保存用户的id,然后可以统计set中的元素数量作为标准判断!这个方式如果保存大量的用户id,就会比较麻烦!我们的目的是为了计数,而不是保存用户id
PFadd mykey a b c d e f g h i j//创建第一个元素
PFcount mykey//统计mykey的基数数量
PFmMERGE mykey3 mykey mykey2 //合并两组 mykey mekey2 =>mykey3 并集
PFCOUNT mykey //看并集的数量!
如果允许容错,那么一定可以使用Hyperloglog
Bitmaps(位存储)
Bitmaps位图,数据结构!都是操作二进制位来进行记录,就只有0和1两个状态
setbit sign 0 1
getbit sign 0
统计操作,统计打卡的天数
bitcount sign
事务
Redis事务本质;一组命令的集合!一个事务中的命令都会被序列化,在事务执行的过程中,会按照顺序执行!一次性、顺序性、排他性!执行一些列的名令
Redis事务没有隔离级别的概念
所有的命令在事务中,并没有被执行!只有发起执行命令的时候才会执行!
MySQL:ACID
Redis单条命令式保存原子性的,但是事务不保证原子性!
redis的事务:
-
开启事务(multi)
-
命令入队(.....)
-
执行事务(exec)执行事务
正常执行事务
multi//开启事务
set k1 v1
set k2 v2
get k2
set k3 v3
exec//执行事务
DISCARD:放弃事务所有入队命令将取消不会被执行
编译型异常:(代码有问题!命令有错!),事务中所有的命令都不会被执行!
运行时异常(1/0):如果事务队列中存在语法性,那么执行命令的是时候,其他命令是可以正常执行的,错误命令抛出异常!
监控Watch
悲观锁
- 很悲观,什么时候都会出问题,无论做什么都会加锁
乐观锁
- 认为什么时候都不会出问题,所以不会上锁!更新数据的时候取判断一下,在此期间是否修改过这个数据.
- 获取version
- 更新的时候比较version
Redis测监视测试
set money 100
OK
set out 0
OK
watch money//监视monty对象
OK
multi//事务正常结束,数据期间没有发生,这个时候就正常执行成功!
OK
DECRBY money 20
QUEUED
INCRBY out 20
QUEUED
EXEC
1.如果发现事务执行失败,就先解锁
2.获取最新的值,再次监视