Redis基础知识

1、Redis启动

在这里插入图片描述

进入redis安装目录,首先双击服务器,然后双击客户端,在客户端进行数据的操作。

2、五大基本数据类型

String类型

  • set和get命令

    127.0.0.1:6379> set key1 v1
    OK
    127.0.0.1:6379> get key1
    "v1"
    
  • keys命令,查看所有key

    127.0.0.1:6379> keys *
    1) "key1"
    
  • del命令,删除key

    127.0.0.1:6379> keys *
    1) "key1"
    127.0.0.1:6379> del key1
    (integer) 1
    127.0.0.1:6379> keys *
    (empty list or set)
    
  • exist命令,是否存在某键

    127.0.0.1:6379> exists key1
    (integer) 1
    
  • append命令,追加字符串内容,如果要追加的key不存在,则相当于set命令

    127.0.0.1:6379> append key1 hello
    (integer) 7
    127.0.0.1:6379> get key1
    "v1hello"
    
  • strlen命令,获取字符串长度

    127.0.0.1:6379> strlen key1
    (integer) 7
    
  • incr命令,自增1

    127.0.0.1:6379> set views 0
    OK
    127.0.0.1:6379> get views
    "0"
    127.0.0.1:6379> incr views
    (integer) 1
    127.0.0.1:6379> incr views
    (integer) 2
    
  • decr命令,自减1

    127.0.0.1:6379> decr views
    (integer) 1
    127.0.0.1:6379> decr views
    (integer) 0
    
  • incrby命令,一次性增加n

    (integer) 0
    127.0.0.1:6379> incrby views 10
    (integer) 10
    
  • decrby命令,一次性减少n

    (integer) 10
    127.0.0.1:6379> decrby views 10
    (integer) 0
    
  • flushdb命令,清空数据库

    127.0.0.1:6379> flushdb
    OK
    127.0.0.1:6379> keys *
    (empty list or set)
    
  • getrange命令,截取字符串

    127.0.0.1:6379> get key1
    "hello,kuangshen"
    127.0.0.1:6379> getrange key1 0 3
    "hell"
    127.0.0.1:6379> getrange key1 0 -1
    "hello,kuangshen"
    
  • setrange命令,替换指定位置开始的字符串

    127.0.0.1:6379> set key2 abcdefg
    OK
    127.0.0.1:6379> get key2
    "abcdefg"
    127.0.0.1:6379> setrange key2 1 xx
    (integer) 7
    127.0.0.1:6379> get key2
    "axxdefg"
    
  • setex(set with expire),设置过期时间

    127.0.0.1:6379> setex key3 30 "hello" #设置key3 30秒过期
    OK
    127.0.0.1:6379> ttl key3
    (integer) 10
    127.0.0.1:6379> get key3
    (nil)
    
  • setnx(set if not exists),不存在再设置,存在,则设置不成功,在分布式锁中会常常使用

    127.0.0.1:6379> setnx mykey "redis"
    (integer) 1
    127.0.0.1:6379> setnx mykey "mongodb"
    (integer) 0
    127.0.0.1:6379> get mykey
    "redis"
    
  • mset命令,同时设置多个key

    127.0.0.1:6379> mset k1 v1 k2 v2 k3 v3
    OK
    127.0.0.1:6379> keys *
    1) "k3"
    2) "k1"
    3) "k2"
    
    127.0.0.1:6379> mset user:1:name zhangsan user:1:age 2
    OK
    127.0.0.1:6379> mget user:1:name user:1:age
    1) "zhangsan"
    2) "2"
    
  • mget命令,同时获取多个key的值

    127.0.0.1:6379> mget k1 k2 k3
    1) "v1"
    2) "v2"
    3) "v3"
    
  • msetnx命令,不存在则创建,msetnx是一个原子性的操作,要么一起成功,要么一起失败

    127.0.0.1:6379> msetnx k1 vv k4 v4 #mset k1 v1不成功,因为k1已存在,mset k4 v4是成功的,因为k4不存在,但由于msetnx是原子性操作,要么都成功,要么都不成功,所以最终结果是失败的
    (integer) 0
    127.0.0.1:6379> keys *
    1) "k3"
    2) "k1"
    3) "k2"
    
  • getset命令,先get再set,若key不存在,则返回nil,然后再设置key;若key存在,则返回值,并设置新值。CAS比较并设置

    127.0.0.1:6379> getset db redis
    (nil)
    127.0.0.1:6379> get db
    "redis"
    127.0.0.1:6379> getset db mongodb
    "redis"
    127.0.0.1:6379> get db
    "mongodb"
    
  • 对象

    127.0.0.1:6379> set user:1 {name:zhangsan,age:3}
    OK
    

String类型的使用场景:value除了是字符串还可以是数字

  • 计数器
  • 统计多单位的数量
  • 粉丝数
  • 对象缓存存储

List

实际上是一个双向链表,可用作栈、消息队列。

所有的list命令都是以l开头的

  • lpush命令,将一个或多个值插入到链表头部

    127.0.0.1:6379> lpush list one
    (integer) 1
    127.0.0.1:6379> lpush list two
    (integer) 2
    127.0.0.1:6379> lpush list three
    (integer) 3
    127.0.0.1:6379> lrange list 0 1
    1) "three"
    2) "two"
    
  • rpush命令,将一个或多个值插入到链表尾部

    127.0.0.1:6379> rpush list four
    (integer) 4
    127.0.0.1:6379> lrange list 0 -1
    1) "three"
    2) "two"
    3) "one"
    4) "four"
    
  • lpop命令,移除链表最左边元素,rpop命令,移除链表最右边元素

    127.0.0.1:6379> lrange list 0 -1
    1) "three"
    2) "two"
    3) "one"
    4) "four"
    127.0.0.1:6379> lpop list
    "three"
    127.0.0.1:6379> rpop list
    "four"
    
  • lindex命令,通过 下标获取list中的某一个元素

    127.0.0.1:6379> lindex list 0
    "two"
    
  • llen命令,返回列表的长度

    127.0.0.1:6379> llen list
    (integer) 2
    
  • lrem命令,移除链表中指定的值

    127.0.0.1:6379> lrange list 0 -1
    1) "three"
    2) "three"
    3) "two"
    4) "one"
    127.0.0.1:6379> lrem list 1 three #删除list中的1个three
    (integer) 1
    127.0.0.1:6379> lrange list 0 -1
    1) "three"
    2) "two"
    3) "one"
    
  • ltrim命令,截取列表中的片段

    127.0.0.1:6379> lrange mylist 0 -1
    1) "hello"
    2) "hello1"
    3) "hello2"
    4) "hello3"
    127.0.0.1:6379> ltrim mylist 1 2
    OK
    127.0.0.1:6379> lrange mylist 0 -1
    1) "hello1"
    2) "hello2"
    
  • rpoplpush命令,将一个列表最末尾元素移动到另一个链表的头部

    127.0.0.1:6379> lrange mylist 0 -1
    1) "hello"
    2) "hello1"
    3) "hello2"
    127.0.0.1:6379> rpoplpush mylist myotherlist
    "hello2"
    127.0.0.1:6379> lrange mylist 0 -1
    1) "hello"
    2) "hello1"
    127.0.0.1:6379> lrange myotherlist 0 -1
    1) "hello2"
    
  • lset命令,设置列表中某个元素的值,前提是该元素存在,否则报错

    127.0.0.1:6379> lrange list 0 -1
    1) "value1"
    127.0.0.1:6379> lset list 0 item
    OK
    127.0.0.1:6379> lrange list 0 0
    1) "item"
    127.0.0.1:6379> lset list 1 ele
    (error) ERR index out of range
    
  • linsert命令,在list某个元素前后插入新的元素

    127.0.0.1:6379> lrange mylist 0 -1
    1) "hello"
    2) "world"
    127.0.0.1:6379> linsert mylist before world other
    (integer) 3
    127.0.0.1:6379> lrange mylist 0 -1
    1) "hello"
    2) "other"
    3) "world"
    127.0.0.1:6379> linsert mylist after world new
    (integer) 4
    127.0.0.1:6379> lrange mylist 0 -1
    1) "hello"
    2) "other"
    3) "world"
    4) "new"
    

Set

set(集合)中的值不能重复,是无序的

所有的set命令都是以s开头的

  • sadd命令,向集合中添加元素

    127.0.0.1:6379> sadd myset "hello"
    (integer) 1
    127.0.0.1:6379> sadd myset "kuangshen"
    (integer) 1
    
  • smembers命令,查看set中所有的元素值

    127.0.0.1:6379> smembers myset
    1) "hello"
    2) "kuangshen"
    
  • sismember命令,判断集合中是否存在某元素

    127.0.0.1:6379> sismember myset hello
    (integer) 1
    127.0.0.1:6379> sismember myset world
    (integer) 0
    
  • scard命令,获取set中元素个数

    127.0.0.1:6379> scard myset
    (integer) 2
    
  • srem命令,移除set中的某个元素

    127.0.0.1:6379> smembers myset
    1) "hello"
    2) "kuangshen"
    127.0.0.1:6379> srem myset "hello"
    (integer) 1
    127.0.0.1:6379> smembers myset
    1) "kuangshen"
    
  • srandmember命令,从集合中随机选择一个或多个元素

    127.0.0.1:6379> smembers myset
    1) "new"
    2) "world"
    3) "kuangshen"
    127.0.0.1:6379> srandmember myset
    "kuangshen"
    127.0.0.1:6379> srandmember myset
    "new"
    127.0.0.1:6379> srandmember myset
    "new"
    127.0.0.1:6379> srandmember myset 2 #随机选取2个元素
    1) "new"
    2) "world"
    
  • spop命令,从集合中随机删除一些元素

    127.0.0.1:6379> smembers myset
    1) "new"
    2) "world"
    3) "kuangshen"
    127.0.0.1:6379> spop myset
    "new"
    127.0.0.1:6379> smembers myset
    1) "world"
    2) "kuangshen"
    
  • smove命令,将一个指定的值移动到另外一个set集合中

    127.0.0.1:6379> smembers myset
    1) "world"
    2) "kuangshen"
    127.0.0.1:6379> smembers myset2
    1) "set2"
    127.0.0.1:6379> smove myset myset2 "world"
    (integer) 1
    127.0.0.1:6379> smembers myset
    1) "kuangshen"
    127.0.0.1:6379> smembers myset2
    1) "world"
    2) "set2"
    
  • 交集sinter、并集sunion、差集sdiff

    微博共同关注,交集

    127.0.0.1:6379> smembers key1
    1) "c"
    2) "b"
    3) "a"
    127.0.0.1:6379> smembers key2
    1) "d"
    2) "e"
    3) "c"
    127.0.0.1:6379> sdiff key1 key2
    1) "b"
    2) "a"
    127.0.0.1:6379> sinter key1 key2
    1) "c"
    127.0.0.1:6379> sunion key1 key2
    1) "b"
    2) "c"
    3) "a"
    4) "d"
    5) "e"
    

Hash

所有的命令以h开头

存放键值对

  • hset和hget

    127.0.0.1:6379> hset myhash "field1" "kuangshen"
    (integer) 1
    127.0.0.1:6379> hget myhash field1
    "kuangshen"
    
  • hdel命令,删除元素

    127.0.0.1:6379> hdel myhash filed2
    (integer) 1
    
  • hlen命令,获取hash表的字段数量

    127.0.0.1:6379> hlen myhash
    (integer) 1
    
  • exists命令,判断hash表中某个字段是否存在

    127.0.0.1:6379> exists myhash field1
    (integer) 1
    
  • hkeys命令,只获取所有的字段

    (integer) 127.0.0.1:6379> hkeys myhash
    1) "field1"
    
  • hvals命令,只获取所有的字段值

    127.0.0.1:6379> hvals myhash
    1) "kuangshen"
    
  • hincrby命令,自增

    127.0.0.1:6379> hset myhash field3 5
    (integer) 1
    127.0.0.1:6379> hincrby myhash field3 1
    (integer) 6
    
  • hsetnx命令,如果不存在,则设置成功

    127.0.0.1:6379> hsetnx myhash field4 world
    (integer) 1
    

Zset

有序集合

  • zadd命令,添加元素

    127.0.0.1:6379> zadd myset 1 one
    (integer) 1
    127.0.0.1:6379> zadd myset 2 two 3 three
    (integer) 2
    127.0.0.1:6379> zrange myset 0 -1
    1) "one"
    2) "two"
    3) "three"
    
  • zrangebyscrore命令,返回分数在min和max之间的所有元素,元素从低分到高分排序。

    127.0.0.1:6379> zadd salary 2500 xiaohong
    (integer) 1
    127.0.0.1:6379> zadd salary 5000 zhangsan
    (integer) 1
    127.0.0.1:6379> zadd salary 500 kuangshen
    (integer) 1
    127.0.0.1:6379> zrangebyscore salary -inf +inf #inf表示无穷
    1) "kuangshen"
    2) "xiaohong"
    3) "zhangsan"
    127.0.0.1:6379> zrangebyscore salary 0 3000
    1) "kuangshen"
    2) "xiaohong"
    
  • zrevrange命令,从大到小进行排序

    127.0.0.1:6379> zrevrange salary 0 -1
    1) "zhangsan"
    2) "xiaohong"
    3) "kuangshen"
    
  • zcount命令,获取分数在区间内的元素个数

    127.0.0.1:6379> zcount salary 500 3000
    (integer) 2
    
  • zcard命令,获取有序集合中元素个数

    127.0.0.1:6379> zcard salary
    (integer) 3
    
  • zrem命令,移除元素

    127.0.0.1:6379> zrem salary xiaohong
    (integer) 1
    127.0.0.1:6379> zrange salary 0 -1
    1) "kuangshen"
    2) "zhangsan"
    

3、三种特殊数据类型

geospatial地理位置

  • geoadd命令,添加地理位置(南北两极无法添加),我们一般会下载城市数据,直接一次性导入!

    127.0.0.1:6379> geoadd china:city 116.40 39.9 beijing
    (integer) 1
    127.0.0.1:6379> geoadd china:city  121.47 31.23 shanghai
    (integer) 1
    127.0.0.1:6379> geoadd china:city 106.50 29.53 chongqin 114.05 22.52 shenzhen 120.16 30.24 guangzhou 108.96 34.26 xian
    (integer) 4
    
  • geopos命令,获取地理位置(坐标)

    127.0.0.1:6379> geopos china:city beijing
    1) 1) "116.39999896287918"
       2) "39.900000091670925"
    
  • geodist命令,两个城市之间的距离

    127.0.0.1:6379> geodist china:city beijing shanghai
    "1067378.7564"
    127.0.0.1:6379>  geodist china:city beijing shanghai km #单位设置成km
    "1067.3788"
    
  • georadius命令,以给定的经纬度为中心,找出某一半径内的元素

    127.0.0.1:6379> georadius china:city 110 30 1000 km #找出以110,30为中心,半径为1000km的所有城市
    1) "chongqin"
    2) "xian"
    3) "shenzhen"
    4) "guangzhou"
    127.0.0.1:6379> georadius china:city 110 30 500 km withcoord #withcoord打印出城市经纬度
    1) 1) "chongqin"
       2) 1) "106.49999767541885"
          2) "29.529999579006592"
    2) 1) "xian"
       2) 1) "108.96000176668167"
          2) "34.2599996441893"
    127.0.0.1:6379> georadius china:city 110 30 500 km withdist #withdist打印出城市距离当前位置的距离
    1) 1) "chongqin"
       2) "341.9374"
    2) 1) "xian"
       2) "483.8340"
    127.0.0.1:6379> georadius china:city 110 30 500 km count 1 #count限制个数
    1) "chongqin"
    
  • georadiusbymember命令,以给定的城市为中心,找出某一半径内的元素

    127.0.0.1:6379> georadiusbymember china:city beijing 1000 km
    1) "beijing"
    2) "xian"
    
  • geohash命令,将二维经纬度转化为一维的11位字符串

    127.0.0.1:6379> geohash china:city beijing
    1) "wx4fbxxfke0"
    
  • GEO底层的实现原理其实就是Zset,我们可以使用Zset命令来操作geo

    127.0.0.1:6379> zrange china:city 0 -1
    1) "chongqin"
    2) "xian"
    3) "shenzhen"
    4) "guangzhou"
    5) "shanghai"
    6) "beijing"
    127.0.0.1:6379> zrem china:city beijing
    (integer) 1
    127.0.0.1:6379> zrange china:city 0 -1
    1) "chongqin"
    2) "xian"
    3) "shenzhen"
    4) "guangzhou"
    5) "shanghai"
    

hyperloglog

基数统计的算法,0.81%错误率!

127.0.0.1:6379> pfadd mykey a b c d
(integer) 1
127.0.0.1:6379> pfcount mykey
(integer) 4
127.0.0.1:6379> pfadd mykey2 c c d e f
(integer) 1
127.0.0.1:6379> pfcount mykey2 #只有一个c添加成功
(integer) 4
127.0.0.1:6379> pfmerge mykey3 mykey mykey2 #并集
OK
127.0.0.1:6379> pfcount mykey3
(integer) 6

bitmaps

位存储

127.0.0.1:6379> setbit sign 0 1 #位置0设置成1
(integer) 0
127.0.0.1:6379> setbit sign 1 0 #位置1设置成0
(integer) 0
127.0.0.1:6379> getbit sign 0 #查看位置0的值
(integer) 1
127.0.0.1:6379> bitcount sign #统计1的个数
(integer) 1

4、事务

Redis事务本质:一组命令的集合!一个事务中的所有命令都会被序列化,在事务执行过程中,会按照顺序执行!

一次性、顺序性、排他性执行一系列的命令!

Redis事务没有隔离级别的概念!

所有的命令在事务中,并没有直接被执行!只有发起执行命令的时候才会执行!

Redis单条命令是保证原子性的,但是事务不保证原子性!

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> get k2
QUEUED
127.0.0.1:6379> set k3 v3
QUEUED
127.0.0.1:6379> exec #执行事务
1) OK
2) OK
3) "v2"
4) OK

取消事务

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> set k4 v4
QUEUED
127.0.0.1:6379> discard #取消事务
OK
127.0.0.1:6379> get k4 #事务队列中命令都不会被执行
(nil)

编译型异常(代码有问题!),事务中所有的命令都不会被执行

127.0.0.1:6379> multi
OK
127.0.0.1:6379> set k1 v1
QUEUED
127.0.0.1:6379> setget k2 v2
(error) ERR unknown command 'setget'
127.0.0.1:6379> set k2 v2
QUEUED
127.0.0.1:6379> exec
(error) EXECABORT Transaction discarded because of previous errors.

运行时异常,如果事务队列中存在语法性,那么执行命令的时候,其他命令是可以正常执行的,错误命令抛出异常!

127.0.0.1:6379> set k1 "v1"
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> incr k1
QUEUED
127.0.0.1:6379> set k2 v2
QUEUED
127.0.0.1:6379> get k2
QUEUED
127.0.0.1:6379> exec
1) (error) ERR value is not an integer or out of range
2) OK
3) "v2"

Redis实现乐观锁

  • 乐观锁

    • 很乐观,认为什么时候都不会出问题,所以不会上锁,更新数据的时候去判断一下,在次期间是否有人修改过这个数据。
    • 获取version
    • 更新的时候比较version
  • watch实现乐观锁

    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
    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 #执行时,若有另外一个线程修改了money的值,则事务执行失败
    (nil)
    

    事务执行失败之后,watch会自动解锁,无需手动unwatch解锁

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值