Redis

官方文档:http://www.redis.cn/

String 基本操作

  • flushall # 清空所有的key
  • type key # 查看key 的类型
  • exists key # 判断key 是否存在,存在返回1
  • append key hello # 追加数据,如果key 不存在,创建key
  • select 0 # 切换第一个数据库
  • keys * # 查看所有的key
  • DBSIZE # 插卡key的数量
  • strlen key # 查看key 的长度
  • incr key # key的值加1 ,i++
  • decr key # key的值减1,i–
  • incrby key 10 # key的值加10,指定步长
  • decrby key 10 # key的值减10
  • getrange key 0 -1 # 截取key指定范围[0,-1]
  • setrange key 0 XX # 替换指定位置的字符串
  • setex # ( set with expire )设置过期时间
    setex key3 hello 30 创建key3,30秒后过期
  • setnx # 不存在再设置(在分布式中经常使用)
  • mset k1 v1 k2 v2 k3 v3 # 同时设置多个值
  • mget k1 k2 k3 # 同时获取多个值
  • msetnx k1 v1 k4 v4 # 设置失败,原子性操作,要么成功,要么失败
  • getset db redis # 如果db不存在返回nil,如果存在返回db的原有值,并设置新的值

List 基本操作

  • Lpush list # 将值插入列表的头部(左)
  • Rpush list # 将值插入列表的尾部(右)
  • Lpop list # 删除列表中头部的第一个元素
  • Rpop list # 删除列表中尾部的第一个元素
  • Lrange list 0 -1 # 输出列表中[0,-1]的元素
  • Lindex list 0 # 输出列表中第一个元素
  • Llen list # 输出列表的长度
  • Lrem list count value # 移除列表中count个value
  • Ltrim list 0 2 # 通过下标截取列表中指定的长度
  • rpoplpush list newlist #移除列表最后一个元素并将移除的元素放到心的列表中
  • lset mylist 0 item # 将列表指定下标的值替换为另外一个元素
  127.0.0.1:6379> lset list 0 item # 如果列表不存在就报错
(error) ERR no such key 
  • linsert 在列表中某元素的前面或者后面插入指定的值
127.0.0.1:6379> linsert mylist before world other
127.0.0.1:6379> linsert mylist after hello new

Set 基本操作

  • 基本操作
127.0.0.1:6379> sadd myset hello # 向集合中添加元素
(integer) 1
127.0.0.1:6379> sadd myset world 
(integer) 1
127.0.0.1:6379> sadd myset love
(integer) 1
127.0.0.1:6379> smembers myset # 获取集合中所有的元素
 1) "world"
 2) "hello"
 3) "love"
127.0.0.1:6379> sismember myset hello # 判断集合中是否存在某元素,存在返回1,不存在返回0
(integer) 1
  • 集合中的数据不能是重复的,获取集合中的元素个数
127.0.0.1:6379> scard myset # 获取集合中的元素个数
(integer) 3
127.0.0.1:6379> sadd myset love # 不能添加重复值
(integer) 0
127.0.0.1:6379> sadd myset love2
(integer) 1
127.0.0.1:6379> scard myset
(integer) 4
  • 移除某元素
127.0.0.1:6379> srem myset love
(integer) 1
  • set 是一个无序不重复,随机抽取元素
127.0.0.1:6379> srandmember myset  # 随机抽取一个元素
127.0.0.1:6379> srandmember myset 2 # 随机抽取两个元素
  • 随机移除元素
 spop myset
  • 移动指定的元素
127.0.0.1:6379> smembers key1
1) "c"
2) "b"
3) "a"
127.0.0.1:6379> smembers key2
1) "c"
2) "e"
3) "d"
127.0.0.1:6379> smove key1 key2 a
(integer) 1
127.0.0.1:6379> smembers key1
1) "c"
2) "b"
127.0.0.1:6379> smembers key2
1) "c"
2) "e"
3) "d"
4) "a"
  • 差集sdiff、交集sinter、并集sunion
127.0.0.1:6379> smembers key1
1) "c"
2) "b"
3) "a"
127.0.0.1:6379> smembers key2
1) "c"
2) "e"
3) "d"
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) "c"
2) "e"
3) "b"
4) "a"
5) "d"

Hash 基本操作

map集合,与string 没有区别,只是变成了key-map,更适合存储对象

  • 赋值hset与取值hget
127.0.0.1:6379> hset myhash field1 kuangshen # 添加一个值
(integer) 1
127.0.0.1:6379> hget myhash field1 # 获取一个字段的值
"kuangshen"
127.0.0.1:6379> hmset myhash field1 hello field2 world # 添加多个字段的值
OK
127.0.0.1:6379> hget myhash field1 
"hello"
127.0.0.1:6379> hget myhash field2
"world"
127.0.0.1:6379> hgetall myhash # 获取全部的字段值
1) "field1"
2) "hello"
3) "field2"
4) "world"
  • 删除某字段hdel
127.0.0.1:6379> hdel myhash field1 # 删除指定的字段
(integer) 1
127.0.0.1:6379> hgetall myhash
1) "field2"
2) "world"
  • 获取hash 的长度
127.0.0.1:6379> hlen myhash # 获取哈希表的长度
(integer) 1
  • 是否存在hexists
127.0.0.1:6379> hexists myhash field1
(integer) 1
127.0.0.1:6379> hexists myhash field3
(integer) 0
  • 获取所有字段hkeys ,获取所有值 hvals
127.0.0.1:6379> hkeys myhash
1) "field1"
2) "filed2"
127.0.0.1:6379> hvals myhash
1) "hello"
2) "world"
  • 增量incr incrby
127.0.0.1:6379> hset myhash field3 5
(integer) 1
127.0.0.1:6379> hincrby myhash field3 2
(integer) 7
127.0.0.1:6379> hincrby myhash field3 -1
(integer) 6

Zset(有序集合)

在set 的基础上加上score

  • 添加元素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"
  • 排序
127.0.0.1:6379> zadd salary 5000 xiaoming 
(integer) 1
127.0.0.1:6379> zadd salary 200 kuangshen
(integer) 1
127.0.0.1:6379> zadd salary 2500 xiaohong
(integer) 1
127.0.0.1:6379> zrangebyscore salary -inf +inf # 从小到大排序
1) "kuangshen"
2) "xiaohong"
3) "xiaoming"
127.0.0.1:6379> zrangebyscore salary -inf +inf withscores # 从小到大排序,附带成绩
1) "kuangshen"
2) "200"
3) "xiaohong"
4) "2500"
5) "xiaoming"
6) "5000"
127.0.0.1:6379> zrangebyscore salary -inf 2500 withscores # 获取小于2500的元素
1) "kuangshen"
2) "200"
3) "xiaohong"
4) "2500"
  • 删除zrem,元素个数zcard
127.0.0.1:6379> zrem salary xiaohong
(integer) 1
127.0.0.1:6379> zcard salary
(integer) 2

Geospatial 基本操作

可以推算地理位置的距离

  • geoadd 将指定的地理空间位置(纬度、经度、名称)添加到指定的key中,geopos 获取指定的城市的经纬度
127.0.0.1:6379> geoadd China:city 121.472644 31.231706 shanghai
(integer) 1
127.0.0.1:6379> geoadd China:city 116.405285 39.904989 beijing
(integer) 1
127.0.0.1:6379> geoadd China:city 106.504962 29.533155 chongqing
(integer) 1
127.0.0.1:6379> geoadd China:city 117.190182 39.125596 tianjin
(integer) 1
127.0.0.1:6379> geoadd China:city 120.153576 30.287459 hangzhou
(integer) 1
127.0.0.1:6379> geopos China:city chongqing
1) 1) "106.50495976209640503"
   2) "29.53315530684997015"
127.0.0.1:6379> geopos China:city tianjin
1) 1) "117.19018310308456421"
   2) "39.12559715251200743"
  • 两人之间的距离geodist
127.0.0.1:6379> geodist China:city beijing shanghai km
"1067.5980"
  • 附近的人,通过半径查询georadius ,georadiusbymember
127.0.0.1:6379> georadius China:city 110 30 1000 km count 1 # 获取经纬度110,30 1000km 之内的一个城市
1) "chongqing" 
127.0.0.1:6379> georadiusbymember China:city beijing 1000 km # 获取距离北京1000km范围的城市
1) "tianjin"
2) "beijing"
  • Geo 底层是zset,zset的命令在此处仍然适用,zrange 等等

Bitmap 操作

记录周一至周日的打卡记录

127.0.0.1:6379> setbit sign 0 1
(integer) 0
127.0.0.1:6379> setbit sign 1 0
(integer) 0
127.0.0.1:6379> setbit sign 2 0
(integer) 0
127.0.0.1:6379> setbit sign 3 0
(integer) 0
127.0.0.1:6379> setbit sign 4 0
(integer) 0
127.0.0.1:6379> setbit sign 5 0
(integer) 0
127.0.0.1:6379> setbit sign 6 1

查看某天是否打开

127.0.0.1:6379> getbit sign 6
(integer) 1
127.0.0.1:6379> getbit sign 5
(integer) 0

统计打卡的天数

127.0.0.1:6379> bitcount sign 
(integer) 2

事务

redis 单条命令要么成功,要么失败,具有原子性。事务没有原子性
redis 事务本质:一组命令的集合,一个事务中的所有命令都被序列化,在执行的过程中,会按照一次性、顺序性、排他性执行一些命令。

  • 开启事务(multi)
  • 命令入队(…)
  • 执行事务(exec)
 127.0.0.1:6379> multi # 开启事务
OK
# 命令入队
127.0.0.1:6379(TX)> set k1 v1 
QUEUED
127.0.0.1:6379(TX)> set k2 v2
QUEUED
127.0.0.1:6379(TX)> get k2
QUEUED
127.0.0.1:6379(TX)> exec # 执行事务
1) OK
2) OK
3) "v2"
127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> set k1 v1 
QUEUED
127.0.0.1:6379(TX)> set k2 v2
QUEUED
127.0.0.1:6379(TX)> set k4 v4
QUEUED
127.0.0.1:6379(TX)> discard # 取消事务
OK
127.0.0.1:6379> get k4  # 事务队列中命令不会被执行
(nil)
  • 命令异常:代码有问题,事务不会被执行
127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> mset k1 v1 k2 v2 k3 v3
QUEUED
127.0.0.1:6379(TX)> getset k4 # 错位代码
(error) ERR wrong number of arguments for 'getset' command
127.0.0.1:6379(TX)> exec # 执行报错
(error) EXECABORT Transaction discarded because of previous errors.
127.0.0.1:6379> keys * # 所有的命令都不执行
(empty array)
  • 运行时异常,可以正常运行,错误命令抛出异常
127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> set k1 "v1"
QUEUED
127.0.0.1:6379(TX)> incr k1 # 字符串不能自增1
QUEUED
127.0.0.1:6379(TX)> set k2 v2 
QUEUED
127.0.0.1:6379(TX)> set k3 v3
QUEUED
127.0.0.1:6379(TX)> exec
1) OK
2) (error) ERR value is not an integer or out of range # 虽然有错误,但依旧可以正常执行下面的命令
3) OK
4) OK
127.0.0.1:6379> get k2
"v2"
127.0.0.1:6379> get k1
"v1"

监控 watch

  • 悲观锁:认为什么时候都会出问题,无论做什么都加锁
  • 乐观锁:认为什么时候都不会出问题,不加锁,更新的时候会判断在此期间是都有人修改过数据
    – 获取version
    – 更新的时候比较version
    正常执行成功
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(TX)> decrby money 20
QUEUED
127.0.0.1:6379(TX)> incrby out 20
QUEUED
127.0.0.1:6379(TX)> exec
1) (integer) 80
2) (integer) 20
  • 测试多线程修改值,使用watch 可以当作redis 的乐观锁操作
127.0.0.1:6379> watch money # 监视money 对象
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> decrby money 10
QUEUED
127.0.0.1:6379(TX)> incrby out 10
QUEUED
127.0.0.1:6379(TX)> exec # 事务执行前,另外一个线程修改了money值,导致事务执行失败
(nil)

如果修改失败,先解锁,再上锁

127.0.0.1:6379> unwatch # 如果事务执行失败,先解锁
OK
127.0.0.1:6379> watch money # 再次监视
OK
127.0.0.1:6379> multi 
OK
127.0.0.1:6379(TX)> incrby money 10
QUEUED
127.0.0.1:6379(TX)> decrby out 10
QUEUED
127.0.0.1:6379(TX)> exec # 比对监视的值是否都发生变化
1) (integer) 1010
2) (integer) 10

Redis 配置文件

  1. 单位的大小写不敏感
    在这里插入图片描述
  2. 可以包含其他配置文件
    在这里插入图片描述
  3. 网络配置
bind 127.0.0.1 -::1 # 绑定IP
protected-mode yes # 保护模式开启
port 6379 # 端口号设置
  1. 通用配置
daemonize yes # 以守护进程的方式开启,需要手动修改为yes
pidfile /var/run/redis_6379.pid # 如果上面修改为yes,需要指定进程pid文件
# Specify the server verbosity level.
# This can be one of:
# debug (a lot of information, useful for development/testing)
# verbose (many rarely useful info, but not a mess like the debug level)
# notice (moderately verbose, what you want in production probably)
# warning (only very important / critical messages are logged)
loglevel notice # 日志级别
logfile "" # 日志的文件名
databases 16 # 数据库的数量,默认16
always-show-logo no # 是否总是显示log
  1. 快照
    持久化,在规定时间内,操作了多少次,则会持久化到文件 .rdb .aof
    redis 是内存数据库,如果没有持久化,断电即失
 # Unless specified otherwise, by default Redis will save the DB:
#   * After 3600 seconds (an hour) if at least 1 change was performed 如果在1小时内至少一个key发生了改变则进行持久化
#   * After 300 seconds (5 minutes) if at least 100 changes were performed 如果在5分钟内至少一百个key发生了改变则进行持久化
#   * After 60 seconds if at least 10000 changes were performed 如果在1分钟内至少一万个key发生了改变则进行持久化
#
# You can set these explicitly by uncommenting the following line.
#
save 3600 1 300 100 60 10000

stop-writes-on-bgsave-error yes # 如果持久化出错了,是否还需要继续保持工作
rdbcompression yes #是否压缩rdb文件,会消耗一些CPU资源
rdbchecksum yes # 保存rdb文件,进行校验
dir ./ #rdb 文件保存的目录
  1. secuirty

设置密码

127.0.0.1:6379> config get requirepass # 获取密码
1) "requirepass"
2) ""
127.0.0.1:6379> config set requirepass binfo # 设置密码
OK
127.0.0.1:6379> exit
(base) [root@GENE-WEB ~]# redis-cli
127.0.0.1:6379> ping 
(error) NOAUTH Authentication required.
127.0.0.1:6379> auth binfo # 输入密码
OK
127.0.0.1:6379> ping
PONG
127.0.0.1:6379> config set requirepass '' # 取消密码
OK
127.0.0.1:6379> quit
(base) [root@GENE-WEB ~]# redis-cli
127.0.0.1:6379> ping
PONG
# maxclients 10000 # 最大客户端数
# maxmemory <bytes> #最大的内存容量
# maxmemory-policy noeviction # 内存到达上限的处理策略
  1. noeviction(默认策略):若是内存的大小达到阀值的时候,所有申请内存的指令都会报错;
  2. allkeys-lru:所有key都是使用LRU算法进行淘汰;
  3. volatile-lru:所有设置了过期时间的key使用LRU算法进行淘汰;
  4. allkeys-random:所有的key使用随机淘汰的方式进行淘汰;
  5. volatile-random:所有设置了过期时间的key使用随机淘汰的方式进行淘汰;
  6. volatile-ttl:所有设置了过期时间的key根据过期时间进行淘汰,越早过期就越快被淘汰
 
  1. APPEND ONLY MODE
appendonly no # 默认不开启aof,大部分情况下rdb就够用
appendfilename "appendonly.aof" # 持久化文件的名字

# appendfsync always # 每次修改都会同步,消耗性能
appendfsync everysec # 每秒同步一次,可能会丢失一秒的数据
# appendfsync no # 不执行同步,操作系统自己同步
在持久化中详细讲解

Redis 发布订阅

是一种消息通信模式:发送者发送消息,订阅者接收消息。微信、微博等
redis 订阅者可以接收多个频道 的消息
订阅/发布消息:
在这里插入图片描述第一:消息发送者,第二消息操控着,第三消息接收者

常用命令:
在这里插入图片描述订阅端:

127.0.0.1:6379> subscribe kuangshenshuo 
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "kuangshenshuo"
3) (integer) 1
# 等待读取推送的信息
1) "message"
2) "kuangshenshuo"
3) "hello,kuangshen"
1) "message"
2) "kuangshenshuo"
3) "hello,world"

发送端:

127.0.0.1:6379> publish kuangshenshuo "hello,kuangshen" # 发布者,发送消息到频道
(integer) 1
127.0.0.1:6379> publish kuangshenshuo "hello,world"
(integer) 1

应用场景:
1.实时消息系统
2.实时聊天
3.订阅关注系统

Redis 主从复制

redis 最大内存不超过20G
环境配置
127.0.0.1:6379> info replication

Replication

127.0.0.1:6379> info replication
# Replication
role:master # 主机角色
connected_slaves:0 # 没有从机
master_failover_state:no-failover
master_replid:cc8d7f0f1f2444ea0eca65f6997e0df4c927c349
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:0
second_repl_offset:-1
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0

复制三个配置文件,修改内容:

  1. 端口号
  2. pid 号
  3. logfile
  4. 备份dump.rdb名字
    通过redis-servre redis79.config 启动,发现三个进程
    在这里插入图片描述一主二从:
    每个redis服务器都是一个主节点
    一般情况下,只需要配置从机
    一主(6379)二从(6380,6381)
    127.0.0.1:6381> slaveof 127.0.0.1 6379
    OK
    127.0.0.1:6381> info replication

Replication

127.0.0.1:6381> slaveof 127.0.0.1 6379 # 设置从机,将6379以为主机
OK
127.0.0.1:6381> info replication
# Replication
role:slave # 角色从机
master_host:127.0.0.1
master_port:6379
master_link_status:up
master_last_io_seconds_ago:4
master_sync_in_progress:0
slave_read_repl_offset:14
slave_repl_offset:14
slave_priority:100
slave_read_only:1
replica_announced:1
connected_slaves:0
master_failover_state:no-failover
master_replid:eaac7bfdf09a4130b9b90da7254a362e6561f148
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:14
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:15
repl_backlog_histlen:0
127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:1 # 多了一个从机
slave0:ip=127.0.0.1,port=6381,state=online,offset=28,lag=0 # 从机的IP地址以及端口号
master_failover_state:no-failover
master_replid:eaac7bfdf09a4130b9b90da7254a362e6561f148
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:28
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:28
127.0.0.1:6380> slaveof 127.0.0.1 6379
OK

真实的主从配置,需要在配置文件中实现,用命令实现的是暂时的,配置文件中的replicaof 命令以及masterauth
在这里插入图片描述主机可写可读,从机只可读

127.0.0.1:6380> set k2 v2
(error) READONLY You can't write against a read only replica.

在这里插入图片描述

Redis 缓存穿透与雪崩

  • 缓存穿透(查不到)
    指,一个请求在redis中找不到,也就是缓存中找不到,就到持久层数据库中查询。
    解决方案:
    布隆过滤器
  • 缓存击穿(查太多,缓存过期)
    指一个key非常热点,大并发量访问同一个点
    解决方案
    1设置热点数据不过期
    2分布式锁
  • 缓存雪崩
    缓存集体失效,redis宕机

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值