NoSQL
QPS(queries per second),mysql的查询较低
NoSQL是适合于大数据存储的技术方案
NoSQL数据库按照其存储类型可分为:
类型 | 部分代表 | 特点 |
---|
列族数据库 | HBase | 按列存储数据,最大的特点是方便存储结构化和半结构化数据,方便做数据压缩,对针对某一列或者某几列的查询有非常大的I/O优势,适合于批量数据处理和即时查询(大数据) | 文档数据库 | MongoDB | 文档数据库一般用类json格式存储数据,存储的内容是文档类型,这样也就有机会对某些字段建立缩影,实现关系数据库的某些功能,但不提供对参照完整性和分布事务的支持 | KV数据库 | Redis | 可以通过key快速查询到其value,有基于内存和基于磁盘两种实现方案(用来做缓存 ) | 图数据库 | flockdb | 使用图结构进行语义查询的数据库,它使用节点,边和属性来表示和存储数据。图数据库从设计上,就可以简单快速的检索难以在关系系统中建模的复杂层次结构 | 对象数据库 | db4o | 通过类似面向对象语言的语法操作数据库,通过对象的放肆存取数据 |
Redis数据库
Redis是一种基于键值对的NoSQL数据库,它提供了对多种数据类型(字符创、哈希、列表、集合、有序集合、位图等)的支持。Redis将数据放在内存中,所以读写速度很快,并且,Redis也提供了持久化机制,能够将内存中的数据保存到硬盘上,在发生意外状况时,数据也不会丢失,此外,Redis还支持键过期、地理信息运算、发布订阅事务、管道、Lua脚本扩展德功能,如果项目中药实现高速缓存和消息队列这样的服务,交给Redis就可以了
Redis(remote dictionary server),是一个用ANSIC编写的高性能的key-value存储系统,与其他key-value存储系统相比,
Redis的优点
- Redis的读写性能极高,并且有丰富的特性(发布,订阅,事务,通知等)
- 支持数据表的持久化(RDB和AOF),可以将内存中的数据保存到磁盘中,重启的时候可以再次加载进行使用
- 支持多种数据类型
- 支持主从复制(实现读写分离)以及哨兵模式(监控master是否宕机并自动调整配置)
- 支持分布式集群,可以很容易的通过水平扩展来提高系统的整体性能
- 基于TCP提供的可靠传输服务进行通信,很多编程语言提供了Redis客户端支持
Redis适合做什么
- 做缓存:
- Redis字符串、哈希表两种数据节后适合用来存储大量的键值对信息,从而实现高速缓存
- 做队列:
- 使用“列表”数据接收,可以实现普通级和优先级队列的功能
- 使用“有序集合”数据结构,可以实现优先级队列
- 使用“哈希表”数据结构,可以实现延时队列
- 去重
- 利用“集合”数据结构,可以实现小批量数据的去重
- 利用“字符串”数据结构的位操作,可以实现布隆过滤器,实现超大规模数据的去重
- 利用自带的HyperLogLog数据结构,可以实现超大规模数据的去重和技术
- 积分板
- Redis的“有序集合”功能可以是吸纳积分板功能还能实现自动排序,排名功能
- 发布/订阅
- Redis自带的“发布/订阅”模式可以实现多对多的“发布/订阅”功能
Redis的应用场景
- 高速缓存:将不常变化但又经常被访问的热点数据放到Redis数据库中,可以大大降低关系型数据库的压力,从而提升系统的响应性能
- 排行榜:利用Redis中的列表和有序集合,可以很方便的构造各种排行榜系统
- 商品秒杀/投票点赞:Redis提供了对计数操作的支持,网站上常见的秒杀、点赞等功能都可以利用Redis的计数器通过+1或-1的操作来实现,从而避免使用关系型数据的update操作
- 分布式锁:利用Redis可以跨多态服务器实现分布锁(类似于线程锁,但是能够被多台机器上的多个线程或进程共享)的功能,用于实现一个阻塞式操作
- 消息列表:消息列表和高速缓存一样,是一个大型网站不可缺少的基础服务,可以实现业务解耦和非实时业务消峰等特性
Redis的安装和配置
wget https://download.redis.io/releases/redis-6.2.3.tar.gz?_ga=2.46010854.317471521.1620276830-457645418.16202768301
tar -zxvf redis···
sudo make && make install
启动服务器
redis-server
移动
cd redis-6.2.3/
cp redis.conf /usr/loacl/etc/
启动变成
redis-server /usr/local/etc/
客户端启动
redis -cli
Windows下Redis的启动
cmd
cd D:\Software\Redis
redis-server
cmd
cd D:\Software\Redis
redis-cli
Redis的配置
在redis源代码的目录下有一个名为redis.conf的配置文件
vim redis.conf
1.配置将Redis服务绑定到指定的IP地址和端口
bind 127.0.0.1
port 6379
2.设置后台运行(以守护进程方式运行)
daemonize yes
3.设置日志级别,可选值(debug:调试,verbose:详细,notice:通知,warning:警告)
loglevel warning
4.配置数据库的数量,默认是16个
databases 16
kill redis时,查找其UID
ps aux|grep redis
5.配置数据写入规则
save 900 1 #900秒(15分钟)内修改过一个key,写入一次数据库
6.配置Redis的持久化机制-RDB
rdbcompression yes #压缩RDB文件
rdbchecksum yes #对RDB文件进行校验
dbfilename dump.rdb #RDB数据库文件的文件名
dir/var/loacl/redis #RDB数据库文件的文件名
7.配置Redis的持久化机制-AOF
appendonly no
appendfilename "appendonly.aof"
8.配置慢查询
slowlog-log-slower-than 10000 #一次操作超过10000毫秒被视作一次慢查询
slowlog-max-len 128 #最多纪录128次满查询
Redis的服务器和客户端
启动Redis服务器,下面的防止以指定的配置文件启动Redis服务
redis-server redis.conf
用Redis客户端连接服务器
redis-cli -h localhost -p 6379
Redis持久化
Redis在运行时,所有的数据都会保存在内存中,进程结束以后,会将数据写入到硬盘中。启动时,会读取硬盘里的内容,并将内容全部加载到内存中(会大量的占用内存)
RDB
默认的持久化方式,是对内存中的数据进行镜像,并以二进制的形式保存到dump.rdb文件中。会根据配置文件的时间节点对文件进行持久化
优点:速度快,直接镜像内存里的数据,文件小
缺点:数据有可能会丢失,在两次保存间隔内的数据,有可能会丢失
AOF
AOF(Append only file)持久化,将修改的每一条指令记录进APPendonly.aof中,需要修改配置文件,来打开aof功能
appendsync yes
appendsync always:每次有新命令追加到aof文件时就执行一个持久化,非常慢,但是安全
appendsync everysec:每次执行一次持久化,足够快(和使用rdb持久化差不多)并且在故障时只会丢失1秒钟的数据
appendfsync no:从不持久化,将数据交给操作系统来处理,redis吃力命令速度加快但是不安全
优点:适合保存增量数据,数据不丢失
缺点:文件体积大,恢复时间长
对redis的操作:读取rdb文件,读取aof文件,删除aof文件
redis字符串操作
创建字符串
set key value
? 其中:
- key可以是数字,大小写字,下划线或者中文(但是不建议使用中文)
- value可以是任意内容
查询字符串
keys *
? 查看Redis中有多少key
读取字符串
get key
? 如果获取一个不存在的Key,则会返回nil
修改key中的值
set key 新值
-
如果不存在这个key,那么set命令可以创建他,如果Redis中有了这个key,则会用新值覆盖旧值 -
如果不希望set命令覆盖旧值,可以使用一个参数’NX’,即如果一个key已经存在于Redis中,那么久不覆盖,直接放弃操作 -
要做的操作是在字符串末尾加上其他字符创,则可以不使用set,而用apppend apppend key value
-
如果值的内容有空格,使用双引号将内容包裹起来 -
该值加减某个数 incr key #让key里的数字加1
decr key #让key里的数字减1
incr key n #让key里的数字加n
decr key n #让key里的数字减n
使用Python实现
Python操作人爱的是的第三方库叫’redis-py’。要使用它,需要首先通过pip命令来安装它
python3 -m pip install redis
创建Redis的客户链接:
import redis
client=redis.Redis()
创建字符串
client.set('key','value')
client.set('key','value',nx=true)
获取字符串的值
client.get('key')
注:
- 不论是Python的字符串还是数字,一旦尽量Redis再出来就会变成bytes型的数据,所以要注意格式的转换
- 字符串值应用在小量级的数据记录中。如果数据量超过了百万级,那么使用字符串来保存简单的映射关系会浪费大量内存。此时应该使用Hash
- 如果Redis中有大量的key,那么执行’keys *'会对Redis性能造成短暂影响,甚至到时Redis失去响应
列表
插入数据
列表分左右两个方向。所以可以从左右两侧插入。插入可以理解为推入(push)
语法:
lpush key value1 value2 value3 #从列表左侧插入数据
rpush key value1 value2 value3
使用Python:
client.lpush('key','value1','value2')
? 向列表中批量添加数据
datas=['one','two','three']
client.rpush('key',*datas)
查看数据
-
查看列表的长度 llen key
python中: client.llen(key)
-
根据索引查看数据 lrange key 开始索引 结束索引
python中: client.lrange(key,开始索引,结束索引)
-
查看列表的所有数据 lrange key 0 -1
? Redis的列表支持“负索引”,-1表示最右边的数据 ? 一般是先查看列表的长度,如果确定数据量很小,则列出所有的值,若果数据量很大,则可以使用索引查看头几条数据和末尾的几条数据 Python中: client.lrange('key',0,-1)
-
弹出数据 lpop key
rpop key
? 在弹出数据的同时,被弹出的这个数据也会从列表中删除 python中: client.lpop(key)
修改数据
lset key index 新值
? python中:
client.lset(key,index,value)
列表的应用:
在工程上,Redis列表一般用来作为一个队列,存放一批可以使用相同逻辑处理的数据
#简易分布式短信发送程序
import redis
import json
client=redis,Redis(host='')
while True:
phone_info_bytes=client.lpop('phone_queue')
if not phone_info_butes:
break
phone_info=json.loads(phone_info_bytes)
retry_times=phone_info.get('retry_number',0)
result=send_sms(phone_number)
if result:
print(f'手机号:{phone_number}短信发送成功!!!')
continue
if retry_times>=3:
print(f'重试超过3次,放弃手机号:{phone_number}’)
continue
next_phone_info={'phone_number':phone_number,'retry_times':retry_times+1}
client.rpush('phone_queue',json.dumps(next_phone_info))
集合
集合是Redis基本数据结构之一
集合里面的数据不能够重复,也没有顺序,由于没有顺序,自然不存在“左右侧”一说
插入数据
语法格式:
sadd key value1 value2 value3
? 注:
? Python中:
client.sadd('key','value1','value2')
datas=[9,0,'one']
client.sadd('key',*datas)
读取数据
查询集合里面元素的数量
语法格式:
scard key
Python中:
client.scard('key')
集合中获取数据
语法格式:
spop key count
? 注:
- 如果count省略,则表示随机获取一条数据
- count大小超过了集合总数据的调试,获取集合中所有的数据
- 由于集合无序,所以spop会随机获取集合中的数据
- 获取一条数据后,这一条数据就会从集合中删除
python中:
client.spop('key')
? 注:
- 在Python中,spop关键字没有count参数,一次只能获取一条数据,如果想一次获取多条数据,可以使用循环来实现
- 获取到的数据类型为bytes
获取集合中所有的数据
语法格式:
smembers key
? 注:
- smembers 获取数据时,并不会删除集合中的数据
Python中:
client.smembers('key')
? 注:smember返回的数据类型是set,但是里面的每一个数据都是bytes类型
判断集合中是否包含了某个元素
语法格式:
sismember key value
? 注:
删除数据
语法格式:
srem key value1 value2
Python中:
client.srem('key','value')
集合的交集
语法格式:
sinter key1 key2 key3
python中:
client.sinter('key1','key2')
集合的并集
语法格式:
sunion key1 key2 key3
python中:
client.sunion('key1','key2')
集合的差集
语法格式:
sdiff key1 key2 key3
? 求所有只在key1对应的集合中有,在key2,key3集合中没有的数据构成集合
python 中:
client.sdiff('key1','key2')
集合的应用
- 根据集合内数据不重复的特性实现去重并记录信息
- 利用多个集合计算交集,并集,差集
果数据存在,则返回1,反之,返回0
删除数据
语法格式:
srem key value1 value2
Python中:
client.srem('key','value')
集合的交集
语法格式:
sinter key1 key2 key3
python中:
client.sinter('key1','key2')
集合的并集
语法格式:
sunion key1 key2 key3
python中:
client.sunion('key1','key2')
集合的差集
语法格式:
sdiff key1 key2 key3
? 求所有只在key1对应的集合中有,在key2,key3集合中没有的数据构成集合
python 中:
client.sdiff('key1','key2')
集合的应用
- 根据集合内数据不重复的特性实现去重并记录信息
- 利用多个集合计算交集,并集,差集
|