Redis学习笔记

Nosql概述

1、单机MySQL的年代
在这里插入图片描述
90年代,一个基本网站的访问量一般不会太大,单个数据库完全足够了。那个时候,更多的去使用静态网页HTML,服务器根本没有太大压力

思考一下,这种情况:整个网站的瓶颈是什么?

  1. 数据量如果太大,一个机器放不下
  2. 数据的索引 300w就一定要建立索引,数据的索引(B+ Tree)一个机器内存也放不下
  3. 访问量(读写混合),一个服务器承受不了

只要开始出现以上的三种情况之一,那你必须要晋级了

Memcached(缓存)+ MySQL + 垂直拆分(读写分离)

网站80%的情况都是在读,每次都要去查询数据库的话就十分麻烦!所以说我们希望减轻数据的压力,我们可以使用缓存来保证效率!

发展过程:优化数据结构和索引 --> 文件缓存(IO操作)–> Memcached(当时最热门的技术)
在这里插入图片描述

分库分表 + 水平拆分 + MySQL集群

本质:数据库(读、写)

早些年数据库引擎采用 MyISAM:表锁,十分影响效率,高并发下就会出现严重的锁问题

现在数据库引擎采用 Innodb:行锁

慢慢的就开始使用分库分表来解决写的压力,MySQL在那个年代推出了表分区,这个并没有多少公司使用;MySQL的集群很好满足那个年代的所有需求

在这里插入图片描述

如今最近的年代

MySQL等关系型数据库就不够用了,数据量很多,变化很快

MySQL有的使用它存储一些比较大的文件、博客、图片,数据库表很大,效率就低了,如果有一种数据库来专门处理这种数据,MySQL压力就变得十分小(研究如何处理这些问题)大数据的IO压力下,表几乎没法更大 1亿

目前一个基本的互联网项目

在这里插入图片描述

为什么要用NoSQL

用户的个人信息(社交网络、地理位置、用户自己产生的数据、用户日志等等爆发式增长)这时候我们就需要使用NoSQL数据库的,NoSQL可以很好的处理以上的情况!

什么是NoSQL

NoSQL = No Only SQL(不仅仅是数据库)

泛指非关系型数据库的,随着web2.0互联网的诞生!传统的关系型数据库很难对付web2.0!尤其是超大规模的高并发的社区!暴露出来很多难以克服的问题,NoSQL在当今大数据环境下发展的非常迅速,Redis是发展最快的,而且是我们当下必须掌握的一个技术

很多的数据类型用户的个人信息、社交网络、地理位置。这些数据类型的存储不需要一个固定的格式;不需要多个操作就可以横向扩展的

NoSQL特点

  1. 方便拓展(数据之间没有关系,很好扩展!)

  2. 大数据量、高性能(Redis 一秒写8万次,一秒读11万次,NoSQL的缓存记录级,是一种细粒度的缓存,性能会比较高)

  3. 数据类型是多样型的(不需要事先设计数据库,随取随用,如果数据量十分大的表,很多人就无法设计了)

  4. 传统RDBMS 和 NoSQL

    传统的 RDBMS
    - 结构化组织
    - SQL
    - 数据和关系都存在单独的表中 row col
    - 操作,数据定义语言
    - 严格的一致性
    - .....
    
    NoSQL
    - 不仅仅是数据
    - 没有固定的查询语言
    - 键值对存储,列存储,文档存储,图形数据库(社交关系)
    - 最终一致性
    - CAP定理 和 BASE(异地多活)初级架构师
    - 三高问题(高性能、高可用、高可扩)
    - ...
    

了解:3V + 3高

大数据时代的 3V:主要是描述问题的

  1. 海量性 Volume
  2. 多样性 Variety
  3. 实时性 Velocity

大数据时代的 3高:主要是对程序的要求

  1. 高并发
  2. 高可扩(随时水平拆分,机器不够了,可以扩展机器来解决)
  3. 高性能(保证用户体验和性能)

真正在公司中的实践:NoSQL + RDBMS 一起使用才是最强的,阿里巴巴架构演进


阿里巴巴架构演进

开源才是技术的王道!!!

任何一家互联网的公司,都不可能只是简简单单让用户能用就好了

大量公司做的都是相同的业务(竞品协议)

随着这样的竞争,业务是越来越完善,然后对于开发者的要求也是越来越高!

Redis入门

redis会周期性的把更新的数据写入磁盘或者把修改写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。免费和开源!是当下最热门的NoSQL技术之一!也被人们称之为结构化数据库

redis能干嘛

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

特性

  1. 多样的数据类型
  2. 持久化
  3. 集群
  4. 事务

测试性能

redis-benchmark 是一个压力测试工具

官方自带的性能测试工具

redis-benchmark 命令参数
在这里插入图片描述
简单测试如下:

// 测试:100个并发连接   100000请求
redis-benchmark -h localhost -p 6379 -c 100 -n 100000

基础知识

redis默认有16个数据库,默认使用的是第0个数据库(可以使用select进行切换)

select 3 	// 切换数据库
DBSIZE		// 查看数据库的大小
keys *		// 查看数据库的所有数据
flushdb		// 清除当前数据库
flushall	// 清除全部数据库内容

思考:为什么redis的默认端口是6379

在这里插入图片描述

Redis是单线程的

Redis是很快的,官方表示,Redis是基于内存操作,CPU不是Redis性能瓶颈,Redis的瓶颈是根据机器的内存和网络带宽,既然可以使用单线程来实现,就使用单线程,所以就使用单线程了

Redis是C语言写的,官方提供的数据为 100000+ 的QPS,完全不比同样是使用 key-value的Memcache差!

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

  • 误区一:高性能的服务器一定是多线程的?
  • 误区二:多线程(CPU上下文会切换)一定比单线程效率高

核心:redis是将所有的数据全部放在内存中,所以说使用单线程去操作效率就是最高的,多线程(CPU上下文会切换:耗时的操作!!!),对于内存系统来说,如果没有上下文切换效率就是最高的!多次读写都是在一个CPU上的,在内存情况下,这个就是最佳的方案!


五大数据类型

String(字符串)

set key1 v1		// 设置key1的值为v1
get key1		// 获取key1的值
keys *			// 查看数据库内的所有数据
EXISTS key1		// 查看key1是否存在
APPEND key1 "hello"		// 向key1字符串后面追加 "hello"
STRLEN key1		// 查看key1的长度
ttl key1		// 查看离过期所剩余的时间

set views 0
incr views	// 自增加一 (i++)
decr views	// 自减减一 (i--)
INCRBY views 10		// 增加10 (i+=10),可以指定增量
DECRBY views 10		// 减少10 (i-=10),可以指定减量

// 字符串范围 range
set key1 "hello"
GETRANGE key1 0 3	// "hell"	截取字符串 [0,3]
GETRANGE key1 0 -1	// 查看全部的字符串

// 替换
set key2 "abcdefg"
get key2	// abcdefg
SETRANGE key2 1 xx	// 替换指定位置开始的字符串
get key2	// axxdefg

// setex (set with expire)	设置过期时间
// setnx (set if not exist)	不存在在设置
setex key3 30 "hello"	// 设置key3的值为 hello 30秒过期
setnx mykey "redis"		// 如果mykey不存在,创建mykey
setnx mykey "MongoDB"	// 如果mykey存在,创建失败

// mset
// mget
mset k1 v1 k2 v2 k3 v3	// 设置 k1 k2 k3的值(同时设置多个值)
mget k1 k2 k3	// 获取k1 k2 k3的值(同时获取多个值)
msetnx k1 v1 k4 v4	// msetnx是一个原子性的操作, 要么一起成功, 要么一起失败
get k4	// 获取失败

// 对象
set user:1 {name: zhangsan, age:3}	// 设置一个user:1 对象 值为JSON字符来保存一个对象
// 这里的key是一个巧妙的设计: user:{id}:{filed}, 如此设计在Redis中完全OK

mset user:1:name zhangsan user:1:age 2
mget user:1:name user:1:age

// getset 先get再set
getset db redis		// 如果不存在值, 则返回nil
get db
getset db mongodb	// 如果存在值, 获取原来的值, 并设置新的值
get db

数据结构是相通的!!!

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

  • 计数器
  • 统计多单位数量 uid:123123:follow 0
  • 粉丝数
  • 对象缓存存储

List

基本的数据类型,列表;在redis里面,我们可以把list玩成:栈、队列、阻塞队列

所有的list命令都是L开头的,Redis不区分大小命令

LPUSH list one	// 将一个值或多个值, 插入到列表头部
LPUSH list two
LPUSH list three
LRANGE list 0 -1	// 获取list内的所有值

Rpush list right	// 将一个值或多个值, 插入到列表尾部(右)

// LPOP 左移除
// RPOP 右移除
Lpop list	// 移除list的第一个元素
Rpop list	// 移除list的最后一个元素

Lindex list 1	// 通过下标获得list中的某一个值
Lindex list 0

// Llen
Llen list	// 返回列表的长度

// 移除指定的值
Lrem list 1 one		// 移除list集合中指定个数的value, 精确匹配
Lrem list 1 three	
Lrem list 2 three

// ltrim 修剪(截取)
ltrim mylist 1 2	// 通过下标截取指定的长度, 这个list已经被改变了

// rpoplpush	移除列表的最后一个元素, 将他移动到新的列表中
rpoplpush mylist myotherlist

lrange mylist 0 -1		// 查看原来的列表
lrange myotherlist 0 -1		// 查看目标列表中, 确定存在改值

// lset	将列表中指定下标的值替换为另一个值, 更新操作
EXISTS	list	// 判断列表是否存在
lset list 0 item	// 如果不存在列表我们去更新就会报错
lset list 0 item	// 如果存在, 更新当前下标的值
lset list 1 other	// 如果存在, 则会报错

// linsert 将某个具体的value插入到列把你中某个元素的前面或者后面
LINSERT mylist before "world" "other"
LINSERT mylist after world new

小结

  • 它实际上是一个链表,before Node after,left,right都可以插入值
  • 如果key不存在,创建新的链表
  • 如果key存在,新增内容
  • 如果移除了所有值,空链表,也代表不存在
  • 在两边插入或者改动值,效率最高,中间元素,相对来说效率会低一点

Set

set中的值是不能重读的!无序不重复集合

sadd myset "hello"		// set集合中添加元素
sadd myset "kuangshen"
sadd myset "lovekuangshen"
SMEMBERS myset	// 查看指定set的所有值
SISMEMBER myset hello	// 存在为1
SISMEMBER myset world	// 不存在为0

scard myset		// 获取set集合中的内容元素个数
sadd myset "lovekuangshen"

srem myset hello	// 移除set集合中的指定元素
scard myset
SMEMBERS myset	// 查看指定set的所有值

// 抽随机
SRANDMEMBER myset	// 随机抽选出一个元素
SRANDMEMBER myset 2		// 随机抽选出指定个数的元素

// 删除指定的key, 随机删除key
SMEMBERS myset	// 查看指定set的所有值
spop myset	// 随机删除一些set集合中的元素

// 将一个指定的值, 移动到另外一个set集合
smove myset myset2 "kuangshen"	// 将一个指定的值, 移动到另外一个set集合

数字集合类

  • 差集
  • 交集
  • 并集
SDIFF key1 key2		// 差集
SINTER key1 key2	// 交集 (共同好友就可以这样实现)
SUNION key1 key2	// 并集

微博、A用户将所有关注的人放在一个set集合中!将它的粉丝也放在一个集合中!共同关注、共同爱好、二度好友、推荐好友(六度分割理论)


Hash(哈希)

Map集合,key-map(key-value)键值对,本质和String类型没有太大区别,还是一个简单的 key-value

set myhash field kuangshen
hset myhash field1 kuangshen	// set一个具体的key-value
hget myhash field1	// 获取一个字段值
hmset myhash field1 hello field2 world	// set多个key-value
hmget myhash field1 field2	// 获取多个字段值
hgetall myhash	// 获取全部的数据
hdel myhash field1	// 删除field1(删除指定的字段)

// hlen
hmset myhash field1 hello field2 world	// set多个key-value
HGETALL myhash
hlen myhash	// 获取hash表的字段数量
HEXISTS	myhash field1	// 判断hash中指定字段是否存在

hkeys myhash // 只获得所有field
hvals myhash // 只获得所有value

// incr		decre
hset myhash field3 5	// 指定增量
HINCRBY myhash field3 1
HINCRBY myhash field3 -1
hsetnx myhash field4 hello	// 如果不存在则可以设置
hsetnx myhash field4 world	// 如果存在则不可以设置
hset user:1 name huake

hash的应用

  • hash变更的数据 user、name、age,尤其是用户信息之类,经常变动的信息!hash更适合于对象的存储

Zset(有序集合)

在set的基础上,增加了一个值,set k1 v1、zset k1 score1 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 500 huake
// ZRANGEBYSCORE key min max
ZRANGEBYSCORE salary -inf +inf	// 显示全部的用户 从小到大排序
ZRANGEBYSCORE salary 0 -1
ZRANGEBYSCORE salary 0 -1 withscores
ZRANGEBYSCORE salary -inf +inf withscores // 显示全部的用户并且附带成绩
ZRANGEBYSCORE salary -inf 2500 withscores	// 显示工资小于2500员工的升序排序

// 移除rem中的元素
zrange salary 0 -1
zrem salary xiaohong	// 移除有序集合中的指定元素
zrange salary 0 -1
zcard salary 	// 获取有序集合中的个数
ZREVRANGE salary 0 -1	// 从大到小进行排序
ZRANGEBYSCORE salary -inf +inf withscores	// 显示全部的用户并且附带成绩
ZRANGEBYSCORE salary -inf 2500 withscores	// 显示工资小于2500员工的升序排序

三种特殊数据类型

geospatial 地理位置

  • 朋友定位
  • 附近的人
  • 打车距离计算

Redis的Geo在Redis3.2版本就推出了!这个功能可以推算地理位置的信息,两地之间的距离,方圆几里的人

可以查询一些测试数据,只有六个命令

相关命令:
	- GEOADD
	- GEODIST
	- GEOHASH
	- GEOPOS
	- GEORADIUS
	- GEORADIUSBYMEMBER

getadd

# getadd 添加地理位置
# 规则: 两级无法直接添加, 我们一般会下载城市, 直接通过Java程序一次性导入
# 参数 key	值(纬度、经度、名称)
# 有效的经度从 -180度到180度
# 有效的纬度从 -85.05112878度到85.05112878度
# 当坐标位置超出上述指定范围时, 该命令将会返回一个错误
geoadd china:city 116.40 39.90 beijing
geoadd china:city 127.47 31.23 shanghai

getpos

获得当前定位:一定是一个坐标值

GEOPOS china beijing chongqing	# 获取指定的城市的经度和纬度

GEODIST

两人之间的距离

单位:

  • m 表示单位为米
  • km 表示单位为千米
  • mi 表示单位为英里
  • ft 表示单位为英尺

GEORADIUS以给定的经纬度为中心,找出某一半径内的元素

GEORADIUS china:city 110 30 1000 km  # 以100 30 这个经纬度为中心, 寻找方圆1000km内的城市
GEORADIUS china:city 110 30 500 km withdist  # 显示到中间距离的位置
GEORADIUS china:city 110 30 500 km withcoord  # 显示他人的定位信息
GEORADIUS china:city 110 30 500 km withdist withcoord count 1  # 筛选出指定的结果

GEORANIUSBYMEMBER

GEORANIUSBYMEMBER china:city beijing 1000 km
GEORANIUSBYMEMBER china:city shanghai 400 km

GEOHASH 命令 - 返回一个或多个位置元素的 Geohash表示

该命令将返回11个字符的Geohash字符串

# 将二维的经纬度转换为一维的字符串, 如果两个字符串越接近, 那么则距离越近
geohash china:city beijing chongqing

GEO底层的实现原理其实就是 Zset,我们就可以使用Zset命令来操作geo

ZRANGE china:city 0 -1	# 查看地图中全部的元素
zrem china:city beijing		# 移除指定元素
  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值