码迷,mamicode.com
首页 > 其他好文 > 详细

Redis入门

时间:2021-02-05 10:51:33      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:arch   设计   duti   rem   下标   als   null   img   缓存   

Redis入门

简介

Redis(Remote Dictionary Server ),即远程字典服务,是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。从2010年3月15日起,Redis的开发工作由VMware主持。从2013年5月开始,Redis的开发由Pivotal赞助。

官网 https://redis.io/

NoSQL

NoSQL,泛指非关系型的数据库。随着互联网web2.0网站的兴起,传统的关系数据库在处理web2.0网站,特别是超大规模和高并发的SNS类型的web2.0纯动态网站已经显得力不从心,出现了很多难以克服的问题,而非关系型的数据库则由于其本身的特点得到了非常迅速的发展。NoSQL数据库的产生就是为了解决大规模数据集合多重数据种类带来的挑战,特别是大数据应用难题。

为什么使用Nosql

用户的个人信息,社交网络,地理位置,自己产生的数据,用户的日志等等爆发增长

这个时候我们就需要使用Nosql数据库

Nosql的特点(解耦)

  • 方便扩展,数据直接没有关系!
  • 大数据量高性能(Redis 一秒写8万次,读取11万,细粒度的缓存)
  • 数据类型是多样型的(不用设计数据库,随取随用,数据量比较大的表,无法一开始就设计出来)

Redis能干嘛

  1. 内存存储,持久化,内存中是断电即失,所以持久化很重要(rdb,aof)
  2. 效率高,高速缓存
  3. 订阅系统
  4. 地图信息分析
  5. 计数器,计时器(浏览量)

Windows安装 GitHub下载教程

发现官网名没有提供Windows版本,只有Linux版本,费了一番周折,说是GitHub上才有

地址是:https://github.com/MicrosoftArchive/redis/tags

技术图片

开启Redis 运行服务即可

技术图片

使用客户端连接redis

技术图片

测试工具redis-benchmark

技术图片

技术图片

基础知识

默认使用第0个数据库。一共16个数据库

127.0.0.1:6379> select 3  //切换数据库
OK
127.0.0.1:6379[3]> dbsize //数据库大小
(integer) 0
127.0.0.1:6379[3]>

查询所有,删除数据库数据

127.0.0.1:6379[3]> keys *   //查询所有
1) "name"
127.0.0.1:6379[3]> flushdb  //删除数据库数据
OK
127.0.0.1:6379[3]> keys *
(empty list or set)
127.0.0.1:6379[3]>  

flushall 清空所有的数据库

Redis是单线程的

Redis是基于内存操作的,Cpu不是Redis的其性能瓶颈,Redis的瓶颈是根据机器的内存和网络带宽,

Redis单线程为什么还那么快?

误区1 高性能的服务器一定是多线程的

误区2 多线程(CPU上下文会互相切换)

核心:

redis是将所有的数据是放在内存中的,所以使用单线程操作效率就是最高的

五大基本数据类型

Redis-key

127.0.0.1:6379> keys *
1) "name"
2) "age"
127.0.0.1:6379> get name
"dutianqi"
127.0.0.1:6379> expire name 10  //设置过期时间
(integer) 1
127.0.0.1:6379> ttl name        //查看过期时间
(integer) 5
127.0.0.1:6379> ttl name
(integer) 2
127.0.0.1:6379> ttl naem
(integer) -2
127.0.0.1:6379> get name
(nil)
127.0.0.1:6379> exists name   //判断是否存在
(integer) 0
127.0.0.1:6379> del age       //删除
(integer) 1
127.0.0.1:6379> type name    //查看判断类型
string
127.0.0.1:6379> type age
string

http://www.redis.cn/commands.html 所有的命令在官方文档

String

127.0.0.1:6379> keys *
1) "name"
2) "age"
127.0.0.1:6379> append name duck   //追加字符字符串
(integer) 12
127.0.0.1:6379> keys *
1) "name"
2) "age"
127.0.0.1:6379> get name
"dutianqiduck"
127.0.0.1:6379> strlen name       //字符串长度 
(integer) 12
127.0.0.1:6379> get views
"0"
127.0.0.1:6379> incr views       //自增
(integer) 1
127.0.0.1:6379> decr views       //自减
(integer) 0
//自增自减一个步长
127.0.0.1:6379> decrby views 20
(integer) -20
127.0.0.1:6379> get views
"-20"
127.0.0.1:6379> incrby views 40
(integer) 20
127.0.0.1:6379> get views
"20"
################################################################
127.0.0.1:6379> getrange name 0 1    //查看截取字符串
"du"
127.0.0.1:6379> setrange name 0 xx   //替换字符串
(integer) 12
127.0.0.1:6379> get name
"xxtianqiduck"
################################################################
127.0.0.1:6379> setex test 30 hello    //设置test的值为hello 30 后过期
OK
127.0.0.1:6379> ttl test
(integer) 26
127.0.0.1:6379> setnx mykey redis    //如果mykey不存在 则创建
(integer) 1
127.0.0.1:6379> setnx mykey mongoDb  //如果mykey存在 ,不操作
(integer) 0
127.0.0.1:6379> get mykey
"redis"
127.0.0.1:6379> ttl test
(integer) -2
127.0.0.1:6379> get test
(nil)
########################################################
127.0.0.1:6379> mset k1 k1 k2 k2 k3 k3     //批量set
OK
127.0.0.1:6379> keys *
1) "k2"
2) "k1"
3) "k3"
127.0.0.1:6379> mget k1 k2 k3             //批量获取
1) "k1"
2) "k2"
3) "k3"
127.0.0.1:6379> msetnx k1 k1 k4 k4      //msetnx是一个原子性的操作 要么一起成功,要么一起失败
(integer) 0
127.0.0.1:6379> get k4              //这里可以看见k4没有赋值成功
(nil)
127.0.0.1:6379>

### 对象
127.0.0.1:6379> mset user:1:name dutianqi    可以实现浏览量的功能  
# article:id:views 数据   有人访问自增一即可
OK
127.0.0.1:6379> get user:1:name
"dutianqi"

### 组合命令getset
127.0.0.1:6379> getset db redis       //这里先去get 没有 去设置
(nil)
127.0.0.1:6379> getset db mongodb     //去get 将原来的替换
"redis"
127.0.0.1:6379> get db
"mongodb"
127.0.0.1:6379> 

String 的使用场景 value除了是我们的字符串还可以是数字

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

List

127.0.0.1:6379> lpush list one     //push 一个值
(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     //取出list中的所有值
1) "three"
2) "two"
3) "one"


127.0.0.1:6379> lrange list 0 -1
1) "three"
2) "two"
3) "one"
127.0.0.1:6379> rpush list right    //在值插入到尾部
(integer) 4
127.0.0.1:6379> lrange list 0 -1
1) "three"
2) "two"
3) "one"
4) "right"

127.0.0.1:6379> lpop list     //两个弹栈
"three"
127.0.0.1:6379> rpop list
"right"
127.0.0.1:6379>

127.0.0.1:6379> lindex list 0  //根据下标取值
"two"

127.0.0.1:6379> llen list    //返回列表的长度
(integer) 2

# 移出指定的值 lrem
127.0.0.1:6379> lpush listo one two three redis mysql orcle
(integer) 6
127.0.0.1:6379> lrange list 0 -1
1) "two"
127.0.0.1:6379> lrange listo 0 -1
1) "orcle"
2) "mysql"
3) "redis"
4) "three"
5) "two"
6) "one"
127.0.0.1:6379> lrem listo 1 mysql   //移出一个mysql 有多个 可以设置移出几个
(integer) 1
127.0.0.1:6379> lrange listo 0 -1
1) "orcle"
2) "redis"
3) "three"
4) "two"
5) "one"
127.0.0.1:6379>

# trim   截断操作
127.0.0.1:6379> flushdb
OK
127.0.0.1:6379> lpush list java mysql redis orcle mongodb duck immortal
(integer) 7
127.0.0.1:6379> lrange list 0 -1
1) "immortal"
2) "duck"
3) "mongodb"
4) "orcle"
5) "redis"
6) "mysql"
7) "java"
127.0.0.1:6379> ltrim list 1 2
OK
127.0.0.1:6379> lrange list 0 -1
1) "duck"
2) "mongodb"

########################################

#rpoplpush   移出列表的最后一个元素,将他移动到新的列表
127.0.0.1:6379> lpush list redis mysql orcle
(integer) 3
127.0.0.1:6379> lrange list 0 -1
1) "orcle"
2) "mysql"
3) "redis"
127.0.0.1:6379> rpoplpush list otherlist    //这里进行移动
"redis"
127.0.0.1:6379> lrange list 0 -1
1) "orcle"
2) "mysql"
127.0.0.1:6379> lrange otherlist 0 -1
1) "redis"
# linsert
127.0.0.1:6379> linsert list before mysql spring   //在前后进行插入值
(integer) 3
127.0.0.1:6379> lrange list 0 -1
1) "orcle"
2) "spring"
3) "mysql"
127.0.0.1:6379>  

Set

set中的值是不能重复的 并且没有顺序

127.0.0.1:6379> sadd set aa bb cc      //添加值
(integer) 3
127.0.0.1:6379> smembers set           //查看所有的元素
1) "bb"
2) "aa"
3) "cc"

127.0.0.1:6379> sismember set aa     //判断集合中是否存在
(integer) 1
127.0.0.1:6379> sismember set dd
(integer) 0
127.0.0.1:6379> spop set            //随机删除
"cc"


############################################
//将一个指定的值,移动到另一个集合中
127.0.0.1:6379> smembers set
1) "cc"
2) "bb"
3) "aa"
127.0.0.1:6379> smove set setmove aa
(integer) 1
127.0.0.1:6379> smembers setmove
1) "aa"
127.0.0.1:6379> smembers set
1) "cc"
2) "bb"

#########################################
实现公共好友,共同的关注
交集,并集,差集
27.0.0.1:6379> sadd set1 a b c
(integer) 3
127.0.0.1:6379> sadd set2  c d e
(integer) 3
127.0.0.1:6379> sdiff set1 set2          //差集
1) "a"
2) "b"
127.0.0.1:6379> sinter set1 set2        //交集
1) "c"
127.0.0.1:6379> sunion set1 set2         //并集
1) "c"
2) "e"
3) "a"
4) "b"
5) "d"

Hash

Map集合 key,<key ,value> 大概模型

127.0.0.1:6379> hset hash field name          //设置set
(integer) 1
127.0.0.1:6379> hget hash field               //get 值
"name"
127.0.0.1:6379> hset hash name dutianqi       //set值
(integer) 1
127.0.0.1:6379> hmset demo name1 1 name2 2 name3 3    //批量set值
OK
127.0.0.1:6379> hgetall demo                  //获取所有的值
1) "name1"
2) "1"
3) "name2"
4) "2"
5) "name3"
6) "3"     
127.0.0.1:6379> hdel demo name1            //删除指定字段
(integer) 1
127.0.0.1:6379> hgetall demo               //查看一下
1) "name2"
2) "2"
3) "name3"
4) "3"
###################################################################
127.0.0.1:6379> hlen demo                    //查看长度
(integer) 2       

127.0.0.1:6379> hexists demo hello1            --查看指定key是否存在
(integer) 0
127.0.0.1:6379> hexists demo name1
(integer) 0
127.0.0.1:6379> hexists demo name2
(integer) 1
127.0.0.1:6379> hkeys demo                   //所有的key
1) "name2"
2) "name3"
127.0.0.1:6379> hvals demo                  //所有的value
1) "2"
2) "3"

Hash应用 存储变更的 数据 ,更加适合字段的存储

String 更适合字符段的存储

Zset(有序集合)

zset基础上增加了一个值

127.0.0.1:6379> zadd zset 1 one                //添加一个值
(integer) 1
127.0.0.1:6379> zadd zset 2 two 3 three        //添加多个值
(integer) 2
127.0.0.1:6379> zrange zset 0 -1               //查看所有
1) "one" 
2) "two"
3) "three"

############################
//排序
127.0.0.1:6379> zadd salary 2000 zhangsan
(integer) 1
127.0.0.1:6379> zadd salary 25000 lisi
(integer) 1
127.0.0.1:6379> zadd salary 29999 wangwu
(integer) 1
127.0.0.1:6379> zrangebyscore salary -inf +inf              。//排序
1) "zhangsan"
2) "lisi"
3) "wangwu"
127.0.0.1:6379> zrem salary zhangsan                          //删除指定的key
(integer) 1
127.0.0.1:6379> zrange salary 0 -1
1) "lisi"
2) "wangwu"
127.0.0.1:6379> zcard salary                           //查看集合中的元素
(integer) 2

三种特殊类型

geospatial

定位 附近的人 应用场景

这个功能可以查看两地之间的距离,方圆几里的人

只有6个命令

https://www.php.cn/manual/view/36388.html 官网

GEOADD 

该命令采用标准格式 x,y 的参数,因此经度必须在纬度之前指定。可以索引的坐标是有限的:非常靠近极点的区域不可索引。EPSG:900913 / EPSG:3785 / OSGEO:41001的具体限制如下:

  • 有效经度从-180到180度。

  • 有效纬度从 -85.05112878 到 85.05112878 度。

当用户尝试索引超出指定范围的坐标时,该命令将报告错误。

127.0.0.1:6379> geoadd china:city 116.40 39.90 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 114.05 29.53 chongqing
(integer) 1

127.0.0.1:6379> geoadd china:city 120.18 30.24 hangzhou
(integer) 1
geopos
127.0.0.1:6379> geopos china:city beijing          //获取北京地区的经纬度
1) 1) "116.39999896287918"
   2) "39.900000091670925"
geodist

返回排序集合表示的地理空间索引中两个成员之间的距离。

给定一个表示地理空间索引的有序集合,该集合使用 GEOADD 命令填充,该命令返回指定单元中两个指定成员之间的距离。

如果一个或两个成员都缺失,则该命令返回 NULL 。

该单位必须是以下之一,并且默认为米:

  • m 为米。

  • km 为千米。

  • mi 为英里。

  • ft 为英尺。

假设地球是一个完美的球体,计算距离,因此在边缘情况下可能出现高达0.5%的误差。

127.0.0.1:6379> geodist china:city beijing shanghai         //北京到上海的直线距离
"1067378.7564"
127.0.0.1:6379> geodist china:city beijing shanghai km
"1067.3788"

实现附件的人功能(获得所有人的地址)

GEORADIUS 
127.0.0.1:6379> georadius china:city 110 30 1000 km    //以经纬度110 30为点,半径1000km内的城市
1) "chongqing"
2) "hangzhou"
GEORADIUSBYMEMBER 
127.0.0.1:6379> GEORADIUSBYMEMBER china:city shanghai 4000 km   //上海附近4000km的城市
1) "chongqing"
2) "hangzhou"
3) "shanghai"
4) "beijing"

GEO底层是用zset封装的 我们可以用zrme 删除元素

127.0.0.1:6379> zrange china:city 0 -1

  1. "chongqing"
  2. "hangzhou"
  3. "shanghai"
  4. "beijing"
    127.0.0.1:6379> zrem china:city beijing
    (integer) 1

hyperloglog

什么是基数? 不重复的元素

应用场景,可以做一些网站的浏览次数,有一些误差

127.0.0.1:6379> pfadd mykey a b c d e f g h i k    //添加元素
(integer) 1
127.0.0.1:6379> pfadd mykey2 d e                  
(integer) 1 
127.0.0.1:6379> pfcount mykey2                     //查看元素的个数
(integer) 2
127.0.0.1:6379> pfmerge mykey3 mykey mykey2        //合并两个元素
OK
127.0.0.1:6379> pfcount mykey3
(integer) 10

BitMap

位存储 统计疫情感染人数 统计用户信息

应用场景,打卡 登录 未登录 !!! 两个状态的都可以

127.0.0.1:6379> setbit sign 0 1     //设置值
(integer) 0
127.0.0.1:6379> setbit sign 1 1
(integer) 0
127.0.0.1:6379> setbit sign 2 1
(integer) 0
127.0.0.1:6379> setbit sign 3 1
(integer) 0
127.0.0.1:6379> getbit sign 3     //获取值
(integer) 1
127.0.0.1:6379> setbit sign 4 0
(integer) 0
127.0.0.1:6379> getbit sign 4
(integer) 0
127.0.0.1:6379> bitcount sign     //
(integer) 4

事务

基本操作

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

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

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

Redis事务: 队列 -------set set set -----执行

  • 开启事务 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 1
QUEUED
127.0.0.1:6379> set k2 2
QUEUED
127.0.0.1:6379> set k3 3
QUEUED
127.0.0.1:6379> discard   //取消事务
OK
127.0.0.1:6379> get k3
(nil)

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

127.0.0.1:6379> multi                                  //开启事务
OK
127.0.0.1:6379> set k1 1
QUEUED
127.0.0.1:6379> set k2 2
QUEUED
127.0.0.1:6379> getset 1                              //语法错误
(error) ERR wrong number of arguments for ‘getset‘ command
127.0.0.1:6379> set k3 3
QUEUED
127.0.0.1:6379> ser k4 4
(error) ERR unknown command ‘ser‘                   //语法错误
127.0.0.1:6379> exec                                //执行报错
(error) EXECABORT Transaction discarded because of previous errors.
127.0.0.1:6379> get k3                             //这里是get不到的,上面的命令没有执行
(nil)

运行时数据异常, 那么执行命令的时候,其他命令是可以正常执行的

127.0.0.1:6379> set k1 v1                       //set一个值
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> set k3 v3
QUEUED
127.0.0.1:6379> exec                         //执行
1) (error) ERR value is not an integer or out of range
2) OK
3) OK
127.0.0.1:6379> get k2                      //可以发现错误后面的命令是执行了的
"v2"

监控

悲观锁:

? 认为什么时候都会处问题,非常谨慎,做什么都加锁,

乐观锁:

? 认为什么时候都不会出问题,所以不上锁,更新数据去判断在其期间是否有人改动这个数据

? mysql用version 字段来实现

Redis的监视测试

正常执行

127.0.0.1:6379> set money 100     //set
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> incrby out 20
QUEUED
127.0.0.1:6379> decrby money 20
QUEUED
127.0.0.1:6379> exec              //执行成功
1) (integer) 20
2) (integer) 80

异常执行 这里执行的时候啊money的值中途改变了,就不会执行了

技术图片


127.0.0.1:6379> watch money
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> incrby out 20
QUEUED
127.0.0.1:6379> decrby money 20
QUEUED
127.0.0.1:6379> exec                    //这里执行的时候啊money的值中途改变了,就不会执行了
(nil)

watch 可以当做Redis的乐观锁

如果取消 监视需要解锁 unwatch 在重新监视

Redis入门

标签:arch   设计   duti   rem   下标   als   null   img   缓存   

原文地址:https://www.cnblogs.com/immortal-mode/p/14375147.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!