主頁 > 資料庫 > 抖音資料采集Frida教程,Java、Interceptor、NativePointer(Function/Callback)使用方法及示例

抖音資料采集Frida教程,Java、Interceptor、NativePointer(Function/Callback)使用方法及示例

2021-01-19 09:05:31 資料庫

抖音資料采集Frida教程,Java、Interceptor、NativePointer(Function/Callback)使用方法及示例

注意,運行以下任何代碼時都需要提前啟動手機中的frida-server檔案,

1.1 Java物件

Java是十分哦不,應該說是極其重要的API,無論是想對so層亦或java層進行攔截,都必須撰寫Java.perform,在使用上面這些API時,應該都已經發現了吧這章我們就來詳細看看`Java`物件都有哪些`API`

1.1.1 Java.available

該函式一般用來判斷當前行程是否加載了JavaVM,DalvikART虛擬機,咱們來看代碼示例!

function frida_Java() {
    Java.perform(function () {
        //作為判斷用
        if(Java.available)
        {
            //注入的邏輯代碼
            console.log("hello java vm");
        }else{
            //未能正常加載JAVA VM
            console.log("error");
        }
    });
}       
setImmediate(frida_Java,0);
輸出如下,
hello java vm

核心注入的邏輯代碼寫在<注入的邏輯代碼>內會非常的安全萬無一失~

1.1.2 Java.androidVersion

顯示android系統版本號

function frida_Java() {
    Java.perform(function () {
        //作為判斷用
        if(Java.available)
        {
            //注入的邏輯代碼
            console.log("",Java.androidVersion);
        }else{
            //未能正常加載JAVA VM
            console.log("error");
        }
    });
}       
setImmediate(frida_Java,0);
輸出如下,
9
因為我的系統版本是9版本~

1.1.3 列舉類Java.enumerateLoadedClasses

該API列舉當前加載的所有類資訊,它有一個回呼函式分別是onMatch、onComplete函式,我們來看看代碼示例以及效果!

function frida_Java() {
    Java.perform(function () {
        if(Java.available)
        {
            //console.log("",Java.androidVersion);
            //列舉當前加載的所有類
            Java.enumerateLoadedClasses({
                //每一次回呼此函式時其引數className就是類的資訊
                onMatch: function (className)
                {
                    //輸出類字串
                    console.log("",className);
                },
                //列舉完畢所有類之后的回呼函式
                onComplete: function ()
                {
                    //輸出類字串
                    console.log("輸出完畢");
                }
            });
        }else{
            console.log("error");
        }
    });
}       
setImmediate(frida_Java,0);

咱們來看執行的效果圖1-7,
image.png
圖1-7 終端執行
它還有一個好兄弟 Java.enumerateLoadedClassesSync(),它回傳的是一個陣列,

1.1.4 列舉類加載器Java.enumerateLoadedClasses

api列舉Java VM中存在的類加載器,其有一個回呼函式,分別是onMatch: function (loader)onComplete: function (),接著我們來看代碼示例,

function frida_Java() {
    Java.perform(function () {
        if(Java.available)
        {
            //列舉當前加載的Java VM類加載器
            Java.enumerateClassLoaders({
                //回呼函式,引數loader是類加載的資訊
                onMatch: function (loader)
                {
                    console.log("",loader);
                },
                //列舉完畢所有類加載器之后的回呼函式
                onComplete: function ()
                {
                    console.log("end");
                }
            });
        }else{
            console.log("error");
        }
    });
}       
setImmediate(frida_Java,0);

執行的效果圖1-8,
image.png
圖1-8 終端執行
它也有一個好兄弟叫Java.enumerateClassLoadersSync()也是回傳的陣列,

1.1.5 附加呼叫Java.perform

API極其重要,Java.perform(fn)主要用于當前執行緒附加到Java VM并且呼叫fn方法,我們來看看示例代碼及其含義,

function frida_Java() {
    //運行當前js腳本時會對當前執行緒附加到Java VM虛擬機,并且執行function方法
    Java.perform(function () {
        //判斷是否Java VM正常運行
        if(Java.available)
        {
            //如不意外會直接輸出 hello
            console.log("hello");
        }else{
            console.log("error");
        }
    });
}       
setImmediate(frida_Java,0);
輸出如下,
[Google Pixel::com.roysue.roysueapplication]-> hello

沒錯你猜對了,它也有一個好兄弟,Java.performNow(fn)~

1.1.6 獲取類Java.use

Java.use(className),動態獲取className的類定義,通過對其呼叫$new()來呼叫建構式,可以從中實體化物件,當想要回收類時可以呼叫$Dispose()方法顯式釋放,當然也可以等待JavaScript的垃圾回識訓制,當實體化一個物件之后,可以通過其實體物件呼叫類中的靜態或非靜態的方法,官方代碼示例定義如下,

Java.perform(function () {
  //獲取android.app.Activity類
  var Activity = Java.use('android.app.Activity');
  //獲取java.lang.Exception類
  var Exception = Java.use('java.lang.Exception');
  //攔截Activity類的onResume方法
  Activity.onResume.implementation = function () {
    //呼叫onResume方法的時候,會在此處被攔截并且呼叫以下代碼拋出例外!
    throw Exception.$new('Oh noes!');
  };
});

1.1.7 掃描實體類Java.choose

在堆上查找實體化的物件,示例代碼如下!

Java.perform(function () {
    //查找android.view.View類在堆上的實體化物件
    Java.choose("android.view.View", {
        //列舉時呼叫
        onMatch:function(instance){
            //列印實體
            console.log(instance);
        },
        //列舉完成后呼叫
        onComplete:function() {
            console.log("end")
        }});
});
輸出如下:
android.view.View{2292774 V.ED..... ......ID 0,1794-1080,1920 #1020030 android:id/navigationBarBackground}
android.view.View{d43549d V.ED..... ......ID 0,0-1080,63 #102002f android:id/statusBarBackground}
end

1.1.8 型別轉換器Java.cast

Java.cast(handle, klass),就是將指定變數或者資料強制轉換成你所有需要的型別;創建一個 JavaScript 包裝器,給定從 Java.use() 回傳的給定類klas的句柄的現有實體,此類包裝器還具有用于獲取其類的包裝器的類屬性,以及用于獲取其類名的字串表示的$className屬性,通常在攔截so層時會使用此函式將jstring、jarray等等轉換之后查看其值,

1.1.9 定義任意陣列型別Java.array

frida提供了在js代碼中定義java陣列的api,該陣列可以用于傳遞給java API,我們來看看如何定義,代碼示例如下,

Java.perform(function () {
        //定義一個int陣列、值是1003, 1005, 1007
        var intarr = Java.array('int', [ 1003, 1005, 1007 ]);
        //定義一個byte陣列、值是0x48, 0x65, 0x69
        var bytearr = Java.array('byte', [ 0x48, 0x65, 0x69 ]);
        for(var i=0;i<bytearr.length;i++)
        {
            //輸出每個byte元素
            console.log(bytearr[i])
        }
});

我們通過上面定義int陣列和byte的例子可以知道其定義格式為Java.array('type',[value1,value2,....]);那它都支持type呢?我們來看看~

type 含義
Z boolean
B byte
C char
S short
I int
J long
F float
D double
V void

1.1.10 注冊類Java.registerClass(spec)

Java.registerClass:創建一個新的Java類并回傳一個包裝器,其中規范是一個包含:
name:指定類名稱的字串,
superClass:(可選)父類,要從 java.lang.Object 繼承的省略,
implements:(可選)由此類實作的介面陣列,
fields:(可選)物件,指定要公開的每個欄位的名稱和型別,
methods:(可選)物件,指定要實作的方法,
注冊一個類,回傳類的實體,下面我貼一個基本的用法~實體化目標類物件并且呼叫類中的方法

Java.perform(function () {
          //注冊一個目標行程中的類,回傳的是一個類物件
          var hellojni = Java.registerClass({
            name: 'com.roysue.roysueapplication.hellojni'
          });
          console.log(hellojni.addInt(1,2));
});

我們再深入看看官方怎么來玩的:

//獲取目標行程的SomeBaseClass類
var SomeBaseClass = Java.use('com.example.SomeBaseClass');
//獲取目標行程的X509TrustManager類
var X509TrustManager = Java.use('javax.net.ssl.X509TrustManager');
var MyWeirdTrustManager = Java.registerClass({
  //注冊一個類是行程中的MyWeirdTrustManager類
  name: 'com.example.MyWeirdTrustManager',
  //父類是SomeBaseClass類
  superClass: SomeBaseClass,
  //實作了MyWeirdTrustManager介面類
  implements: [X509TrustManager],
  //類中的屬性
  fields: {
    description: 'java.lang.String',
    limit: 'int',
  },
  //定義的方法
  methods: {
    //類的建構式
    $init: function () {
      console.log('Constructor called');
    },
    //X509TrustManager介面中方法之一,該方法作用是檢查客戶端的證書
    checkClientTrusted: function (chain, authType) {
      console.log('checkClientTrusted');
    },
    //該方法檢查服務器的證書,不信任時,在這里通過自己實作該方法,可以使之信任我們指定的任何證書,在實作該方法時,也可以簡單的不做任何處理,即一個空的函式體,由于不會拋出例外,它就會信任任何證書,
    checkServerTrusted: [{
      //回傳值型別
      returnType: 'void',
      //引數串列
      argumentTypes: ['[Ljava.security.cert.X509Certificate;', 'java.lang.String'],
      //實作方法
      implementation: function (chain, authType) {
         //輸出
        console.log('checkServerTrusted A');
      }
    }, {
      returnType: 'java.util.List',
      argumentTypes: ['[Ljava.security.cert.X509Certificate;', 'java.lang.String', 'java.lang.String'],
      implementation: function (chain, authType, host) {
        console.log('checkServerTrusted B');
        //回傳null會信任所有證書
        return null;
      }
    }],
    // 回傳受信任的X509證書陣列,
    getAcceptedIssuers: function () {
      console.log('getAcceptedIssuers');
      return [];
    },
  }
});

我們來看看上面的示例都做了啥?實作了證書類的javax.net.ssl.X509TrustManager類,,這里就是相當于自己在目標行程中重新創建了一個類,實作了自己想要實作的類構造,重構造了其中的三個介面函式、從而繞過證書校驗,

1.1.11 Java.vm物件

Java.vm物件十分常用,比如想要拿到JNI層的JNIEnv物件,可以使用getEnv();我們來看看具體的使用和基本小實體,~

function frida_Java() {     
    Java.perform(function () {
         //攔截getStr函式
         Interceptor.attach(Module.findExportByName("libhello.so" , "Java_com_roysue_roysueapplication_hellojni_getStr"), {
            onEnter: function(args) {
                console.log("getStr");
            },
            onLeave:function(retval){
                //它的回傳值的是retval 在jni層getStr的回傳值的jstring 
                //我們在這里做的事情就是替換掉結果
                //先獲取一個Env物件
                var env = Java.vm.getEnv();
                //通過newStringUtf方法構建一個jstirng字串
                var jstring = env.newStringUtf('roysue');
                //replace替換掉結果
                retval.replace(jstring);
                console.log("getSum方法回傳值為:roysue")
            }
    });
}
setImmediate(frida_Java,0);

1.2 Interceptor物件

該物件功能十分強大,函式原型是Interceptor.attach(target, callbacks):引數target是需要攔截的位置的函式地址,也就是填某個so層函式的地址即可對其攔截,target是一個NativePointer引數,用來指定你想要攔截的函式的地址,NativePointer我們也學過是一個指標,需要注意的是對于Thumb函式需要對函式地址+1callbacks則是它的回呼函式,分別是以下兩個回呼函式:

1.2.1 Interceptor.attach

onEnter:函式(args):回呼函式,給定一個引數args,可用于讀取或寫入引數作為 NativePointer 物件的陣列,
onLeave:函式(retval):回呼函式給定一個引數 retval,該引數是包含原始回傳值的 NativePointer 派生物件,可以呼叫 retval.replace(1337) 以整數 1337 替換回傳值,或者呼叫 retval.replace(ptr("0x1234"))以替換為指標,請注意,此物件在 OnLeave 呼叫中回收,因此不要將其存盤在回呼之外并使用它,如果需要存盤包含的值,請制作深副本,例如:ptr(retval.toString())
我們來看看示例代碼~

//使用Module物件getExportByNameAPI直接獲取libc.so中的匯出函式read的地址,對read函式進行附加攔截
Interceptor.attach(Module.getExportByName('libc.so', 'read'), {
  //每次read函式呼叫的時候會執行onEnter回呼函式
  onEnter: function (args) {
    this.fileDescriptor = args[0].toInt32();
  },
  //read函式執行完成之后會執行onLeave回呼函式
  onLeave: function (retval) {
    if (retval.toInt32() > 0) {
      /* do something with this.fileDescriptor */
    }
  }
});

通過我們對Interceptor.attach函式有一些基本了解了~它還包含一些屬性
我們來看看示例代碼,

function frida_Interceptor() {
    Java.perform(function () {
        //對So層的匯出函式getSum進行攔截
        Interceptor.attach(Module.findExportByName("libhello.so" , "Java_com_roysue_roysueapplication_hellojni_getSum"), {
            onEnter: function(args) {
                //輸出
                console.log('Context information:');
                //輸出背景關系因其是一個Objection物件,需要它進行接送、轉換才能正常看到值
                console.log('Context  : ' + JSON.stringify(this.context));
                //輸出回傳地址
                console.log('Return   : ' + this.returnAddress);
                //輸出執行緒id
                console.log('ThreadId : ' + this.threadId);
                console.log('Depth    : ' + this.depth);
                console.log('Errornr  : ' + this.err);
            },
            onLeave:function(retval){
            }
        });
    });
}
setImmediate(frida_Interceptor,0);


我們注入腳本之后來看看執行之后的效果以及輸出的這些都是啥,執行的效果圖1-9
image.png
圖1-9 終端執行

1.2.2 Interceptor.detachAll

簡單來說這個的函式的作用就是讓之前所有的Interceptor.attach附加攔截的回呼函式失效,

1.2.3 Interceptor.replace

相當于替換掉原本的函式,用替換時的實作替換目標處的函式,如果想要完全或部分替換現有函式的實作,則通常使用此函式,,我們也看例子,例子是最直觀的!代碼如下,

function frida_Interceptor() {
    Java.perform(function () {
       //這個c_getSum方法有兩個int引數、回傳結果為兩個引數相加
       //這里用NativeFunction函式自己定義了一個c_getSum函式
       var add_method = new NativeFunction(Module.findExportByName('libhello.so', 'c_getSum'), 
       'int',['int','int']);
       //輸出結果 那結果肯定就是 3
       console.log("result:",add_method(1,2));
       //這里對原函式的功能進行替換實作
       Interceptor.replace(add_method, new NativeCallback(function (a, b) {
           //h不論是什么引數都回傳123
            return 123;
       }, 'int', ['int', 'int']));
       //再次呼叫 則回傳123
       console.log("result:",add_method(1,2));
    });
}

我來看注入腳本之后的終端是是不是顯示了3123見下圖1-10
image.png
圖1-10 終端執行

1.3 NativePointer物件

同等與C語言中的指標

1.3.1 new NativePointer(s)

宣告定義NativePointer型別

function frida_NativePointer() {
    Java.perform(function () {
        //第一種字串定義方式 十進制的100 輸出為十六進制0x64
        const ptr1 = new NativePointer("100");
        console.log("ptr1:",ptr1);
        //第二種字串定義方式 直接定義0x64 同等與定義十六進制的64
        const ptr2 = new NativePointer("0x64");
        console.log("ptr2:",ptr2);        
        //第三種定數值義方式 定義數字int型別 十進制的100 是0x64
        const ptr3 = new NativePointer(100);
        console.log("ptr3:",ptr3);
    });
}     
setImmediate(frida_NativePointer,0);
輸出如下,都會自動轉為十六進制的0x64
ptr1: 0x64
ptr2: 0x64
ptr3: 0x64

1.3.2 運算子以及指標讀寫API

它也能呼叫以下運算子


看完API含義之后,我們來使用他們,下面該腳本是readByteArray()示例~

function frida_NativePointer() {
    Java.perform(function () {
       console.log("");
        //拿到libc.so在記憶體中的地址
        var pointer = Process.findModuleByName("libc.so").base;
        //讀取從pointer地址開始的16個位元組
        console.log(pointer.readByteArray(0x10));
    });
}     
setImmediate(frida_NativePointer,0);
輸出如下:
           0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F  0123456789ABCDEF
00000000  7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00  .ELF............

首先我先來用readByteArray函式來讀取libc.so檔案在記憶體中的資料,這樣我們方便測驗,我們從libc檔案讀取0x10個位元組的長度,肯定會是7F 45 4C 46...因為ELF檔案頭部資訊中的Magic屬性,

1.3.3 readPointer()

咱們直接從API索引11開始玩readPointer(),定義是從此記憶體位置讀取NativePointer,示例代碼如下,省略function以及Java.perform~

var pointer = Process.findModuleByName("libc.so").base;
    console.log(pointer.readByteArray(0x10));
    console.log("readPointer():"+pointer.readPointer());
    輸出如下,
    readPointer():0x464c457f

也就是將readPointer的前四個位元組的內容轉成地址產生一個新的NativePointer

1.3.4 writePointer(ptr)

讀取ptr指標地址到當前指標

//先列印pointer指標地址
        console.log("pointer :"+pointer);
        //分配四個位元組的空間地址
        const r = Memory.alloc(4);
        //將pointer指標寫入剛剛申請的r內
        r.writePointer(pointer);
        //讀取r指標的資料
        var buffer = Memory.readByteArray(r, 4);
        //r指標內放的pointer指標地址
        console.log(buffer);
輸出如下,
//console.log("pointer :"+pointer); 這句列印的地址 也就是libc的地址
pointer :0xf588f000
//console.log(buffer); 輸出buffer 0xf588f000在記憶體資料會以00 f0 88 f5方式顯示
           0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F  0123456789ABCDEF
00000000  00 f0 88 f5                                      ....

1.3.5 readS32()、readU32()

從該記憶體位置讀取有符號或無符號8/16/32/etc或浮點數/雙精度值,并將其作為數字回傳,這里拿readS32()、readU32()作為演示.

//從pointer地址讀4個位元組 有符號
    console.log(pointer.readS32());
    //從pointer地址讀4個位元組 無符號
    console.log(pointer.readU32());
輸出如下,
           0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F  0123456789ABCDEF
00000000  7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00  .ELF............
1179403647 == 0x464c457f
1179403647 == 0x464c457f

1.3.6 writeS32()、writeU32()

將有符號或無符號8/16/32/等或浮點數/雙精度值寫入此記憶體位置,

//申請四個位元組的記憶體空間
    const r = Memory.alloc(4);
    //將0x12345678寫入r地址中
    r.writeS32(0x12345678);
    //輸出
    console.log(r.readByteArray(0x10));
// writeS32()、writeU32()輸出的也是一樣的,只是區別是有符號和無符號
輸出如下,
           0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F  0123456789ABCDEF
00000000  78 56 34 12 00 00 00 00 00 00 00 00 00 00 00 00  xV4.............

1.3.7 readByteArray(length))、writeByteArray(bytes)

readByteArray(length))連續讀取記憶體length個位元組,、writeByteArray連續寫入記憶體bytes

//先定義一個需要寫入的位元組陣列
       var arr = [ 0x72, 0x6F, 0x79, 0x73, 0x75, 0x65];
       //這里申請以arr大小的記憶體空間
       const r = Memory.alloc(arr.length);
       //將arr陣列位元組寫入r
       Memory.writeByteArray(r,arr);
       //讀取arr.length大小的陣列
       var buffer = Memory.readByteArray(r, arr.length);
       console.log("Memory.readByteArray:");
       console.log(hexdump(buffer, {
            offset: 0,
            length: arr.length,
            header: true,
            ansi: false
        }));
輸出如下,       
Memory.readByteArray:
           0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F  0123456789ABCDEF
00000000  72 6f 79 73 75 65                                roysue

1.3.8 readCString([size = -1])、writeUtf8String(str)

readCString功能是讀取指標地址位置的位元組字串,對應的writeUtf8String是寫入指標地址位置的字串處,(這里的r是接著上面的代碼的變數),

//在這里直接使用readCString讀取會把上面的'roysue'字串讀取出來
        console.log("readCString():"+r.readCString());
        //這里是寫入字串 也就是 roysue起始位置開始被替換為haha
        const newPtrstr = r.writeUtf8String("haha");
        //替換完了之后再繼續輸出 必然是haha
        console.log("readCString():"+newPtrstr.readCString());


圖1-11 終端執行

1.4 NativeFunction物件

創建新的NativeFunction以呼叫address處的函式(用NativePointer指定),其中rereturn Type指定回傳型別,argTypes陣列指定引數型別,如果不是系統默認值,還可以選擇指定ABI,對于可變函式,添加一個‘.’固定引數和可變引數之間的argTypes條目,我們來看看官方的例子,

// LargeObject HandyClass::friendlyFunctionName();
//創建friendlyFunctionPtr地址的函式
var friendlyFunctionName = new NativeFunction(friendlyFunctionPtr,
    'void', ['pointer', 'pointer']);
//申請記憶體空間    
var returnValue = https://www.cnblogs.com/titodata/archive/2021/01/18/Memory.alloc(sizeOfLargeObject);
//呼叫friendlyFunctionName函式
friendlyFunctionName(returnValue, thisPtr);

我來看看它的格式,函式定義格式為new NativeFunction(address, returnType, argTypes[, options]),參照這個格式能夠創建函式并且呼叫!returnType和argTypes[,]分別可以填void、pointer、int、uint、long、ulong、char、uchar、float、double、int8、uint8、int16、uint16、int32、uint32、int64、uint64這些型別,根據函式的所需要的type來定義即可,
在定義的時候必須要將引數型別個數和引數型別以及回傳值完全匹配,假設有三個引數都是int,則new NativeFunction(address, returnType, ['int', 'int', 'int']),而回傳值是intnew NativeFunction(address, 'int', argTypes[, options]),必須要全部匹配,并且第一個引數一定要是函式地址指標,

1.5 NativeCallback物件

new NativeCallback(func,rereturn Type,argTypes[,ABI]):創建一個由JavaScript函式func實作的新NativeCallback,其中rereturn Type指定回傳型別,argTypes陣列指定引數型別,您還可以指定ABI(如果不是系統默認值),有關支持的型別和Abis的詳細資訊,請參見NativeFunction,注意,回傳的物件也是一個NativePointer,因此可以傳遞給Interceptor#replace,當將產生的回呼與Interceptor.replace()一起使用時,將呼叫func,并將其系結到具有一些有用屬性的物件,就像Interceptor.Attach()中的那樣,我們來看一個例子,如下,利用NativeCallback做一個函式替換,

Java.perform(function () {
       var add_method = new NativeFunction(Module.findExportByName('libhello.so', 'c_getSum'), 
       'int',['int','int']);
       console.log("result:",add_method(1,2));
       //在這里new一個新的函式,但是引數的個數和回傳值必須對應
       Interceptor.replace(add_method, new NativeCallback(function (a, b) {
            return 123;
       }, 'int', ['int', 'int']));
       console.log("result:",add_method(1,2));
    });

結語

本篇咱們學習了非常實用的API,如Interceptor物件對so層匯出庫函式攔截、NativePointer物件的指標操作、NativeFunction物件的實體化so函式的使用等都是當前灰常好用的函式建議童鞋了多多嘗試

短視頻、直播資料實時采集介面,請查看檔案: TiToData


免責宣告:本檔案僅供學習與參考,請勿用于非法用途!否則一切后果自負,

轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/250591.html

標籤:其他

上一篇:與HBase對比,Cassandra的優勢特性是什么?

下一篇:基于業務和平臺理解數字營銷概念

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • GPU虛擬機創建時間深度優化

    **?桔妹導讀:**GPU虛擬機實體創建速度慢是公有云面臨的普遍問題,由于通常情況下創建虛擬機屬于低頻操作而未引起業界的重視,實際生產中還是存在對GPU實體創建時間有苛刻要求的業務場景。本文將介紹滴滴云在解決該問題時的思路、方法、并展示最終的優化成果。 從公有云服務商那里購買過虛擬主機的資深用戶,一 ......

    uj5u.com 2020-09-10 06:09:13 more
  • 可編程網卡芯片在滴滴云網路的應用實踐

    **?桔妹導讀:**隨著云規模不斷擴大以及業務層面對延遲、帶寬的要求越來越高,采用DPDK 加速網路報文處理的方式在橫向縱向擴展都出現了局限性。可編程芯片成為業界熱點。本文主要講述了可編程網卡芯片在滴滴云網路中的應用實踐,遇到的問題、帶來的收益以及開源社區貢獻。 #1. 資料中心面臨的問題 隨著滴滴 ......

    uj5u.com 2020-09-10 06:10:21 more
  • 滴滴資料通道服務演進之路

    **?桔妹導讀:**滴滴資料通道引擎承載著全公司的資料同步,為下游實時和離線場景提供了必不可少的源資料。隨著任務量的不斷增加,資料通道的整體架構也隨之發生改變。本文介紹了滴滴資料通道的發展歷程,遇到的問題以及今后的規劃。 #1. 背景 資料,對于任何一家互聯網公司來說都是非常重要的資產,公司的大資料 ......

    uj5u.com 2020-09-10 06:11:05 more
  • 滴滴AI Labs斬獲國際機器翻譯大賽中譯英方向世界第三

    **桔妹導讀:**深耕人工智能領域,致力于探索AI讓出行更美好的滴滴AI Labs再次斬獲國際大獎,這次獲獎的專案是什么呢?一起來看看詳細報道吧! 近日,由國際計算語言學協會ACL(The Association for Computational Linguistics)舉辦的世界最具影響力的機器 ......

    uj5u.com 2020-09-10 06:11:29 more
  • MPP (Massively Parallel Processing)大規模并行處理

    1、什么是mpp? MPP (Massively Parallel Processing),即大規模并行處理,在資料庫非共享集群中,每個節點都有獨立的磁盤存盤系統和記憶體系統,業務資料根據資料庫模型和應用特點劃分到各個節點上,每臺資料節點通過專用網路或者商業通用網路互相連接,彼此協同計算,作為整體提供 ......

    uj5u.com 2020-09-10 06:11:41 more
  • 滴滴資料倉庫指標體系建設實踐

    **桔妹導讀:**指標體系是什么?如何使用OSM模型和AARRR模型搭建指標體系?如何統一流程、規范化、工具化管理指標體系?本文會對建設的方法論結合滴滴資料指標體系建設實踐進行解答分析。 #1. 什么是指標體系 ##1.1 指標體系定義 指標體系是將零散單點的具有相互聯系的指標,系統化的組織起來,通 ......

    uj5u.com 2020-09-10 06:12:52 more
  • 單表千萬行資料庫 LIKE 搜索優化手記

    我們經常在資料庫中使用 LIKE 運算子來完成對資料的模糊搜索,LIKE 運算子用于在 WHERE 子句中搜索列中的指定模式。 如果需要查找客戶表中所有姓氏是“張”的資料,可以使用下面的 SQL 陳述句: SELECT * FROM Customer WHERE Name LIKE '張%' 如果需要 ......

    uj5u.com 2020-09-10 06:13:25 more
  • 滴滴Ceph分布式存盤系統優化之鎖優化

    **桔妹導讀:**Ceph是國際知名的開源分布式存盤系統,在工業界和學術界都有著重要的影響。Ceph的架構和演算法設計發表在國際系統領域頂級會議OSDI、SOSP、SC等上。Ceph社區得到Red Hat、SUSE、Intel等大公司的大力支持。Ceph是國際云計算領域應用最廣泛的開源分布式存盤系統, ......

    uj5u.com 2020-09-10 06:14:51 more
  • es~通過ElasticsearchTemplate進行聚合~嵌套聚合

    之前寫過《es~通過ElasticsearchTemplate進行聚合操作》的文章,這一次主要寫一個嵌套的聚合,例如先對sex集合,再對desc聚合,最后再對age求和,共三層嵌套。 Aggregations的部分特性類似于SQL語言中的group by,avg,sum等函式,Aggregation ......

    uj5u.com 2020-09-10 06:14:59 more
  • 爬蟲日志監控 -- Elastc Stack(ELK)部署

    傻瓜式部署,只需替換IP與用戶 導讀: 現ELK四大組件分別為:Elasticsearch(核心)、logstash(處理)、filebeat(采集)、kibana(可視化) 下載均在https://www.elastic.co/cn/downloads/下tar包,各組件版本最好一致,配合fdm會 ......

    uj5u.com 2020-09-10 06:15:05 more
最新发布
  • day02-2-商鋪查詢快取

    功能02-商鋪查詢快取 3.商鋪詳情快取查詢 3.1什么是快取? 快取就是資料交換的緩沖區(稱作Cache),是存盤資料的臨時地方,一般讀寫性能較高。 快取的作用: 降低后端負載 提高讀寫效率,降低回應時間 快取的成本: 資料一致性成本 代碼維護成本 運維成本 3.2需求說明 如下,當我們點擊商店詳 ......

    uj5u.com 2023-04-20 08:33:24 more
  • MySQL中binlog備份腳本分享

    關于MySQL的二進制日志(binlog),我們都知道二進制日志(binlog)非常重要,尤其當你需要point to point災難恢復的時侯,所以我們要對其進行備份。關于二進制日志(binlog)的備份,可以基于flush logs方式先切換binlog,然后拷貝&壓縮到到遠程服務器或本地服務器 ......

    uj5u.com 2023-04-20 08:28:06 more
  • day02-短信登錄

    功能實作02 2.功能01-短信登錄 2.1基于Session實作登錄 2.1.1思路分析 2.1.2代碼實作 2.1.2.1發送短信驗證碼 發送短信驗證碼: 發送驗證碼的介面為:http://127.0.0.1:8080/api/user/code?phone=xxxxx<手機號> 請求方式:PO ......

    uj5u.com 2023-04-20 08:27:27 more
  • 快取與資料庫雙寫一致性幾種策略分析

    本文將對幾種快取與資料庫保證資料一致性的使用方式進行分析。為保證高并發性能,以下分析場景不考慮執行的原子性及加鎖等強一致性要求的場景,僅追求最終一致性。 ......

    uj5u.com 2023-04-20 08:26:48 more
  • sql陳述句優化

    問題查找及措施 問題查找 需要找到具體的代碼,對其進行一對一優化,而非一直把關注點放在服務器和sql平臺 降低簡化每個事務中處理的問題,盡量不要讓一個事務拖太長的時間 例如檔案上傳時,應將檔案上傳這一步放在事務外面 微軟建議 4.啟動sql定時執行計劃 怎么啟動sqlserver代理服務-百度經驗 ......

    uj5u.com 2023-04-20 08:26:35 more
  • 云時代,MySQL到ClickHouse資料同步產品對比推薦

    ClickHouse 在執行分析查詢時的速度優勢很好的彌補了MySQL的不足,但是對于很多開發者和DBA來說,如何將MySQL穩定、高效、簡單的同步到 ClickHouse 卻很困難。本文對比了 NineData、MaterializeMySQL(ClickHouse自帶)、Bifrost 三款產品... ......

    uj5u.com 2023-04-20 08:26:29 more
  • sql陳述句優化

    問題查找及措施 問題查找 需要找到具體的代碼,對其進行一對一優化,而非一直把關注點放在服務器和sql平臺 降低簡化每個事務中處理的問題,盡量不要讓一個事務拖太長的時間 例如檔案上傳時,應將檔案上傳這一步放在事務外面 微軟建議 4.啟動sql定時執行計劃 怎么啟動sqlserver代理服務-百度經驗 ......

    uj5u.com 2023-04-20 08:25:13 more
  • Redis 報”OutOfDirectMemoryError“(堆外記憶體溢位)

    Redis 報錯“OutOfDirectMemoryError(堆外記憶體溢位) ”問題如下: 一、報錯資訊: 使用 Redis 的業務介面 ,產生 OutOfDirectMemoryError(堆外記憶體溢位),如圖: 格式化后的報錯資訊: { "timestamp": "2023-04-17 22: ......

    uj5u.com 2023-04-20 08:24:54 more
  • day02-2-商鋪查詢快取

    功能02-商鋪查詢快取 3.商鋪詳情快取查詢 3.1什么是快取? 快取就是資料交換的緩沖區(稱作Cache),是存盤資料的臨時地方,一般讀寫性能較高。 快取的作用: 降低后端負載 提高讀寫效率,降低回應時間 快取的成本: 資料一致性成本 代碼維護成本 運維成本 3.2需求說明 如下,當我們點擊商店詳 ......

    uj5u.com 2023-04-20 08:24:03 more
  • day02-短信登錄

    功能實作02 2.功能01-短信登錄 2.1基于Session實作登錄 2.1.1思路分析 2.1.2代碼實作 2.1.2.1發送短信驗證碼 發送短信驗證碼: 發送驗證碼的介面為:http://127.0.0.1:8080/api/user/code?phone=xxxxx<手機號> 請求方式:PO ......

    uj5u.com 2023-04-20 08:23:11 more