Redis学习笔记
Posted 想成为大师啊
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Redis学习笔记相关的知识,希望对你有一定的参考价值。
Nosql概述
1、单机mysql的年代
90年代,一个基本网站的访问量一般不会太大,单个数据库完全足够了。那个时候,更多的去使用静态网页html,服务器根本没有太大压力
思考一下,这种情况:整个网站的瓶颈是什么?
- 数据量如果太大,一个机器放不下
- 数据的索引 300w就一定要建立索引,数据的索引(B+ Tree)一个机器内存也放不下
- 访问量(读写混合),一个服务器承受不了
只要开始出现以上的三种情况之一,那你必须要晋级了
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特点
-
方便拓展(数据之间没有关系,很好扩展!)
-
大数据量、高性能(Redis 一秒写8万次,一秒读11万次,NoSQL的缓存记录级,是一种细粒度的缓存,性能会比较高)
-
数据类型是多样型的(不需要事先设计数据库,随取随用,如果数据量十分大的表,很多人就无法设计了)
-
传统RDBMS 和 NoSQL
传统的 RDBMS - 结构化组织 - SQL - 数据和关系都存在单独的表中 row col - 操作,数据定义语言 - 严格的一致性 - ..... NoSQL - 不仅仅是数据 - 没有固定的查询语言 - 键值对存储,列存储,文档存储,图形数据库(社交关系) - 最终一致性 - CAP定理 和 BASE(异地多活)初级架构师 - 三高问题(高性能、高可用、高可扩) - ...
了解:3V + 3高
大数据时代的 3V:主要是描述问题的
- 海量性 Volume
- 多样性 Variety
- 实时性 Velocity
大数据时代的 3高:主要是对程序的要求
- 高并发
- 高可扩(随时水平拆分,机器不够了,可以扩展机器来解决)
- 高性能(保证用户体验和性能)
真正在公司中的实践:NoSQL + RDBMS 一起使用才是最强的,阿里巴巴架构演进
阿里巴巴架构演进
开源才是技术的王道!!!
任何一家互联网的公司,都不可能只是简简单单让用户能用就好了
大量公司做的都是相同的业务(竞品协议)
随着这样的竞争,业务是越来越完善,然后对于开发者的要求也是越来越高!
Redis入门
redis会周期性的把更新的数据写入磁盘或者把修改写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。免费和开源!是当下最热门的NoSQL技术之一!也被人们称之为结构化数据库
redis能干嘛
- 内存存储、持久化,内存中是断电即失,所以持久化很重要(RDB、AOF)
- 效率高,可以用于高速缓存
- 发布订阅系统
- 地图信息分析
- 计时器、计数器(浏览量)
- …
特性
- 多样的数据类型
- 持久化
- 集群
- 事务
- …
测试性能
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
以上是关于Redis学习笔记的主要内容,如果未能解决你的问题,请参考以下文章