您好,我是南橘,万法仙门的掌门,刚刚从九州世界穿越到地球,因为时空乱流的影响导致我的法力全失,现在不得不通过这个平台向广大修真天才们借去力量。你们的每一个点赞,每一个关注都是让我回到九州世界的助力,兄弟萌来为我注入修为吧!关注WX号:南橘ryc

等我回去以后,大家都是万法仙门的长老,我会给大家数不尽的天材地宝,人人如龙,全民飞升。

作为一个仙侠世界的宗门,当然会存在宗门大比这种事情。

而作为我们的主角,李小庚自然也会在其中大放光彩。

万法仙门,宗门三号擂台,筑基组淘汰赛。

“承让!”

轻轻挥了挥衣袖,我们的主角李小庚朝已经飞出擂台的对手点了点头。

“三号擂台比试结束,胜者,云霄殿,李小庚。”裁判面无表情地给李小庚发了一个牌子。

“这人也太赖了吧!”

“草(我爱你)一上台就用法器,完全不给我们这些普通弟子活路啊!”

“云霄殿都是一群狗大户,结丹期的擂台上,云霄殿的二弟子带着炼器宗的oracle大杀四方,没想到这边又是一样的剧情。”

李小庚听到这些议论,嘴角露出一丝无奈的笑容,使用绝技发胶手轻轻整了整发型,望向议论纷纷的观众说道:“谢谢大家的支持,我会继续努力的!”

“不过他好帅啊,我原谅他了。”

“是啊,看到他的脸,这样一想不尊重公平竞技其实也没啥事吧?”

“草只是一种植物而已。”


回到一周前。

云霄殿中,李小庚一如既往的在给云小霄献殷勤。

“师父,下周就是宗门大比了。您天天在万法研究院里搞研究,肯定很累吧,小徒弟来给您松松肩膀。”

云小霄看着满脸谄媚的李小庚,轻哼了一下:“放心,人人都有份,给你Redis行不行?”

“Redis?炼器宗出品,号称能解决大部分分布式问题的神器?”

“没错,如果你想要,那我就要考验考验你。你知道Redis的五种基础数据结构是什么吗?”

“简单,师父,且听我娓娓道来。”

一、Redis基础知识

1、1 String 字符串类型

redis中最基本的数据类型,一个key对应一个value

适用情况:

1、缓存: 经典使用场景,把常用信息,字符串,图片或者视频等信息放到redis中,redis作为缓存层,mysql做持久化层,降低mysql的读写压力。2.计数器:redis是单线程模型,一个命令执行完才会执行下一个,同时数据可以一步落地到其他的数据源。3.session:通过redis实现session共享
复制代码

1、2 Hash (哈希)

对于Java中的HashMap,本身是一种KV对结构,如 value={{field1,value1},…fieldN,valueN}},非常好理解

适用情况:

HashMap作为缓存,相比于string更节省空间的维护缓存信息,适合存储如用户信息,视频信息等
复制代码

底层用字典dict实现

1、3 List (链表)

Redis 的链表相当于 Java 语言里面的 LinkedList

适用情况:

1、List在Redis中既可以做队列也可以做栈使用,它的插入和删除操作非常快,时间复杂度为 0(1),但是索引定位很慢,时间 复杂度为 O(n)。2、可以作为微博的时间轴,有人发布微博,用lpush加入时间轴,展示新的列表信息。     3、可以实现阻塞队列,左进右出的队列组完成设计
复制代码

list底层使用quickList(快速链表)实现

在早期的设计中, 当列表对象中元素的长度比较小或者数量比较少的时候,采用ziplist来存储,当列表对象中元素的长度比较大或者数量比较多的时候,则会转而使用双向列表linkedlist来存储。

这两种存储方式都各有优缺点

  • 双向链表linkedlist便于在表的两端进行push和pop操作,在插入节点上复杂度很低,但是它的内存开销比较大。首先,它在每个节点上除了要保存数据之外,还要额外保存两个指针;其次,双向链表的各个节点是单独的内存块,地址不连续,节点多了容易产生内存碎片。
  • ziplist存储在一段连续的内存上,所以存储效率很高。但是,它不利于修改操作,插入和删除操作需要频繁的申请和释放内存。特别是当ziplist长度很长的时候,一次realloc可能会导致大批量的数据拷贝。

3.2版本更新之后,list的底层实现变成了quickList

quickList是 zipList 和 linkedList 的混合体,它将 linkedList 按段切分,每一段使用 zipList 来紧凑存储,多个 zipList 之间使用双向指针串接起来。

1、4 Set 集合

Redis 的集合相当于 Java 语言里面的 HashSet ,它内部的键值对是无序的、唯一 的。

它的内部实现相当于一个特殊的字典,字典中所有的 value 都是一个值 NULL 当集合中最后一个元素被移除之后,数据结构被自动删除,内存被回收。
复制代码

适用情况:

1、标签(tag),给用户添加标签,或者用户给消息添加标签,这样有同一标签或者类似标签的可以给推荐关注的事或者关注的人。2、点赞,或点踩,收藏等,可以放到set中实现3、可以用来存储在某活动中中奖的用户 ID ,因为有去重功能,可以保证同 一个用户不会中奖两次。
复制代码

1、5 Zset 有序集合

它类似于 Java SortedSet HashMap 的结合体, 方面它是个 set ,保证 了内部 value 的唯性,另方面它可 以给每个 value 赋予一个 score ,代表 这个 value 的排序权重。它的内部实现 用的是一种叫作“跳跃表”的数据 结构。

从这张图片,我们可以看出来:跳跃表的底层是一个顺序链表,每隔一个节点有一个上层的指针指向下一个节点,并层层向上递归。这样设计成类似树形的结构,可以使得对于链表的查找可以到达二分查找的时间复杂度。

skiplist他不要求上下两层链表之间个数的严格对应关系,他为每个节点随机出一个层数。比如上图第三个节点的随机出的层数是4,那么就把它插入到四层的空间上,而第四个节点随机出的层数是1,那它就只存在第一层空间上。

  • 当数据较少的时候,zset是由一个ziplist来实现的,就和list底层之前是一样的

ziplist是由一系列特殊编码的连续内存块组成的顺序存储结构,类似于数组,ziplist在内存中是连续存储的,但是不同于数组,为了节省内存 ziplist的每个元素所占的内存大小可以不同。 ziplist将一些必要的偏移量信息记录在了每一个节点里,使之能跳到上一个节点或下一个节点。

  • 当数据较多的时候,zset是一个由dict 和一个 skiplist来实现的,dict用来查询数据到分数的对应关系,而skiplist用来根据分数查询数据

除了这五大基础数据结构,Redis还有更加专业的数据结构 HyperLogLog(基数统计的算法)、Geo(地理位置系列)、Pub\Sub(消息队列)、Pipeline(管道)、BloomFiler(布隆过滤器),都在不同的地方有用到,有些我会在下文向大家介绍。

1、6 Pipeline

可以将多次IO往返时间缩减为一次,前提是pipleline执行的指令之间没有因果关系

管道(pipeline)可以一次性发送多条命令并在执行完后一次性将结果返回,pipeline 通过减少客户端与redis的通信次数来实现降低往返延时时间,而且Pipeline 实现的原理是队列,而队列的原理是时先进先出,这样就保证数据的顺序性。

注意:pipeline机制可以优化吞吐量,但无法提供原子性/事务保障

“哎哟,不错哦,还能举一反三,是不是一早就打起Redis的主意了?”云小霄玩味的盯着李小庚的眼睛.

不过李小庚是何许人物?举世誉之而不加劝,举世非之而不加沮,脸色毫无任何变化:“哪能啊师父,你也知道我除了修炼就是去图书馆了,关于redis的书籍这段时间也是小有涉猎,不信您再考考我?”

“长本事了嘛小庚同学!”云小霄来了兴趣。

当年收李小庚入门的时候,百分之五十(其实是百分之百)是看脸,剩下百分之五十的考量也是他的基础非常扎实,完全不像普通的炼气期。李小庚本人也十分争气,入门半年便突破了筑基期,并且不急不躁,一步一个脚印的践行着万法仙门三年筑基的规划。学习今法,虽然快速的掌握各种先进技能能很快的突破,但是若是没有坚实的基础,那么未来的道路肯定会遇到各种各样的问题。

“那么我来考考你,Redis如何实现分布式锁?”

“我有一言,请诸位静听。”

二、集群与分布式锁

2、1 Redis实现分布式锁

随着互联网技术的飞速发展,越来越多的单体架构已经转型成了分布式架构,,分布式架构确实能带来性能和效率上的提升,但是也会带来数据一致性的问题。

分布式锁,就是解决分布式架构中数据一致性的专用武器,分布式锁需要满足一下三个方面方可放心使用:

  • 排他性:在同一时间只会有一个客户端能获取到锁,其它客户端无法同时获取

  • 避免死锁:这把锁在一段有限的时间之后,一定会被释放(正常释放或异常释放)

  • 高可用:获取或释放锁的机制必须高可用且性能佳

目前,我所知道的分布式锁大概有三种主流方式实现,分别是zookpeer,redis,还有本地数据库,今天我就介绍一下如何用redis实现分布式锁。

基于Redis实现的锁机制,主要是依赖redis自身的原子操作

setnx争抢锁,再用expire添加过期时间

没有看错,就是这么简单,如果害怕不妥,比如争抢锁的时候还没有设置过期时间就突然宕机之类的问题,可以直接用jedis等封装好的RedisTemplate把setnx和expire合成一条指令使用。

“但是这样的分布式锁真的安全吗?如果法器服务器宕机怎么办?”

“当然,这样的单体redis所使用的分布式锁的安全性并不高。”李小庚仿佛知道云小霄会这样问,嘴角不经意泛起一抹微笑。

首先,单点故障的问题不可避免

其次,因为使用锁的客户端,和redis服务器,不在一起啊!时间是有延迟的,我们只能依靠redis的TTL命令来查询锁的剩余时间,然后根据这个剩余时间来判断锁是否超时。
然而在通常的计算机系统中,很难获取到一个可靠的时间。

  • 系统可能由于时间服务器同步调整时间,
  • 虚拟机可能调整时间,
  • JVM GC可能导致时间停顿
    RedLock的出现在一定程度上解决了这个问题,它的执行流程如下:
  1. 客户端获取当前时间,生成一个随机值作为锁的值(目的是更加精确的获得时间)
  2. 依次尝试在所有5个redis上取得同一个锁(使用类似单机redis锁的方法, 使用同样的key和同一个随机值)
    获取锁的操作本身需要设定一个比较小的超时时间(如5-50ms), 防止在一个挂掉的redis上浪费太多时间
    如果一个redis不可用,要尽快开始尝试下一个
  3. 客户端计算获取锁一共用了多长时间,通过用当前时间减去第1步得到的时间
    如果客户端获取了多数redis上的这个锁(3到五个5),并且这时还没有超过锁的超时时间,
    这个锁就算是获取成功了
  4. 如果锁获取成功了,有效时间就按锁超时时间-获取锁花费时间算
  5. 如果失败,尝试在所有redis上解除锁
    (解除锁的操作是一段lua script,删除一个key如果key的value是第1步生成的随机值)

当然,它也不能解决问题,但是, redis锁只会在比较极端的情况下出错,如果不是需要特别精确,只需要保证绝大多数可靠的时候,可以放心使用redis集群或者redlock。

“你说你使用RedLock工具,那么我直接击毁你的redis单体怎么办?你还如何保持分布式锁的健壮性?而且我们的万法玄天阵也是用到了分布式锁来确保出入弟子的身份ID不被盗用,按你的方式来使用,如果结果不够精确,那对于其他门派来说咱的阵法就和筛子没有区别了。”云小霄挥手从殿内的盆栽上弄来了几个小橘子,望向了第三面墙外的各位,好像在提示大家可以喝口水动一动了。

“那么,就要提到Redis集群了。”李小庚推了推眼镜。

2、2Redis集群

集群同步机制

Redis中有主从机制,一个主节点对应一个或多个从节点,主节点提供数据存取,从节点则是从主节点拉取数据备份,当这个主节点挂掉后,就会有这个从节点选取一个来充当主节点,从而保证集群不会挂掉。先讲一下Redis主从同步的流程:

  • 1.第一次同步时,从服务器向主服务器发送一次SYNC命令,主服务器收到之后做一次bgsave、并同时将后续修改操作记录到内存buffer,待完成后将RDB文件全量同步到复制节点
  • 2.复制节点接收完成后将RDB镜像加载到内存中,加载完成后,再通知主节点
  • 3.后续的增量数据通过AOF日志同步即可,有点类似数据库的binlog

同时,在2.8版本之后,Redis可以自动判断是需要全量同步还是增量同步,效率比较高,增量同步其实就是在完成全量同步后,开始新复制时向主服务器发送PSYNC( )命令(runid是上次复制的主服务器id,offset是从服务器的复制偏移量),主服务器会根据这个两个参数来决定做哪种同步,判断服务器id是否和本机相同,复制偏移量是否在缓冲区中。

高可用性:

  • Redis Sentinal(哨兵模式)集群着眼于高可用,在master宕机时自动将slave提升为master,继续提供服务
  • Redis Cluster集群着眼于扩展性,在单个redis内存不足时,使用Cluster进行分片存储

“原来是在这里等着我呢。李小庚,如果我给你一套redis集群,你如何去实现你所设想的方案呢?”云小霄笑出了声,本来只想给一个单体redis法器,再凭借李小庚自己的扎实的基础,就有希望在筑基期大比上夺魁的,没想到他的目标一直都是redis集群。

“不急不急,我从书中看到了三套实现redis集群的方案,还请师父帮忙演示一二。”李小庚也知道云小霄知道了自己的目的,纵使脸皮再厚也开始微微泛红,配上一双剑眉下一对细长的桃花眼,云小霄的口水不争气的流了下来。

云小霄伸了伸懒腰,然后单手指天:“剑来!”。

无数红白相间细小飞剑从房间的各个角落出现并环绕在她的身边,这边是李小庚一直心心念念的redis集群了。

“接下来集群的指挥权交给你,看你表演咯~”

李小庚学有样学样:“今日我李小庚便要重回陆地神仙之境。”

三、Redis集群的实现

3、1传统的主从模式

大概是所有的集群都有主从模式

主从模式的一个作用是备份数据,这样当一个节点损坏(指不可恢复的硬件损坏)时,数据因为有备份,可以方便恢复。
另一个作用是负载均衡,所有客户端都访问一个节点肯定会影响Redis工作效率,有了主从以后,查询操作就可以通过查询从节点来完成。

在主从模式中,一个Master可以有多个Slaves,默认配置下,master节点可以进行读和写,slave节点只能进行读操作,无法进行写操作

如果修改默认配置,可以让slave进行写,但是这毫无意义,因为写入的数据不会同步给其他slave,同时,master节点如果修改了,slave上的数据会马上被覆盖

slave节点挂了不影响其他slave节点的读和master节点的读和写,重新启动后会将数据从master节点同步过来。master节点挂了以后,不影响slave节点的读,Redis将不再提供写服务,master节点启动后Redis将重新对外提供写服务

所以,我们可以发现Redis的主从和Zookeeper的主从完全不一样!它竟然不会选举!

这个缺点影响是很大的,尤其是对生产环境来说,是一刻都不能停止服务的,所以一般的生产坏境是不会单单只有主从模式的。所以有了下面的sentinel模式。

3、2sentinel模式(哨兵模式)

哨兵模式要搭配主从模式来使用,主从不能自己选举,那我们就加一个哨兵,当sentinel发现master节点挂了以后,sentinel就会从slave中重新选举一个master。

哨兵的作用就是监控Redis系统的运行状况。它的功能包括以下两个。

(1)监控主服务器和从服务器是否正常运行。
(2)主服务器出现故障时自动将从服务器转换为主服务器。

这不就皆大欢喜了吗?

哨兵的工作方式:

  • 1、每个Sentinel(哨兵)进程以每秒钟一次的频率向整个集群中的Master主服务器,Slave从服务器以及其他Sentinel(哨兵)进程发送一个 PING 命令。
  • 2、如果一个实例(instance)距离最后一次有效回复 PING 命令的时间超过 down-after-milliseconds 选项所指定的值, 则这个实例会被 Sentinel(哨兵)进程标记为主观下线(SDOWN)
  • 3、如果一个Master主服务器被标记为主观下线(SDOWN),则正在监视这个Master主服务器的所有 Sentinel(哨兵)进程要以每秒一次的频率确认Master主服务器的确进入了主观下线状态
    当有足够数量的 Sentinel(哨兵)进程(大于等于配置文件指定的值)在指定的时间范围内确认Master主服务器进入了主观下线状态(SDOWN), 则Master主服务器会被标记为客观下线(ODOWN)
  • 4、在一般情况下, 每个 Sentinel(哨兵)进程会以每 10 秒一次的频率向集群中的所有Master主服务器、Slave从服务器发送 INFO 命令。
    当Master主服务器被 Sentinel(哨兵)进程标记为客观下线(ODOWN)时,Sentinel(哨兵)进程向下线的 Master主服务器的所有 Slave从服务器发送 INFO 命令的频率会从 10 秒一次改为每秒一次。
  • 5、若没有足够数量的 Sentinel(哨兵)进程同意 Master主服务器下线, Master主服务器的客观下线状态就会被移除。若 Master主服务器重新向 Sentinel(哨兵)进程发送 PING 命令返回有效回复,Master主服务器的主观下线状态就会被移除。

sentinel模式基本可以满足一般生产的需求,具备高可用性。但是当数据量过大到一台服务器存放不下的情况时,主从模式或sentinel模式就不能满足需求了,这个时候需要对存储的数据进行分片,将数据存储到多个Redis实例中,这就是cluster模式。

3、3cluster模式

cluster的出现是为了解决单机Redis容量有限的问题,将Redis的数据根据一定的规则分配到多台机器。

Redis-Cluster采用无中心结构,它的特点如下:

  • 所有的redis节点彼此互联(PING-PONG机制),内部使用二进制协议优化传输速度和带宽。

  • 节点的失效是通过集群中超过半数的节点检测失效时才生效。

  • 客户端与redis节点直连,不需要中间代理层.客户端不需要连接集群所有节点,连接集群中任何一个可用节点即可。

cluster可以说是sentinel和主从模式的结合体,通过cluster可以实现主从和master重选功能,所以如果配置三个副本三个分片的话,就需九六个Redis实例。
因为Redis的数据是根据一定规则分配到cluster的不同机器的,当数据量过大时,可以新增机器进行扩容,这种模式适合数据量巨大的缓存要求,当数据量不是很大使用sentinel即可。

引用一张大佬的图片来直观展现一下什么是 Redis-Cluster

每个请求访问Redis-Cluster集群的时候,都会进行一个路由,路由可以通过Hash(也可以用别的)来进行随机分片,但是如果完全hash的话很可能导致分片们旱的旱死,涝的涝死。,所以,提出了**一致性哈希(自动缓存迁移)+虚拟节点(自动负载均衡)**的方法来解决问题

一致性哈希的原理 :将所有master node落在一个圆环上面,然后,有一个key过来之后。同样就是hash值,然后会用hash值在圆环对应的各个点上(每个点都有一个hash值)去对比,看hash值落在那个位置,落在圆环上面以后,就会顺时针旋转去寻找距离自己最近的一个节点,数据的存储于读取都在该节点进行。

一致性哈希的优势 :保证了任何一个master宕机,只会影响之前在那个master上面的数据,因为照着顺时针走,全部在之前的master上面找不到了,master也宕机了,就会继续顺着顺时针走到下一个master节点去。这样就只会有一部分数据丢失。

在李小庚的指挥下,reids集群也慢慢的变成了他的模样,一会儿在空中变成*,一会儿变成*,好不快乐。

“不要急,小庚,除此之外,关于redis还有一些其他的东西你需要掌握。”

四、Redis进阶知识

4、1异步队列

Redis的本职工作是缓存,但是由于它多才多艺,成为队列也不错,有一些阻塞式的API让其有能力做消息队列;另外,做消息队列的其他特性例如FIFO(先入先出)也很容易实现,只需要一个List对象从头取数据,从尾部塞数据即可

  • 在Redis中,如果让List结构作为队列、rpush生产消息、lpop消费消息、当lpop没有消息的时候,可以当sleep一会再重试,这就相当于生产者消费模式模式了。同时List有个指令叫blpop,在没有消息的时候,它会阻塞住直到消息到来。
  • pub\sub主题订阅者模式、可以实现1对N的消息队列,实现生产一次,消费多次。但是,它也有不足之处,如果让pub\sub主题订阅者模式、消费者下线的情况下,消息会丢失、不如直接用MQ

4、2延时队列

在Redis中,可以利用 sorted-set 来做延时队列

zadd key score1 value1 score2 value2

  • socre为执行时间,key为队列名,value为数据
  • 消费队列循环从sorted-set根据score获取(zrangebyscore)小于等于当前时间的且score最小的一条数据轮询处理
  • 如果没有取到数据,睡一会再去获取

但是,Redis的延时队列无法返回ACK,所以需要自己实现

4、3 持久化

Redis有两种持久化的方式,分别是RDB和AOF

RDB做镜像全量持久化、AOF做增量持久化,因为RDB会耗费较长时间,不够实时,在停机的时候会导致大量有效数据丢失,所以需要AOF来配合使用,在redis实例重启时,会使用RDB持久化文件重新构建内存,再使用AOF重放近期的操作指令来实现完整恢复重启之前的状态。

RDB机制

RDB持久化是指在指定的时间间隔内将内存中的数据集快照写入磁盘。也是默认的持久化方式,这种方式是就是将内存中数据以快照的方式写入到二进制文件中,默认的文件名为dump.rdb。RDB提供了三种机制来触发持久化

  • 1、save触发方式—客户端发起save请求

    执行save命令期间,Redis不能处理其他命令,直到RDB过程完成为止

  • 2、bgsave触发方式–客户端发起bgsave请求

    执行该命令时,Redis会在后台异步进行快照操作,快照同时还可以响应客户端请求

  • 3、自动触发

    自动触发是由我们的配置文件来完成的,在redis.conf文件中配置,大家可以去了解一下,这里就不写那么多东西了

AOF机制

全量备份总是耗时的(随机的传说总是好的???),有时候我们提供一种更加高效的方式AOF,Redis会将每一个收到的写命令都通过write函数追加到文件中,就是日志记录。

和RDB一样,AOF也有三种同步机制:

  • 1、always:同步持久化 每次发生数据变更会被立即记录到磁盘 性能较差但数据完整性比较好
  • 2、everysec:每秒同步,异步操作,每秒记录 如果一秒内宕机,有数据丢失
  • 3、no:从不同步

Redis本身的机制是AOF持久化开启存在AOF文件时,优先加载AOF文件。AOF文件不存在时候,加载RDB文件。加载AOF\RDB文件后,Redis启动成功。AOF\RDB文件存在错误时,Redis启动失败并打印错误信息。

不要问AOF和RDB用哪个,我的经验就是,全都用。 RDB同步快,但是要损失最多五分钟的内容,AOF同步慢,但是每秒同步的情况下最多损失1s的内容,损失的内容也可以通过日志去找回。

解决机器断电对数据丢失的影响

AOF日志中可以进行sync属性的配置,如果不要求性能,在每条写指令时都sync一下磁盘,就不会丢失数据,但在高性能要求下每次都sync是不现实的,一般都使用定时sync,比如1s一次,这个时候就最多丢失1s的数据。

【JAVA今法修真】 第三章 关系非关系 redis法器相关推荐

  1. 【JAVA今法修真】 第二章 一气化三清 线程分心念

    这是我的微信公众号,希望有兴趣的朋友能够一起交流,也希望能够多多支持新人作者,你的每一份关注都是我写文章的动力:南橘ryc 天有八纪,地分九州,万法仙门与天道剑宗一并坐落在东北方通辽州. 与李小庚想象 ...

  2. 小强怎样练成——读《现代软件工程——构建之法》第三章有感

    小强怎样练成 ----读<现代软件工程--构建之法>第三章有感 一.知道自己吃几碗干饭 先秦时期的"革命家"告诉我们"知人者智,自知者明",&quo ...

  3. java虚拟机读书笔记 第三章 垃圾收集器和内存分配策略

    java虚拟机读书笔记 第三章 垃圾收集器和内存分配策略 GC需要完成的三件事情:哪些内存需要回收.什么时候回收.如何回收 垃圾回收器在对堆进行回收前,首先要确定那些对象存活,哪些对象已经死去,判断的 ...

  4. 离散数学第三章 集合与关系

    第三章 集合与关系 3-1 集合的概念和表示法 说明集合的方法有两种: 列举法(eg.A={a,b,c,d}) 叙述法(eg.S₁={x|x是中国的省}) 我们用p(x)表示任何谓词,则{x|p(x) ...

  5. 离散数学第三章 集合与关系(1~7)

    第三章 集合与关系(1~7) 3-1 集合的概念和表示法 说明集合的方法有两种: 列举法(eg.A={a,b,c,d}) 叙述法(eg.S₁={x|x是中国的省}) 我们用p(x)表示任何谓词,则{x ...

  6. 【离散数学】集合论 第三章 集合与关系(3) 集合计数的加法原理、容斥原理

    本文属于「离散数学」系列文章之一.这一系列着重于离散数学的学习和应用.由于内容随时可能发生更新变动,欢迎关注和收藏离散数学系列文章汇总目录一文以作备忘.此外,在本系列学习文章中,为了透彻理解数学知识, ...

  7. 【JAVA今法修真】 第五章 练气百日,筑基三年

    您好,我是南橘,万法仙门的掌门,刚刚从九州世界穿越到地球,因为时空乱流的影响导致我的法力全失,现在不得不通过这个平台向广大修真天才们借去力量.你们的每一个点赞,每一个关注都是让我回到九州世界的助力,兄 ...

  8. java程序语言设计第三章答案_java语言程序设计课后习题解答张思民第三章

    java语言程序设计课后习题解答张思民第三章 1 第3章 面向对象程序设计基础 [1]什么是 Java 程序使用的类?什么是类库? [解答]:Java 程序的基本单位是类.对象是对事物的抽象,而类是对 ...

  9. JAVA实现数据库编程第三章_[数据库]使用Java实现数据库编程—03 第三章 高级查询(一)...

    [数据库]使用Java实现数据库编程-03 第三章 高级查询(一) 0 2018-07-21 03:01:10 1.修改表:(1)修改表名语法: ALTER TABLE RENAME [ TO ] : ...

最新文章

  1. debian10 简单的CA使用
  2. 8、Python与设计模式--门面模式
  3. (转)如何在一台电脑上开启多个tomcat 和配置让系统识别哪个具体的tomcat
  4. Sitemesh排除Exclude不装饰特定页面的解决办法
  5. C# winform WebBrowser怎么获取js中的变量的值?怎么触发js的事件?
  6. php interbase,PHP: Firebird/InterBase - Manual
  7. 单片机C语言中空语句,单片机C语言中的空语句.doc
  8. mysql 过滤相同数据库_MySQL数据库查询中的重复记录过滤
  9. vbs获取程序窗体句柄_PyQt5 GUI程序的基本框架
  10. ArrayList的使用方法【转载】
  11. 感觉又学到了不少,在这里写下来,但也有一个问题,不知道是为甚吗?
  12. 二分- Count on Canton
  13. 带你深入理解Java的IO到底是个啥
  14. apache+php+mysq环境详细l配置
  15. spring使用之旅(一) ---- bean的装配
  16. 基于WinForm的多语言开发之界面加载
  17. android zxing 自动对焦,Zxing中的camera
  18. 【优化算法】帝国主义竞争优化算法(ICA)【含Matlab源码 1635期】
  19. DB2完整的SQLCODE和SQLState错误信息
  20. 电脑微信双开 bat文件

热门文章

  1. 1.gstreamer USB摄像头保存至图片及视频
  2. 虚拟现实,带你走进一个不一样的科学探索世界
  3. C语言 宏定义练习:计算平方
  4. Latex中文字体问题
  5. android图片格式
  6. Android自定义控件开发系列(一)——第一次动手做自定义控件
  7. 百度搜索引擎优化指南2.0
  8. 计算机网络两台主机互相通信过程概览
  9. 完了!我写的 bug 要保留到一万年以后鞭尸
  10. 西南大学校园网客户端共享网络之路由器开wifi