初识redis(分布式系统, redis的特性, 基本命令)

什么是分布式

谈到分布式时首先要提到单机架构(应用程序+数据库),这样的两个服务器是部署在同一台主机上的,但随着用户量和访问量的增加,此时一台主机已经处理不了这样的数据量,此时就要将应用程序和数据库服务器分离到不同的主机上,所以当引入多台主机时,此时的系统就是分布式系统了。

但随着用户的进一步增加,就意味着需要应用程序可能会将CPU内存等资源耗尽,就需要对应用程序和数据库这样的结构进行修改,引用负载均衡,就是将应用服务器变为集群,由负载均衡来进行任务的发配,来提高处理的效率,引入更多应用服务器就表示有更多的CPU内存等资源。同时还有一个好处就是当集群中的服务器出现宕机的情况,此时集群中的其他服务器仍然可以进行承担服务,提高了系统的可用性。

应用服务器增加,但数据库服务器还是要承担一切,为了降低数据库服务器的压力就可以引入读写分离,将数据库分为主从,主服务器主要负责写功能,从服务器负责读功能。

为了解决数据库访问慢的问题,将数据库数据分为冷热数据,将数据库中经常被访问的热点数据放入缓存中(redis就是处于这样的位置),而相对"冷"的数据就放在硬盘中(仍然存放的是全量数据)。但是这里可能存在缓存服务器和硬盘服务器数据不能同步的问题。

应用服务器会出现内存CPU等资源耗尽问题,数据库服务器就也会出现这样的问题,当一个表或库中的数据量太大,此时就需要进行分库分表来解决。

总而言之,分布式其实就是一台主机的资源不够用,需要引入多台主机来进行分担任务,同时需要根据不同的情况分配不同主机的任务。

redis的特点

上面了解到redis其实就是一个在内存中存储数据的中间件。

在内存中存储:redis最核心的一个特点,MySQL是使用"表"这样的结构存储数据,redis则是使用"键值对"这样结构的非关系型数据库。

可编程的:redis可以通过一些简单的交互式命令进行操作,也可以通过脚本来进行操作。

可拓展的:redis可以除redis提供功能外,还可以通过C/C++,Rust等编程语言编写拓展(动态链接库,windows上dll可以供exe调用)。

持久化的:redis是把数据存储在内存中的,但内存中的数据是易失的,所以redis会把数据在硬盘上中备份一份,如果出现系统重启或进程退出的情况,下次就会重新去硬盘上加载数据

可以支持集群:一个redis支持的存储空间是有限的,所以就可以引入多个主机,在每个主机上安装redis节点。

高可用:redis支持主从这样的结构,主服务器挂了,从服务器就可以直接顶替,从服务器其实就是主服务器的备份。

访问速度快:

1.数据存放在内存中

2.redis中的核心功能都是比较简单逻辑,核心功能都是比较简单的数据结构

3.redis使用的是单线程模型,可以减少线程之间的竞争开销(多线程高效率的前提是CPU密集执行任务,使用多个线程可以充分利用cpu资源,但是redis进行得是简单的操作内存中的操作系统,引入多线程可能会触发加锁,降低效率)

redis的使用场景

提到数据存储会想到大的空间去存储,但是不妨一些场景需要比较快的访问速度,redis就可以作为数据库来进行存储数据.

redis可以作为缓存,存储比较"热"的数据.

redis可以作为一个消息队列.

redis存全量数据的场景是redis作为主要的数据库,每条数据都比较重要,作为缓存的场景是将redis作为一个辅助的角色.

redis的限制

redis是在内存中存储,所以不能够大规模存储数据.

在一些场景下,redis会更慢,例如是直接使用内存中的hashmap还是使用redis,这里如果使用redis时,会先通过网络操作内存,但是hashmap是直接操作内存.

好处是当重启服务时,存储的数据可以重新加载,而hashmap中的数据就直接没了.

redis客户端的介绍

redis和MySQL一样也是客户端-服务器结构的程序.

在Linux系统下下载redis,下载后需要使用rides-cli来打开redis的命令行客户端.

当然redis不止一个客户端,还有图形化客户端和基于redis提供的api自行开发的客户端(类似于MySQL中的JDBC).

redis的基本命令

redis中两个最基本的命令是 get 和 set

前面谈到redis是一个使用键值对存储数据的非关系型数据库,所以它的存储方式是类时于哈希表的,redis中使用key-value的形式进行存储,使用set存储键值对,使用get获取value.

使用set

使用get,当输入的key不存在时会返回nil

此外,redis是不区分大小写,并且字符串不需要使用引号,当然使用也是可以的.

redis的常见全局命令

一个易误解的点:redis可以支持多种数据结构,这里的数据结构不是指redis使用的"键值对",而是key是字符串,value则可以是各种数据结构.全局命令就是在任何一个数据结构中都可以使用的.

1)keys pattarn : 查询当前服务器上所有匹配的key,可以使用一些通配符来描述key的"模样",来找到key.

来自官方文档:

?表示只能有一个任意字符

*表示有0或任意个任意字符

ae\]表示只能匹配括号内中的字符 \[\^e\]表示除以外所有字符 \[a-b\]表示a\~b所有字符 我们可以使用keys\*查询当前redis中的所有key,但是这是十分危险的操作,很可能导致服务器宕机. 2)exists:表示查找key的个数,针对多个key返回个数.比如查找三个key,一个不存在两个存在,此时返回2. ![](https://i-blog.csdnimg.cn/direct/2b8d7dd7eb5b44c898ccd463c3f8e90f.png) 简单的来说,exists表示的是当前的key存在的个数,这样的操作并不是害怕key重复,而为了在寻找多个key的时候更加方便. ![](https://i-blog.csdnimg.cn/direct/7f44fe0a5c35456998d40bc61ea827cb.png) 这样的查找时间复杂度是O(1),而查找多个key时,此时就会时间复杂度就是O(n)这里的n等于查找key的个数. 上面的一次查找两个key和分两次查找两个key的写法有什么区别呢,redis是一个客户端-服务器形式的程序,当进行一次查询时,客户端和服务器实际上会通过网络进行通信,而分两次进行查找就会产生多次的网络通信,这样就会相较于直接操作内存会更快. 3)del del是删除指定的key,这里的del是相比于mysql中的delete较安全的操作,这是因为redis是一般是作为一个缓存数据库来使用的.这里删除的可能只是一部分热点数据,而真正的全量数据是存储在MySQL中的. 4)expire expire是给key设定过期时间,超过这个时间就会删除这个key ![](https://i-blog.csdnimg.cn/direct/15a17682fe9043c98dde17285a27ed6d.png) expire后面表示的是秒,还有一个pexpire使用的是毫秒. 5)ttl 表示还剩多久过期时间. ![](https://i-blog.csdnimg.cn/direct/6fd7e54634f24c45b0a5050153f6ba7a.png) 6)type 查看当前key的value的数据类型(数据结构类型) 不同的数据结构有不同的插入方法. ### redis的过期策略(重) redis是如何判断一个key是否过期,难道是遍历一遍库中的所有key?这样的操作慢且没效率. 这里使用了两种方式:惰性清理和定期清理 惰性清理表示的是如果当前key已经过期,此时还是放在库中.当需要这个key的时候再进行判断一下可以是否过期. 定期清理表示的是每次只抽取一部分,进行验证是否过期,抽取一部分是为了检查的速度足够快.这里规定时间是为了防止扫描key时间过长耽误正常的线程(redis是单线程模型). 但上面的这些操作可能并不能清理完全,redis还有内存清理机制. ## redis的数据类型和编码方式 redis中的主要的数据类型有hash(哈希表),string(字符串),set(集合),zset(有序集合),list(列表)等. 但是这些数据类型的底层编码其实并非按照类型的名字进行的.例如hash底层并非按照哈希表严格进行的,而是在保证时间复杂度的前提下又优化增加了一些其他的编码方式. **hash : hashTable,ziplist** hashTable是redis中的哈希表的实现,和Java标准库中的hashTable不是同一物. ziplist:当哈希表比较小时,redis就会将它压缩以减小占用内存. **string : raw,int,embstr** raw是标准的字符串实现,Java中表示的是用byte数组实现的字符串. int数据是数字的时候,此时就用int. embstr表示当字符串比较短的时候使用. **list : linkedlist(链表),ziplist** **set:hashTable,intset** set中都是整数就会优化成intset **zset:skipset,zipset** skipset(跳表)表示的是一个节点中有多个指针域,可以通过指针域进行查询,时间复杂度是O(logn). 我们可以通过object encoding key命令查看具体的key的具体的类型. ![](https://i-blog.csdnimg.cn/direct/3250c0aede9d4d6da55aea2fa025a6d0.png) ## redis的单线程模型 redis使用的是单线程模型,但并不是说redis服务器中只有一个线程,其实redis有其他线程,但是都是用于网络IO,通过网卡读写到数据,然后将任务交给主线程,这个单线程指的是处理任务的线程只有一个.那么如果有多个客户端同时访问一个服务器,那么此时服务器就会采用串行执行的方法来执行任务,也就是会一个个执行任务. redis为什么访问速度快? 1)redis相比于MySQL等访问硬盘的数据库,是直接访问内存的. 2)redis的核心任务是比较简单的,相较于mysql中的各种查询条件和约束 3)是单线程模型,因为redis的任务比较简单,任务处理快,所以使用单线程模型可以减少线程间的竞争,这样自然就减少了CPU开销. 4)在进行网络IO时,redis采用了epoll这样的IO多路复用机制(一个线程可以管理多个socket.当一个客户端与服务器建立连接时,服务器就需要分配一个socket给客户端,但是并不是所有socket都活跃,所以就让一个线程管理多个socket减少创建线程消耗的资源).

相关推荐
Elastic 中国社区官方博客5 小时前
在 Elasticsearch 中使用 Mistral Chat completions 进行上下文工程
大数据·数据库·人工智能·elasticsearch·搜索引擎·ai·全文检索
编程爱好者熊浪6 小时前
两次连接池泄露的BUG
java·数据库
cr7xin7 小时前
缓存三大问题及解决方案
redis·后端·缓存
爱怪笑的小杰杰8 小时前
浏览器端缓存地图请求:使用 IndexedDB + ajax-hook 提升地图加载速度
ajax·okhttp·缓存
TDengine (老段)8 小时前
TDengine 字符串函数 CHAR 用户手册
java·大数据·数据库·物联网·时序数据库·tdengine·涛思数据
qq7422349848 小时前
Python操作数据库之pyodbc
开发语言·数据库·python
姚远Oracle ACE8 小时前
Oracle 如何计算 AWR 报告中的 Sessions 数量
数据库·oracle
Dxy12393102169 小时前
MySQL的SUBSTRING函数详解与应用
数据库·mysql
码力引擎9 小时前
【零基础学MySQL】第十二章:DCL详解
数据库·mysql·1024程序员节
杨云龙UP9 小时前
【MySQL迁移】MySQL数据库迁移实战(利用mysqldump从Windows 5.7迁至Linux 8.0)
linux·运维·数据库·mysql·mssql