IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 大数据 -> 题目>>redis>>1 -> 正文阅读

[大数据]题目>>redis>>1

1、Redis效率高的原因?

  • 完全基于内存存储实现
    • 完全基于内存,绝大部分请求时纯粹的内存操作,速度非常快。
  • 合理的数据编码
    • Redis支持多种数据类型,每种基本类型可能对多种数据编码。
  • 单线程模型
    • Redis是单线程模型(处理客户端请求的线程为单线程)。避免了CPU不必要的上下文切换和竞争锁的消耗
    • 缺点:在执行命令过长(keys、hgetall)时,会造成排队阻塞。
  • 合理的线程模型
    • 使用了多路复用I/O模型,非阻塞I/O;
    • 可以让单个线程高效的处理多个连接请求。Redis使用epoll作为IO多路复用技术的实现,会将epoll中的连接、读写、关闭等都转换为事件,不在网络IO上浪费过多时间。

2、为什么Redis6.0之后改为多线程?

  • Redis6.0之前,在处理客户端请求时,包括读socket、解析、执行、写socket等都是由一个顺序串行的主线程处理。
  • Redis6.0之后,还是使用单线程模型来处理客户端请求,只是使用多线程处理数据的读写和协议解析,执行命令还是用单线程。
  • 效果:解决redis由于网络IO引起的性能瓶颈,使用多线程提升IO读写的效率,从而整体提高redis性能。

3、Redis的过期策略?

在set key的时候,可以设置一个过期时间expire key time。这个key的过期策略有以下几种:

  • 定期过期
    • 每个设置过期时间的key都需要创建一个定时器,到过期时间就会对key进行清除。
    • 优点:会立即清除过期的数据,对内存很友好;
    • 缺点:会占用大量的CPU资源去清除过期的数据,从而影响缓存的响应时间和吞吐量
  • 惰性过期
    • 只有当访问一个key时,才会判断该key是否已经过期,过期则进行清除
    • 优点:可以最大化的节省CPU资源
    • 缺点:对内存很不友好。极端情况下会出现大量的过期key没有再次被访问,从而不会被清除,造成占用大量内存。
  • 定期过期
    • 每个一定的时间,会扫描一定数量的数据库的expires字典中的key,并清除已经过期的key。
    • 定期惰性的折中方案,通过调整时间间隔和限定耗时,实现CPU和内存资源达到最优的平衡效果。
  • 综合策略
    • 若只是用定期过期,还是会出现很多key为被删除的情况;此时添加惰性过期,将定期过期未清除的数据进行删除;业务量越来越大时,这种综合策略也支撑不了性能了,这时就需要使用redis的内存淘汰策略。

4、Redis的内存淘汰策略?

  • volatile-lru:当内存不足以容纳新写入的数据时,在设置了过期时间的key中使用LRU(最近最少使用)算法进行淘汰;
  • allkeys-lru:当内存不足以容纳新写入的数据时,在所有key中使用LRU;
  • volatile-lfu:当内存不足以容纳新写入数据时,在过期的key中,使用LFU(新的最少使用的回收模式:一段时间内使用频率)删除key;
  • allkeys-lfu:当内存不足以容纳新写入的数据时,在所有key中使用LFU;
  • volatile-random:当内存不足以容纳新写入的数据时,在设置了过期key中,随机淘汰数据;
  • allkeys-random:当内存补足语容纳新写入的数据时,在所有key中随机淘汰数据;
  • volatile-ttl:当内存不足以容纳新写入数据时,在设置了过期key中,根据过期时间进行淘汰,最早过期的优先淘汰;
  • noeviction:默认策略,当内存不足以容纳信息写入数据时,写入操作会报错。

5、Redis的事务机制

  • Redis事务具有顺序性、一次性和排他性的执行一个队列中的一系列命令。
    在这里插入图片描述
  • 执行事务的流程:
    • 开始事务(MULTI)
    • 命令入队列
    • 执行事务(EXEC)、撤销事务(DISCARD)
  • Redis事务特点
    • 与Mysql的事务不同,Redis事务遇到执行错误时,不会进行回滚,而是简单放过,并保证其他命令的正常执行,不会保证事务的原子性;
    • 如果事务执行过程中,Redis挂掉了,未执行的命令部分就被丢弃了。

6、介绍一下Redis的Hash槽?

概念

  • Redis集群中有16384(2^14)个Hash槽,每个key通过CRC16校验后对16384个取模来决定放在哪个槽。集群的每个节点负责部分Hash槽,每个节点都不会存储所有的槽。
  • 优点:可以方便的添加或移除节点,增删改某一个节点,都不会造成集群不可用。当需要新增节点时,需要把其他节点的某些Hash槽挪到新节点;当需要移除节点时,需要把移除节点上的Hash槽挪到其他节点上。在操作时,并不需要停掉所有的Redis服务

Redis Cluster为什么设计16384个槽?

  • 如果槽位为65535,则发送心跳信息的消息头即为8k,心跳信息的包过于庞大
    • 消息头的大小为 65535 / 8 / 1024 = 8kb。每秒redis节点需要发送一定数量的ping消息作为心跳包,8kb明显太大。
  • 槽位越小,节点数少的情况下,压缩率高
    • Redis主节点的配置信息中,所负责的Hash槽会通过一张bitmap来保存。在传输过程中,会对bitmap进行压缩,但是如果bitmap的填充率(slots / 节点数)过高的话,压缩率会很低。
    • 如果节点书很少,Hash槽很多,bitmap压缩率就很低。

7、Redis在集群中查找key时,如何定位到具体节点?

定位步骤

  • 首先使用CRC16算法对key进行hash,再将hash值对16384进行取模,得到具体的槽位hash slot
  • 根据节点与槽位的映射信息(与集群建立联系后,客户端可以取得槽位映射信息),找到对应的节点地址;
  • 在具体节点地址找key。todo

8、Redis涉及到的协议?

RESP协议 - Redis Serialization Protocol

  • 是专门为Redis设计的一套序列化协议
  • 优点:实现简单、解析速度快、可读性好。

gossip协议

  • 节点间的内部通信方式,redis cluster节点之间通过gossip协议进行通信。
  • 协议包含多种消息:ping、pong、meet、fail等。
    • meet:某个节点发送meet给新加入的节点,让新节点加入集群中,新节点就会开始与其他节点进行通信;
    • ping:每个节点都会频繁的给其他节点发送ping,其中包含自己的状态还有自己维护的集群元数据;互相通过ping 交换元数据
    • pong:返回ping和meet,包含自己的状态和其他信息。用于信息广播和更新;
    • fail:某个节点判断另一个节点fail之后,会发送fail给其他节点,通知另一个节点宕机信息。

9、redis中map的扩容方式

Redis中的Hash和Java的HashMap相似,都是数组+链表的结构,当发生Hash碰撞时,会把元素追加到链表上。
Redis的扩容方式:采用了渐进式rehash策略。扩容步骤为:

  • 全量Hash表(数组+链表) 中数组被填满时,开始扩容,扩容的新数组是原数组容量的2倍;
  • 此时会申请一个新的全量Hash表;在查询时,会同时查询新、旧两个表,Redis会将旧表中的数据迁移至新表中;
  • 迁移完成后,旧表数据结构会被删除。

10、如何降低Redis的内存使用情况?

控制key的长度

  • 可以尽可能的将key设置的短一些,以节省内存空间;若太长无法优化,可以使用Hash或者映射的方式,使用短字符串进行替换

避免存储bigKey

  • bigKey:指的是这个key的value很大。另外,客户端在写入bigKey时,易产生性能问题,解决方案:
    • String:控制在10kb以下;
    • List、Hash、Set、Zset:元素数量控制在10000以下。

尽可能都设置过期时间

  • 将Redis中的数据尽可能都设置过期时间,可以只保留Redis中经常访问的热数据,提升内存利用率。

实例设置maxmemory + 淘汰策略

  • 问题:如果过期时间设置的足够长,且业务应用写入量很大,短时间内Redis的内存依旧会快速增长。
  • 设置maxmemory:设置实例的内存使用上限;
  • 设置数据淘汰策略:以保证在内存无法写入新数据时的Redis内存淘汰策略。

11、如何使用Redis的性能更高?

master考虑关闭持久化

  • master关闭持久化,slaver开启RDB;对于重要服务,slaver需要开启RDB和AOF;

不使用复杂度过高的指令

  • Redis是单线程模型处理请求,在执行复杂度过高的指令时,会消耗更多的CPU资源;其他请求就只能等待,会发生阻塞;因此减少使用sort、sinter等聚合类命令;

执行复杂度O(n)命令时,关注n的大小

  • 在查询数据时,需要遵循以下原则:
    • 先查询数据元素的数量(LLEN/HLEN/SCARD/ZCARD)
    • 元素数量较少,可一次性查询全量;
    • 元素数量很多,则分批查询数据(LRANGE/HASCAN/SSCAN/ZSCAN)

批量命令代替单个命令

  • 当一次性需要操作多个key时,使用批量命令,降低网络IO开销:
    • String/Hash使用MGET/MSET替代GET/SET,HMSET/HMGET代替HSET/HGET;
    • 对于其他数据类型,可以使用Pipeline,一次性发送多个指令

key避免集中过期

  • 若存在大量key集中过期的情况,Redis清理过期key时,会出现阻塞主线程的情况;
  • 需要给key设置一个随机过期时间,把这些key的过期时间打散,降低集中过期对主线程的影响;

只是用db0

  • Redis会默认创建16个db。
  • Redis Cluster只支持db0,后期如果迁移,使用其他db的迁移成本高。

应用题

1、Redis获取海量数据的正确操作方式?

可以直接使用keys,简单暴力

  • 缺点:
    • 没有offset、limit参数,一次性突出所有key,一次返回字符串太大,很难处理;
    • 因为Redis是单线程模型,会顺序执行所有指令。因此,其他指令会等keys执行完之后再执行
    • keys是复杂度为O(n)的遍历算法,遍历千万级的key,会造成Redis服务卡顿

scan命令

  • 对比keys,他有优点:
    • scan命令的复杂度也是O(n),但是由于是分次执行,因此不会阻塞线程;
    • scan提供了limit参数,可以控制每次返回结果的最大条数。
  • 缺点:
    • scan返回的结果可能存在重复,需要客户端幂等。

2、如何解决Redis的并发竞争Key的问题?

背景

  • 许多客户端同时并发写一个key(多个客户端同时set一个key),如果本来应该先写的数据后写了,会导致数据版本错误。

解决方案
分布式锁

  • 分布式锁常见的三种实现方式:
    • 乐观锁;
    • 基于Redis的分布式锁;
    • 基于zookeeper的分布式锁。
  • 分布式锁的特性
    • 互斥性:在任何时刻,只有一个客户端能持有锁
    • 不能死锁:客户端在持有锁的期间崩溃,没有主动释放锁,也能保证其他客户端加锁;
    • 容错性:只要大部分的Redis节点正常运行,客户端就可以加锁和解锁。
  • 通过setnx实现简单分布式锁
    • 加锁
      • set key client_value NX PX 3000:setnx——代表只在key不存在时,才对key进行set操作;PX 3000——设置key的存活时间为3000ms;client_value——客户端传的唯一值,后期删除时作为比对使用。
      • 如果上述命令执行成功,则证明客户端获取到了锁。
    • 解锁
      • 解锁的过程就是把key删除,首先判断锁的value是否与client_value相同;相同,则可以删除。
  • 通过redisson实现复杂的分布式锁
    • redisson实现了可重入锁,步骤为:
      • 首先使用getLock(key)方法获取锁的实例(此时调用了RedissionLock构造方法,进行对象初始化);
      • 加锁:
        • 通过**tryAcquire()**方法尝试获取锁;若返回null,则证明没有锁,可以加锁;
        • 若不为null,则对比一下value,若value相同,则重入;value若不相同,则代表其他客户端还未释放订阅这个channel尝试循环获取锁;直到成功获取锁,则取消订阅;
      • 解锁:
        • 判断当前value是否与锁的value相同,相同就释放锁。

3、如何使用Redis做异步队列?

概述

  • 主要依靠list的数据结构模仿队列,实现队列右入左出(先进先出)的队列需求
  • 实现方法:
    • 使用rpush右侧加入,生产消息lpop左侧取出,消费消息
    • 需要创建一个线程做监听。使用blpop从左侧取出数据,因为blpop具有特点:可以在队列中没有数据时将连接阻塞,有数据时,再读取。
    • 若队列中长时间没有数据,也会造成redis连接断掉的情况。因此需要在断开连接的异常catch中重新建立连接

缺点

  • redis实现消息队列,我们消费的时候可能无法获取消息的ack,因此需要维护一个消息消费表来记录消费的情况。

4、如何使用Redis做延时队列?

概述

  • 主要依靠zset数据格式,因为zset是按照score进行排序的,主要借助score参数。
  • 实现方法(按照5s延迟为例):
    • 首先插入一条数据,将score设置为当前时间戳+5s。redisclient.zadd("key", System.currentTimeMillis() + 5000, JSON.toJSONString(value));然后根据5s的时间批量赋值;
    • 获取数据:zrangebyscore key min max withscores limit 0 1 可以查询最早的一条数据;zrangebyscore key min max withscores 可以查询min到max的成员,并按照分数从小到大排序。

5、使用Redis统计网站的UV,应该怎么做?

一般有2个方案

  • 用BitMap
    • BitMap存储用户的uid,计算UV的时候,需要做一下bitcount;
  • 使用HyperLogLog工具类
    • operations = redisTemplate.opsForHyperLogLog()
    • 获取时,operations.size(key)
  • 布隆过滤器
    • 每次访问的用户uid都放到布隆过滤器中。
    • 优点是省内存,缺点是无法得到精准的UV。很适合只需要UV大概量级的场景。

6、什么是热Key问题?如何解决?

热Key问题

  • 概念:突然有上百万的请求去访问redis上某个特定的key。会造成流量过于集中,带宽被打满,节点宕机。
  • 产生原因:
    • 用户消费的数据远大于生产的数据。如:秒杀、热点新闻等读多写少的场景;
    • 请求分片集中,超过但Redis服务器的性能。如:固定名称的key,hash存储在同一个节点,瞬间访问量极大,产生key热点问题。

如何解决

  • 首先需要识别到热点key
    • 凭经验判断哪些是热Key;
    • 客户端统计上报;
    • 服务代理层上报。
  • 如何解决
    • Redis集群扩容:增加分片副本,均衡读的流量;
    • 将热Key分散到不同的节点中;
    • 使用二级缓存,即JVM本地缓存,减少Redis的读请求。

7、RDB和AOF?

Redis持久化有三种方式

  • 快照方式(RDB):将某一个时刻的内存数据,以二进制方式写入磁盘;
  • 文件追加方式(AOF):记录所有的写操作命令,并以文本的形式追加到文件中;
  • 混合持久化方式:先把当前数据以RDB形式写入文件的开头;再将后续的操作命令以AOF格式存入文件。既保证了Redis重启速度,又避免数据丢失的风险

RDB

  • RDB有2中出发方式:手动触发、自动触发
    • 手动触发:有2种操作指令:save、bgsave
      • SAVE:阻塞式的完成持久化,其他client请求被阻塞;
      • BGSAVE(后台保存):会fork()一个子进程来执行持久化,其他client请求未被阻塞整个过程中只有在fork()时会产生阻塞
    • 自动触发:通过配置,当满足某一条件时,自动去进行BGSAVE命令。
      • Redis默认设置了3个保存点。
        在这里插入图片描述
  • 优点:
    • 在数据量较大的情况下,RDB的启动速度更快;
    • RDB文件内容更加简洁,只记录了某个时间点的Redis数据,适用于备份;
    • RDB的性能更好,在持久化时,会fork一个子进程用于持久化,主进程不会有相关的IO操作。
  • 缺点:
    • RDB 容易造成数据丢失。如1min保存一次快照,若Redis挂掉,两次快照之间的数据无法保存
    • RDB使用fork()产生子进程的过程会阻塞主进程。

AOF

  • AOF会将Redis执行的所有写操作指令记录下来,只追加文件,不做文件改写
  • Redis启动之初,会读取该文件重新构建数据库
  • AOF持久化流程
    在这里插入图片描述
    • Client作为命令来源,对Redis Server进行请求;
    • Redis server将命令先放入**AOF缓存(内存里)**中。目的是:当这些命令达到一定量时,再写入磁盘,避免频繁的磁盘IO操作。
    • AOF根据对应的策略,将命令写入磁盘上的AOF文件中;
    • AOF重写:即AOF的文件压缩:随着内容的增加,会根据规则进行合并;
    • 当Redis server重启时,会从AOF文件中载入数据。
  • 优点:
    • AOF的数据安全性更高;
    • AOF日志文件是一个追加的文件,如果服务器突然宕机,也不会出现日志定位或损坏的问题;
    • 当AOF文件太大时,Redis会在后台自动重写
  • 缺点:
    • 相同数据集下,AOF文件大小比RDB更大;
    • AOF开启后,写QPS会比RDB更低。

AOF缓冲区同步文件策略

  • Always策略:appendfsync always
    • 是在主线程中进行的,由于fsync的阻塞特性,会导致在此期间服务无法处理新的请求;但是可以保持内存和硬盘的数据一致性;
  • EverySec(默认)策略:appendfsync everysec
    • 是通过后台IO线程进行的。主线程并不会阻塞;但是内存和硬盘中的数据会有1s左右的差别;
  • No策略:appendfsync no
    • 将同步操作的控制权交由操作系统。主线程并不会阻塞,但内存和硬盘的数据一致性会很差。

AOF重写机制

  • 概念:AOF使用文件追加,文件会越来越大,重写机制是为了对AOF文件内容进行压缩,只保留可以恢复数据的最小指令集。 如:set key 1; set key 2; set key 3。压缩之后只存set key 3。
  • 优点:AOF重写不仅降低了文件的占用空间,同时更小的AOF也可以更快地被Redis加载
  • 触发机制
    • 手动:客户端向服务器发送bgrewriteaof命令;
    • 自动:通过配置,满足一定条件时,自动执行bgrewriteaof命令。默认条件时AOF文件大小是上次rewrite后大小的一倍且文件大于64MB
  • 重写原理
    • AOF文件持续增长而过大时,会fork出一个新线程来进行AOF重写,遍历内存中的数据,每条数据记录为一条set语句
    • 重写AOF文件,并没有读取旧AOF文件;二是会将整个内存中的数据库内容用set命令的方式重写了一个新的AOF文件。

线上环境的持久化

  • 官方建议:同时开启2种持久化策略。因为有时需要RDB快照是用来数据库备份、更快重启以及发生AOF引擎错误的解决方法。
  • 将RDB作为后备用途,只需要在slaver开启RDB;
  • 如果选择AOF,则应该尽量减少AOF rewrite。原因:rewrite带来持续IO;rewrite最后将新数据写到新文件的过程,造成了阻塞。可以将重写基础值大小改为2G。

8、缓存穿透、击穿、雪崩?

缓存穿透

  • 概念:指查询一个缓存和数据库都不存在的数据
  • 场景:秒杀活动——同一时刻会有大量的请求,都在秒杀同一件商品,此时缓存和数据库中都没有这条数据。数据库流量压力太大,直接挂掉。
  • 解决方案
    • 验证拦截:接口层进行校验,根据用户权限、性别等字段进行基础校验;
    • 布隆过滤器:可以将真实的商品id,添加到布隆过滤器中;每当再次进行查询时,先确认查询的id是否存在过滤器中;性能高、空间占用率小;
    • 缓存空对象:若查询数据库无数据,则将空对象加入缓存,设置一个过期时间,保护后端数据源。

缓存击穿

  • 概念:指缓存中没有,但数据库中有的数据,且某一个key非常热点,并发量极大。当key 缓存时间到期,持续大并发击穿缓存,直接请求数据库,导致压垮数据库。
  • 解决方案
    • 设置热点数据永不过期:设置热点数据在热点时段不过期,在访问低峰期过期;
    • 使用分布式锁:在key失效时,通过分布式锁对数据库搜索上锁。会导致吞吐量下降。

缓存雪崩

  • 概念:指在某一时间段内,缓存集中失效。会导致流量直接请求数据库,引起数据库压力过大甚至直接宕机。是缓存击穿的加长版。
  • 缓存雪崩的原因
    • Redis服务器挂掉了:Redis集群发生大面积故障,导致缓存失败;
    • 对缓存数据设置了相同的过期时间,导致某个时间段内缓存集中失效。
  • 解决方案
    • 实现Redis的高可用
      • 事前:搭建Redis哨兵或Redis集群
      • 事中:缓存降级——使用Hystrix,通过熔断、降级、限流等手段来降低雪崩发生后的损失;
      • 事后:Redis备份和快速缓存预热。
    • 缓存数据的过期时间设置随机,防止同一时间大量数据过期现象发生。
    • 设置热点数据永不过期。

4、Epoll和poll模型?

5、redis哨兵机制(sentinel)?

Sentinel作用

  • Master状态监测;
  • 如果Master异常,则会进行Master-Slave切换。将其中的一个Slave切换为Master,将之前的Master切换为Slave;
  • Master-Slave切换后,master_redis.conf、slave_redis.conf和sentinel.conf的内容都会发生改变。Sentinel的监控目标也切换为新Master。

Sentinel工作方式

  • 每个Sentinel以每秒一次的频率向它所知的Master、Slave以及其他的Sentinel 节点发送一个PING命令;
  • 如果一个节点距离最后一次有效回复PING命令时间超过 own-after-millionseconds 指定的值,则此节点会被Sentinel标记为主观下线
  • 如果一个Master节点被标记主观下线,则正在检测此Master节点的Sentinel要以每秒一次的频率确认Master的确进入主观下线状态;
  • 当有足够多数量的Sentinel(不小于配置文件中的值)在指定的时间范围内确认Master进入主观下线状态,则Master会被标记为客观下线
  • 一般情况下,Sentinel会以每10s一次的频率向它已知的Master、Slave发送INFO命令(发现Slave节点;确认主从关系);
  • 当Master被Sentinel标记为客观下线后,Sentinel向下线Master的所有Slave发送INFO命令的频率会从10s一次改为1s一次
  • 若没有足够数量的Sentinel同意Master已经下线,Master的客观下线状态会被移除。若Master重新向Sentinel发送PING命令有效回复,Master的主观下线状态会被移除。

6、介绍一下redis分片集群?

8、机器16G内存,redis占了10G,redis能否完成rdb?

9、缓存失效时,如何防止瞬间大量请求进入DB?

  大数据 最新文章
实现Kafka至少消费一次
亚马逊云科技:还在苦于ETL?Zero ETL的时代
初探MapReduce
【SpringBoot框架篇】32.基于注解+redis实现
Elasticsearch:如何减少 Elasticsearch 集
Go redis操作
Redis面试题
专题五 Redis高并发场景
基于GBase8s和Calcite的多数据源查询
Redis——底层数据结构原理
上一篇文章      下一篇文章      查看所有文章
加:2022-03-22 20:40:57  更:2022-03-22 20:41:32 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 6:15:44-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码