摘要: 1:推荐系统简易架构图 2:推荐引擎流程图 Mixer系统的用户推荐就是按照上面流程实现,接下来分别介绍各个功能 3:索引内容 1:索引目的是提供高效查询 索引内容就是将内容生产索引文件,目的是提高查询速度,不可能每个请求过来都把所有的数据查出来,然后过滤、计算特征、排序、最后将排在前面的数据推给用 阅读全文
posted @ 2024-02-02 10:35 啊汉 阅读(346) 评论(0) 推荐(1) 编辑
摘要: 本篇文章为你解答以下问题: 0:redis单线程的实现流程是怎样的? 1:redis哪些地方用到了多线程,哪些地方是单线程? 2:redis多线程是怎么实现的? 3:redis多线程是怎么做到无锁的? 0:redis单线程的实现流程是怎样的? Redis一开始是单线程模型,在一个线程中要同时处理两种 阅读全文
posted @ 2020-11-25 19:23 啊汉 阅读(5374) 评论(0) 推荐(3) 编辑
摘要: 代码库地址:https://github.com/garyburd/redigo 1:连接池 2:发送命令 3:解析结果 1:连接池 连接池结构体如下: type Pool struct { // Dial is an application supplied function for creati 阅读全文
posted @ 2020-10-28 11:47 啊汉 阅读(819) 评论(0) 推荐(0) 编辑
摘要: 一:需要选主的场景 1:服务有多台机器,取其中一台去执行任务。多台机器同时执行会出问题,如将数据库中状态为失败的记录取出来重新执行,如果多台机器同时执行,会导致一个失败的任务被多台机器同时执行。 2:服务有多台机器,选其中一台作为主,主负责任务的分发,大家一起消费并处理任务。还是将数据库中状态为失败 阅读全文
posted @ 2020-09-09 10:31 啊汉 阅读(1219) 评论(0) 推荐(0) 编辑
摘要: 1:io多路复用epoll io多路复用简单来说就是一个线程处理多个网络请求。 我们知道epoll in 的事件触发是可读了,这个比较好理解,比如一个连接过来,或者一个数据发送过来了,那么in事件就触发了,那么out事件是如何触发的呢?缓冲区可写(有空的区域),就可以触发,epoll有两种模式LT( 阅读全文
posted @ 2020-09-08 10:53 啊汉 阅读(2147) 评论(0) 推荐(3) 编辑
摘要: golang本身对常用集合的封装还是比较少的,主要有数组(切片)、双向链表、堆等。在工作中可能用到其他常用的集合,于是我自己对常用的集合进行了封装,并对原理做了简单介绍,代码库地址:https://github.com/chentaihan/container,代码都是经过测试的,欢迎下载使用,反馈 阅读全文
posted @ 2020-04-20 14:43 啊汉 阅读(1299) 评论(0) 推荐(0) 编辑
摘要: nsq的源码比较简单,值得一读,特别是golang开发人员,下面重点介绍nsqd,nsqd是nsq的核心,其他的都是辅助工具,看完这篇文章希望你能对消息队列的原理和实现有一定的了解。 nsqd是一个守护进程,负责接收,排队,投递消息给客户端,并不保证消息的严格顺序,nsqd默认监听一个tcp端口 ( 阅读全文
posted @ 2019-09-02 10:23 啊汉 阅读(3353) 评论(0) 推荐(1) 编辑
摘要: map结构 整体为一个数组,数组每个元素可以理解成一个槽,槽是一个链表结构,槽的每个节点可存8个元素,搞清楚了map的结构,想想对应的增删改查操作也不是那么难 1:槽大小计算&hash算法 我们可以简单的理解成:槽大小为1<<N,每个元素计算出一个hash值hashCode,hash到这些槽中,ha 阅读全文
posted @ 2019-02-20 20:16 啊汉 阅读(1417) 评论(0) 推荐(1) 编辑
摘要: 一:原子操作CAS(compare-and-swap) 原子操作分三步:读取addr的值,和old进行比较,如果相等,则将new赋值给*addr,他能保证这三步一起执行完成,叫原子操作也就是说它不能再分了,当有一个CPU在访问这块内容addr时,其他CPU就不能访问 func CompareAndS 阅读全文
posted @ 2019-01-17 10:49 啊汉 阅读(3407) 评论(0) 推荐(0) 编辑
摘要: 1.channel数据结构 type hchan struct { qcount uint // 缓冲区中已有元素个数 dataqsiz uint //循环队列容量大小 buf unsafe.Pointer // 缓冲区指针 elemsize uint16 //元素大小 closed uint32 阅读全文
posted @ 2019-01-16 09:31 啊汉 阅读(2653) 评论(0) 推荐(0) 编辑
摘要: go并发调度模型如上图 M指的是Machine,一个M直接关联了一个线程。 P指的是Processor,代表了M所需的上下文环境,也是处理用户级代码逻辑的处理器。 G指的是Goroutine,其实本质上也是一种轻量级的线程。 ⾸先是 Processor(简称 P),其作⽤类似 CPU 核,⽤来控制可 阅读全文
posted @ 2019-01-15 20:41 啊汉 阅读(3185) 评论(0) 推荐(1) 编辑
摘要: 我为什么吃撑了要实现go的aes-cbc-256加密解密功能? 之前的项目是用php实现的,现在准备用go重构,需要用到这个功能,这么常用的功能上网一搜一大把现成例子,于是基于go现有api分分钟实现一对加密解密函数,你想得没错,一跑就失败,好了不废话了,go的aes-cbc实现由两个限制 1:面临 阅读全文
posted @ 2018-10-25 20:24 啊汉 阅读(13554) 评论(6) 推荐(1) 编辑
摘要: 每次要用PHP的某个功能的时候,都要去查一下,于是决定将PHP所有类和函数都整理出来,加上注释 大致实现 github地址:https://github.com/chentaihan/phpNote a 0 acos 反余弦 1 acosh 反双曲余弦 2 addcslashes 以 C 语言风格使 阅读全文
posted @ 2018-01-27 18:20 啊汉 阅读(3759) 评论(0) 推荐(0) 编辑
摘要: 前几天看到这样一篇博客《那些年·我们读过的专业书籍》,里面列了很多大家认为很好的书,加上自己在自学C++的工程中也看了不少书,感觉并不是所有的书都值得花时间去看的,毕竟很多人一年下来也看不了2,3本书,不同的技术能力的人,适合看的书都不太一样,在这么多大家都认为是经典的书中,选出几本真正适合自己的才... 阅读全文
posted @ 2013-12-26 11:32 啊汉 阅读(22638) 评论(60) 推荐(31) 编辑
摘要: 之前有一个问题一直困扰着我,就是一个变量出了作用域,我以为这个变量的内存就被回收了,其实不是这样的,昨天问了一个高手,才豁然开朗,自己在看相关代码的反汇编代码,才知道原来真是这样就。这个问题,我想简单的说一下内存的分配VS回收&构造函数VS析构函数之间的关系。我的疑问:为什么p出了作用域,指向p的ptr还能读到p中arr的内容,难道p出了作用域,还没有析构?下面的内容会解答这个疑问,先说说跟这篇文章有关的内容。可能是因为平时习惯的原因,我们在实例化一个对象的时候,往往是一条语句实现两个功能:1分配内存;2调用构造函数class A{public: A() { i=0;... 阅读全文
posted @ 2013-11-09 09:43 啊汉 阅读(2816) 评论(10) 推荐(1) 编辑
摘要: 在软件开发中,有些对象使用非常频繁,那么我们可以预先在堆中实例化一些对象,我们把维护这些对象的结构叫“内存池”。在需要用的时候,直接从内存池中拿,而不用从新实例化,在要销毁的时候,不是直接free/delete,而是返还给内存池。把那些常用的对象存在内存池中,就不用频繁的分配/回收内存,可以相对减少内存碎片,更重要的是实例化这样的对象更快,回收也更快。当内存池中的对象不够用的时候就扩容。我的内存池实现如下:#pragma once#include templatestruct ProxyT{ ProxyT():next(NULL){} T data; ProxyT* ne... 阅读全文
posted @ 2013-10-28 08:33 啊汉 阅读(8497) 评论(5) 推荐(4) 编辑
摘要: 我相信很多人对构造函数在什么时候产生,以及产生的原因,理解得不是很透彻;更有甚者认为默认构造函数和复制构造函数是一定会产生的,成员变量就应该在初始化参数列表中进行初始化,当然这些是初学者的认识,下面分享一下我的看法。构造函数不负责分配内存,只是在分配好的一块内存中进行赋值操作.这一点我们可以很容易从new/delete与malloc/free的区别中看出来,malloc/free只负责分配内存不负责初始化,而new/delete不仅负责分配内存,如果对象存在相应的够着函数,就会调用相应的构造函数,如果不存在当然就不调用,如int *i=new int[10];int类型没有构造函数,所以new 阅读全文
posted @ 2013-08-25 16:41 啊汉 阅读(2396) 评论(3) 推荐(2) 编辑
摘要: 我们知道通过一个指向之类的父类指针可以调用子类的虚方法,因为子类的方法会覆盖父类同样的方法,通过这个指针可以找到对象实例的地址,通过实例的地址可以找到指向对应方法表的指针,而通过这个方法的名字就可以确定这个方法在方法表中的位置,直接调用就行,在多继承的时候,一个类可能有多个方法表,也就有多个指向这些方法表的指针,一个类有多个父类,怎么通过其中一个父类的指针调用之类的虚方法?其实前面几句话并没有真正说清楚,在单继承中,父类是怎么调用子类的虚方法的,还有多继承又是怎么实现这点的,想知道这些,请认真往下看。我们先看单继承是怎么实现的。先上两个简单的类:#include using namespac. 阅读全文
posted @ 2013-07-25 11:53 啊汉 阅读(3841) 评论(3) 推荐(4) 编辑
摘要: 如果一个类只定义了类名,没定义任何方法和字段,如class A{};那么class A的每个实例占用1个字节的内存,编译器会会在这个其实例中安插一个char,以保证每个A实例在内存中有唯一的地址,如A a,b;&a!=&b。如果一个直接或是间接的继承(不是虚继承)了多个类,如果这个类及其父类像A一样没有方法没有字段,那么这个类的每个实例的大小都是1字节,如果有虚继承,那就不是1字节了,每虚继承一个类,这个类的实例就会多一个指向被虚继承父类的指针。还有一点值得说明的就是像A这样的类,编译器不一定会产生传说中的那6个方法,这些方法只会在需要的时候产生,如class A没有被任何地方 阅读全文
posted @ 2013-07-08 09:13 啊汉 阅读(2890) 评论(2) 推荐(2) 编辑
摘要: 简单介绍一下DataTable。DataTable主要基于表、行、单元格。行用集合包装单元格,表用集合包装行,大致就是这样。DataColumn表示单元格,DataColumn中的字段还挺多的,在实际应用中我们可能只想用它来存一个int型的数据;DataColumnCollection中用一个ArrayList封装DataColumn,表示一些单元格的集合;DataRow直接在DataColumnCollection的基础上提供一些方法,成为行记录。而DataRowCollection则用集合的方式封装DataRow成为表,但它不是以线性、链表等方式,而是基于红黑树RBTree<Data 阅读全文
posted @ 2013-05-31 11:26 啊汉 阅读(6825) 评论(12) 推荐(1) 编辑
摘要: NSQ是一个由Go语言编写的高性能、可扩展且易于部署的实时消息处理平台,专为大规模系统设计。在今天的微服务架构及云计算环境中,NSQ提供了一种优雅而强大的方式来进行异步通信和解耦服务。此篇文章旨在从多个角度深入分析NSQ,助你了解其工作原理、特点以及应用场景。 工作原理 NSQ遵循发布订阅(pub/ 阅读全文
posted @ 2024-01-18 18:20 啊汉 阅读(32) 评论(0) 推荐(0) 编辑
摘要: 删除单链表中值等于XXX的所有元素 不经意间看到了一个不同寻常的实现方法,觉得挺有意思,于是自己实现了一下,代码真的是简单明了跑得还贼快! 好,现在先在脑海中想想,你会怎么实现?这么简单,5秒钟后,你想到了解决方案,于是你决定验证你的思路,请继续往下看 定义链表节点结构如下: type ListNo 阅读全文
posted @ 2019-12-19 13:25 啊汉 阅读(933) 评论(0) 推荐(0) 编辑